Databaseprofessionals worden regelmatig geconfronteerd met problemen met de databaseprestaties, zoals onjuiste indexering en slecht geschreven code in productie-SQL-instanties. Stel dat u een transactie hebt bijgewerkt en SQL Server het volgende deadlock-bericht heeft gerapporteerd. Voor DBA's die net beginnen, kan dit als een schok komen.
In dit artikel onderzoeken we de impasses van SQL Server en de beste manieren om ze te vermijden.
Wat is een SQL Server-impasse?
SQL Server is een zeer transactionele database. Stel dat u de database voor een online winkelportaal ondersteunt waar u de klok rond nieuwe bestellingen van klanten ontvangt. Waarschijnlijk voeren meerdere gebruikers tegelijkertijd dezelfde activiteit uit. In dit geval moet uw database de eigenschappen Atomiciteit, Consistentie, Isolatie, Duurzaamheid (ACID) volgen om consistent en betrouwbaar te zijn en de gegevensintegriteit te beschermen.
De afbeelding hieronder beschrijft de ACID-eigenschappen in een relationele database.
Om de ACID-eigenschappen te volgen, gebruikt SQL Server vergrendelingsmechanismen, beperkingen en write-ahead logging. Verschillende soorten vergrendelingen zijn:exclusieve vergrendeling (X), gedeelde vergrendeling (S), updatevergrendeling (U), intentvergrendeling (I), schemavergrendeling (SCH) en bulkupdatevergrendeling (BU). Deze sloten kunnen worden verkregen op sleutel-, tabel-, rij-, pagina- en databaseniveau.
Stel dat u twee gebruikers heeft, John en Peter, die verbonden zijn met de klantendatabase.
- John wil de records bijwerken voor de klant met [customerid] 1.
- Tegelijkertijd wil Peter de waarde ophalen voor de klant met [customerid] 1.
In dit geval gebruikt SQL Server de volgende vergrendelingen voor zowel John als Peter.
Sloten voor John
- Er is een intentie-exclusief (IX) slot nodig op de klantentabel en de pagina die het record bevat.
- Er is verder een exclusief (X) slot nodig op de rij die John wil updaten. Het voorkomt dat een andere gebruiker de rijgegevens wijzigt totdat proces A zijn vergrendeling opheft.
Sloten voor Peter
- Het verkrijgt een intent shared (IS) lock op de klantentabel en de pagina die het record bevat volgens de waar-clausule.
- Er wordt geprobeerd een gedeeld slot te gebruiken om de rij te lezen. Deze rij heeft al een exclusief slot voor John.
In dit geval moet Peter wachten tot John klaar is met zijn werk en het exclusieve slot vrijgeeft. Deze situatie staat bekend als blokkeren.
Stel nu dat in een ander scenario John en Peter de volgende sloten hebben.
- John heeft een exclusief slot op de klantentafel voor de klant-ID 1.
- Peter heeft een exclusief slot op de besteltafel voor klant-ID 1.
- John heeft een exclusief slot op de besteltafel nodig om zijn transactie af te ronden. Peter heeft al een exclusief slot op de besteltafel.
- Peter heeft een exclusief slot op de klantentafel nodig om zijn transactie af te ronden. John heeft al een exclusief slot op de klantentafel.
In dit geval kan geen van beide transacties doorgaan, omdat voor elke transactie een resource vereist is die in het bezit is van de andere transactie. Deze situatie staat bekend als een SQL Server-impasse.
SQL Server-bewakingsmechanismen voor deadlock
SQL Server bewaakt periodiek deadlock-situaties met behulp van de deadlock-monitorthread. Dit controleert de processen die betrokken zijn bij een deadlock en identificeert of een sessie een deadlock-slachtoffer is geworden. Het maakt gebruik van een intern mechanisme om het slachtofferproces in een impasse te identificeren. Standaard wordt de transactie met de minste hoeveelheid middelen die nodig zijn voor het terugdraaien als slachtoffer beschouwd.
SQL Server beëindigt de slachtoffersessie zodat een andere sessie de vereiste vergrendeling kan verkrijgen om de transactie te voltooien. Standaard controleert SQL Server de deadlock-situatie elke 5 seconden met behulp van de deadlock-monitor. Als het een deadlock detecteert, kan het de frequentie verlagen van 5 seconden tot 100 milliseconden, afhankelijk van het optreden van een deadlock. Het stelt de monitoringthread opnieuw in op 5 seconden als er geen frequente deadlocks optreden.
Zodra de SQL Server een proces als een deadlock-slachtoffer doodt, ontvangt u het volgende bericht. In deze sessie was proces-ID 69 een slachtoffer van een impasse.
De gevolgen van het gebruik van SQL Server-deadlock-prioriteitsverklaringen
Standaard markeert SQL Server de transactie met de goedkoopste rollback als een deadlock-slachtoffer. Gebruikers kunnen de deadlock-prioriteit in een transactie instellen met behulp van het DEADLOCK_PRIORITY-statement.
SET DEADLOCK_PRIORITY
Het gebruikt de volgende argumenten:
- Laag:het komt overeen met de deadlock-prioriteit -5
- Normaal:dit is de standaard deadlock-prioriteit 0
- Hoog:dit is de hoogste prioriteit 5.
We kunnen ook numerieke waarden instellen voor de deadlock-prioriteit van -10 tot 10 (totaal 21 waarden).
Laten we eens kijken naar een paar voorbeelden van impasse-prioriteitsverklaringen.
Voorbeeld 1:
Sessie 1 met deadlock-prioriteit:Normaal (0)> Sessie 2 met deadlock-prioriteit:Laag (-5)
Slachtoffer in een impasse: Sessie 2
Voorbeeld 2:
Sessie 1 met deadlock-prioriteit:Normaal (0)
Slachtoffer in een impasse: Sessie 1
Voorbeeld 3
Sessie 1 met deadlock-prioriteit:-3> Sessie 2 met deadlock-prioriteit:-7
Voorbeeld 4:
Sessie 1 met deadlock-prioriteit:-5
Slachtoffer in een impasse: Sessie 1
Een deadlock-grafiek is een visuele weergave van de deadlock-processen, hun locks en het deadlock-slachtoffer. We kunnen de traceringsvlaggen 1204 en 1222 inschakelen om deadlock-detailinformatie vast te leggen in een XML- en grafisch formaat. We kunnen de standaard uitgebreide gebeurtenis system_health gebruiken om de details van de deadlock te verkrijgen. Een snelle en gemakkelijke manier om de impasse te interpreteren is door middel van een deadlock-grafiek. Laten we een deadlock-toestand simuleren en de bijbehorende deadlock-grafiek bekijken.
Voor deze demonstratie hebben we de tabel Klant en Bestellingen gemaakt en enkele voorbeeldrecords ingevoegd.
Vervolgens hebben we een nieuw queryvenster geopend en de traceervlag globaal ingeschakeld.
DBCC-traceon(1222,-1)
Nadat we de deadlock-traceervlag hadden ingeschakeld, zijn we twee sessies gestart en hebben we de query in de onderstaande volgorde uitgevoerd:
In dit voorbeeld kiest SQL Server een deadlock-slachtoffer (sessie-ID 65) en stopt de transactie. Laten we de deadlock-grafiek ophalen uit de system_health uitgebreide gebeurtenissessie.
Deze query geeft ons een deadlock XML waarvoor een ervaren DBA nodig is om de informatie te interpreteren.
We slaan deze deadlock-XML op met de .XDL-extensie en wanneer we het XDL-bestand openen in SSMS, krijgen we de onderstaande deadlock-grafiek.
Deze impassegrafiek geeft de volgende informatie:
Het stelt een patstellingslachtoffer voor door het ovaal in de impassegrafiek door te strepen.
U kunt op de volgende manieren SQL Server-deadlock-informatie vastleggen:
1) Impasse bij het opzoeken van bladwijzers
Het opzoeken van bladwijzers is een veel voorkomende impasse in SQL Server. Het treedt op vanwege een conflict tussen de select-instructie en de DML-instructies (insert, update en delete). Meestal kiest SQL Server de select-instructie als een deadlock-slachtoffer omdat het geen gegevenswijzigingen veroorzaakt en het terugdraaien snel is. Om het opzoeken van bladwijzers te voorkomen, kunt u een dekkingsindex gebruiken. U kunt ook een NOLOCK-queryhint gebruiken in de select-instructies, maar deze leest niet-vastgelegde gegevens.
2) Impasse van bereikscan
Soms gebruiken we een SERIALIZABLE isolatieniveau op serverniveau of sessieniveau. Het is een beperkend isolatieniveau voor gelijktijdigheidscontrole en kan bereikscanvergrendelingen maken in plaats van vergrendelingen op pagina- of rijniveau. In het SERIALIZABLE-isolatieniveau kunnen gebruikers geen gegevens lezen als deze zijn gewijzigd, maar wachten om in een transactie te worden vastgelegd. Evenzo, als een transactie gegevens leest, kan een andere transactie deze niet wijzigen. Het biedt de laagste gelijktijdigheid, dus we moeten dit isolatieniveau gebruiken in specifieke toepassingsvereisten.
3) Trapsgewijze beperking van de beperking
SQL Server gebruikt de bovenliggende-onderliggende relatie tussen tabellen met behulp van de externe-sleutelbeperkingen. Als we in dit scenario een record bijwerken of verwijderen uit de bovenliggende tabel, zijn de nodige vergrendelingen op de onderliggende tabel nodig om verweesde records te voorkomen. Om deze impasses te elimineren, moet u altijd eerst gegevens in een onderliggende tabel wijzigen, gevolgd door de bovenliggende gegevens. U kunt ook rechtstreeks met de bovenliggende tabel werken met behulp van de opties DELETE CASCADE of UPDATE CASCADE. U moet ook geschikte indexen maken voor de kolommen met vreemde sleutels.
4) Intra-query parallellisme impasse
Zodra een gebruiker een query indient bij de SQL-queryengine, stelt de queryoptimalisatie een geoptimaliseerd uitvoeringsplan op. Het kan de query uitvoeren in een seriële of parallelle volgorde, afhankelijk van de querykosten, de maximale mate van parallellisme (MAXDOP) en de kostendrempel voor parallellisme.
In een parallellisme-modus wijst SQL Server meerdere threads toe. Soms beginnen deze threads elkaar te blokkeren voor een grote query in een parallelle modus. Uiteindelijk verandert het in impasses. In dit geval moet u het uitvoeringsplan en uw MAXDOP- en kostendrempel voor parallellismeconfiguraties herzien. U kunt ook de MAXDOP op sessieniveau specificeren om problemen met het deadlock-scenario op te lossen.
5) Impasse objectvolgorde omkeren
In dit type impasse hebben meerdere transacties toegang tot objecten in een andere volgorde in de T-SQL. Dit veroorzaakt blokkering van de bronnen voor elke sessie en zet het om in een impasse. U wilt objecten altijd in een logische volgorde benaderen, zodat dit niet tot een impasse leidt.
Deadlocks zijn een natuurlijk mechanisme in SQL Server om te voorkomen dat de sessie vergrendelingen vasthoudt en wacht op andere bronnen. U moet deadlock-query's vastleggen en optimaliseren zodat ze niet met elkaar conflicteren. Het is belangrijk om de vergrendeling voor een korte tijd vast te leggen en vrij te geven, zodat andere zoekopdrachten er effectief gebruik van kunnen maken.
SQL Server-deadlocks komen voor en hoewel SQL Server intern omgaat met deadlock-situaties, moet u proberen deze waar mogelijk te minimaliseren. Enkele van de beste manieren om deadlocks te elimineren, zijn door een index te maken, wijzigingen in de app-code toe te passen of de resources in een deadlock-grafiek zorgvuldig te inspecteren. Voor meer tips over het vermijden van SQL-deadlocks, bekijk onze post:SQL-deadlocks vermijden met het afstemmen van zoekopdrachten.SQL Server-deadlocks met behulp van deadlock-grafieken
CREATE TABLE Customer
(ID INT IDENTITY(1,1), CustomerName VARCHAR(20))
GO
CREATE TABLE Orders
(OrderID INT IDENTITY(1,1), ProductName VARCHAR(50))
GO
INSERT INTO Customer(CustomerName) VALUES ('Rajendra')
Go 100
S INSERT INTO Orders(ProductName) VALUES ('Laptop')
Go 100
SELECT XEvent.query('(event/data/value/deadlock)[1]') AS DeadlockGraph
FROM (
SELECT XEvent.query('.') AS XEvent
FROM (
SELECT CAST(target_data AS XML) AS TargetData
FROM sys.dm_xe_session_targets st
INNER JOIN sys.dm_xe_sessions s
ON s.address = st.event_session_address
WHERE s.NAME = ‘system_health’
AND st.target_name = ‘ring_buffer’
) AS Data
CROSS APPLY TargetData.nodes('RingBufferTarget/event[@name="xml_deadlock_report"]
') AS XEventData(XEvent)
) AS source;
5 soorten impasses in SQL Server
Handige manieren om SQL Server-deadlocks te vermijden en te minimaliseren
Overwegingen voor SQL Server-impasses