Inleiding
Relationele databases volgen de ACID-eigenschappen in de manier waarop ze transacties implementeren:atoomkracht, consistentie, isolatie en duurzaamheid. Isolatie is nodig om ervoor te zorgen dat meerdere transacties geen wijzigingen in gegevens kunnen veroorzaken en de uiteindelijke resultaten inconsistent laten. Om te garanderen dat de bewerkingen geïsoleerd blijven, past SQL Server vergrendelingsmechanismen toe.
Vergrendelingsmodi en hiërarchie
Het mechanisme van SQL Server voor gelijktijdigheidscontrole is hierbij betrokken. Om de prestaties te optimaliseren in termen van wachttijden voor vergrendelingen, deadlocks en dergelijke, moet u een beslissing nemen op basis van het specifieke scenario.
In SQL Server kunnen vergrendelingen op verschillende manieren en op verschillende granulariteitsniveaus worden vastgehouden. Lock Modes zijn de specifieke manieren om dit te doen, en hun niveaus zijn Lock Hiërarchie.
Afbeelding 1 toont de vergrendelingsmodi die beschikbaar zijn in SQL Server voor het standaard transactie-isolatieniveau (LEES TOEGANG):
Overzicht van escalatie van vergrendeling
SQL Server kan resources op verschillende niveaus vergrendelen. Het hangt af van de meest efficiënte handelingen naargelang de aard van de werklast. Tabel 1 toont de bronnen die kunnen worden vergrendeld.
- Vergrendelingen op een gedetailleerder niveau (bijvoorbeeld vergrendelingen op rijniveau) zorgen voor meer gelijktijdigheid en minder blokkering.
- Vergrendelingen op een hoger niveau (bijvoorbeeld Table Level Lock) verminderen gelijktijdigheid. Ze kunnen meer blokkering veroorzaken, afhankelijk van hoe lang de feitelijke verklaring duurt.
SQL Server kiest het benodigde vergrendelingsniveau op basis van interne statistieken.
Een Lock Escalation vindt plaats wanneer een lock wordt omgezet van een fijner niveau van granulariteit naar een grover niveau.
Bijvoorbeeld een rijvergrendeling omzetten in een tafelvergrendeling (zie tabel 1).
Bron | Beschrijving |
RID | De rij-ID die wordt gebruikt om een enkele rij binnen een heap te vergrendelen. |
SLEUTEL | De rijvergrendeling binnen een index die wordt gebruikt om sleutelbereiken in serialiseerbare transacties te beschermen. |
PAGINA | De pagina van 8 kilobyte (KB) in een database, zoals gegevens- of indexpagina's. |
EXTENT | De aaneengesloten groep van acht pagina's, zoals gegevens- of indexpagina's. |
HoBT | De hoop of B-boom. Het slot beschermt een B-tree (index) of de heap-gegevenspagina's in een tabel die geen geclusterde index heeft. |
TABEL | De hele tabel, inclusief alle gegevens en indexen. |
BESTAND | Het databasebestand. |
TOEPASSING | De door de applicatie gespecificeerde bron. |
METADATA | Metagegevens worden vergrendeld. |
ALLOCATION_UNIT | De toewijzingseenheid. |
DATABASE | De volledige database. |
De reden voor escalatie van sloten
Sloten in SQL Server kunnen behoorlijk duur zijn. Voor elk slot dat de Lock Manager verwerft, moet SQL Server geheugen reserveren - 64 bytes of 128 bytes. Het bedrag hangt af van of we te maken hebben met respectievelijk een 32-bits of 64-bits systeem.
Naarmate het aantal rijvergrendelingen op een tabel toeneemt, moet SQL Server steeds meer geheugen krijgen. Vandaar dat andere processen verhongeren, geen geheugen meer hebben.
Het is logisch om rijvergrendelingen en paginavergrendelingen om te zetten in een enkele tabel (object) niveauvergrendeling. Het gebeurt wanneer het aantal sloten voor die tafel de 5000 overschrijdt.
Het compromis treedt op wanneer de hele tafel niet langer beschikbaar is voor andere sessies in het transactieproces.
Slotescalatie demonstreren
We kunnen Lock Escalation demonstreren met behulp van de code in Listing 1.
Laten we de tafel eerst een beetje beschrijven. Production.ProductsI is een relatief kleine tafel met ongeveer 7777 rijen. De bouwelementen zijn dezelfde set van 77 rijen, 101 keer gedupliceerd. De Code in Listing 1 bestaat uit drie versies van dezelfde update-verklaring, elk ingesloten in een transactie.
-- Listing 1: Demonstrating Lock Escalation
-- Update very few rows
BEGIN TRAN
use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice='18.00';
ROLLBACK
-- Update a large number of rows
BEGIN TRAN
use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice>'18.00';
ROLLBACK
-- Update over 5000 rows
BEGIN TRAN
use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00';
ROLLBACK
Voor meer duidelijkheid zullen we de inhoud van Listing 1 opsplitsen.
Laten we eerst eens kijken naar Listing 2 - een query om de vergrendelingen in de TSQLV4-database weer te geven.
Onze eerste actie is het uitvoeren van listing 1a. Vervolgens gebruiken we Listing 2 om te onderzoeken hoe de Lock Manager vergrendeling uitvoert in het scenario. We voeren Listing 1a uit zonder de rollback-verklaring af te geven. Op deze manier bewaren we de sloten lang genoeg, zodat de zoekopdracht in Listing 2 ze kan vastleggen.
-- Listing 1a: Demonstrating Lock Escalation
-- Update very few rows
BEGIN TRAN
use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice='18.00';
ROLLBACK
-- Listing 2: Displaying Locks Held in Database TSQLV4
USE TSQLV4
GO
SELECT
resource_type
, DB_NAME (resource_database_id) database_name
--, OBJECT_NAME(resource_associated_entity_id) resource_name
, request_mode
, request_type
, request_status
, request_reference_count
, request_session_id
, resource_associated_entity_id
, OBJECT_NAME(resource_associated_entity_id) [object_name] --small obj ids
, getuser.login_name
FROM sys.dm_tran_locks
CROSS APPLY dmv.dbo.getuser(request_session_id) as getuser
WHERE DB_NAME (resource_database_id)='TSQLV4';
Wanneer we de query in Listing 1a uitvoeren en vervolgens de vergrendelingen controleren met behulp van de query in Listing 2, retourneert SQL Server het resultaat dat wordt getoond in Afbeelding 2.
404 rijen in de tabel hebben unitprice=’18.00’ . De Lock Manager vergrendelt deze rijen samen met de andere sloten van elk gewenst niveau. Het brengt het aantal rijen van Figuur 2 op 467.
-- Listing 1b: Demonstrating Lock Escalation
-- Update a large number of rows
BEGIN TRAN
use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice>'18.00';
ROLLBACK
We observeren soortgelijk gedrag wanneer we de query in Listing 1b uitvoeren. Deze keer hebben we te maken met 4406 rijen. Het geeft het aantal rijen op tafel Production.ProductI weer met eenheidsprijs>18,00.
-- Listing 1c: Demonstrating Lock Escalation
-- Update over 5000 rows
BEGIN TRAN
use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00';
ROLLBACK
Als we verder gaan en de code in Listing 1c uitvoeren, zien we een ander gedrag (zie figuur 4).
Listing 1c probeert alle 7777-rijen in de tabel Production.ProductI bij te werken. SQL Server stelt vast dat het vergrendelen van zoveel rijen niet langer efficiënt is om isolatie te garanderen. In plaats daarvan is de hele tafel vergrendeld.
Meer over Lock Escalation
De tabelvergrendeling houdt in dat geen enkele andere sessie de rijen kan wijzigen voor de transactieduur, wat zelfs kan gebeuren als een blokkerende sessie niet alle rijen in de tabel manipuleert.
Het is ook vermeldenswaard dat andere factoren van invloed kunnen zijn op hoe vergrendelingen worden verkregen en geëscaleerd in SQL Server. Dit zijn het geconfigureerde isolatieniveau, indexering en traceervlaggen.
Traceervlaggen T1211 en T1224 kunnen worden toegepast om Lock Escalation volledig uit te schakelen. Lock Escalation kan ook worden uitgeschakeld en ingeschakeld voor een specifieke tabel met de volgende code:
-- Listing 5: Disable and Enable Lock Escalation
ALTER TABLE Production.ProductsI SET (LOCK_ESCALATION=DISABLE);
ALTER TABLE Production.ProductsI SET (LOCK_ESCALATION=TABLE);
Misschien wil je het doen om de blokkering van de hele tafel te verminderen. Vanwege de impact op het geheugen, moet het worden overwogen als een tijdelijke maatregel.
Conclusie
SQL Server gebruikt Lock Escalation om de impact van meer gedetailleerde vergrendeling op serverbronnen te beheersen. Om de manier van optreden van deze vergrendelingen weer te geven - rijvergrendelingen, paginavergrendelingen, objectvergrendelingen, enz. - vraagt u de dynamische beheerweergave sys.dm_tran_locks aan. Het biedt veel informatie over vergrendelen, naast Lock Escalation.
Hoewel het mogelijk is om het gedrag van de Lock Manager te manipuleren, is het essentieel om dit met grote zorg te doen. Het is ook van cruciaal belang om de precieze prestatie-impact te kennen van elke inspanning die is gericht op het maken van dergelijke wijzigingen.
Referenties
- Korotkevitch, D., 2016. Pro SQL Server-internals. Florida:Dmitri Korotkevitch
- Scenario's vergrendelen met Sys.dm_tran_locks
- Handleiding voor het vergrendelen van transacties en rijversies