sql >> Database >  >> RDS >> Sqlserver

De anatomie van SQL Server-impasses en de beste manieren om ze te vermijden

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

SQL Server-deadlocks met behulp van deadlock-grafieken

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.

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

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:

  • De eerste sessie start een transactie om de klantentabel bij te werken voor klant-ID 1.
  • De tweede sessie start een transactie om de besteltabel voor bestelling-ID 10 bij te werken.
  • De eerste sessie probeert de besteltabel bij te werken voor dezelfde bestelling-ID 10. De tweede sessie vergrendelt deze rij al. Sessie 1 is geblokkeerd vanwege de vergrendelingen van sessie 2.
  • Nu willen we voor sessie 2 de klantentabel bijwerken voor klant-ID 1. Het genereert een impasse waarbij zowel sessie-ID 63 als ID 65 niet kunnen doorgaan.

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.

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;

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:

  • Procesknooppunten:  In het ovaal krijg je procesgerelateerde informatie.
  • Bronknooppunten:  Bronknooppunten (vierkante doos) geven informatie over de objecten die bij de transacties zijn betrokken, samen met de vergrendelingen. In dit voorbeeld toont het RID-vergrendelingen omdat we geen indexen hebben voor beide tabellen.
  • Randen:  Een edge verbindt het procesknooppunt en het resourceknooppunt. Het toont de eigenaar van de bron en de verzoekvergrendelingsmodus.

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:

  • SQL Server-profiler
  • SQL Server uitgebreide gebeurtenissen
  • SQL Server-foutlogboeken
  • Standaardsporen in SQL Server

5 soorten impasses in SQL Server

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.

Handige manieren om SQL Server-deadlocks te vermijden en te minimaliseren

  • Probeer transacties kort te houden; dit voorkomt dat een transactie voor een lange periode wordt vastgehouden.
  • Toegang tot objecten op een vergelijkbare logische manier in meerdere transacties.
  • Maak een dekkingsindex om de kans op een impasse te verkleinen.
  • Maak indexen die overeenkomen met de refererende-sleutelkolommen. Op deze manier kunt u impasses door trapsgewijze referentiële integriteit elimineren.
  • Stel deadlock-prioriteiten in met behulp van de sessievariabele SET DEADLOCK_PRIORITY. Als u de deadlock-prioriteit instelt, beëindigt SQL Server de sessie met de laagste deadlock-prioriteit.
  • Gebruik de foutafhandeling met behulp van de try-catch-blokken. U kunt de deadlock-fout opvangen en de transactie opnieuw uitvoeren in het geval van een deadlock-slachtoffer.
  • Verander het isolatieniveau in READ COMMITTED SNAPSHOT ISOLATION of SNAPSHOT ISOLATION. Dit verandert het vergrendelingsmechanisme van SQL Server. Hoewel u voorzichtig moet zijn bij het wijzigen van het isolatieniveau, omdat dit andere vragen negatief kan beïnvloeden.

Overwegingen voor SQL Server-impasses

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.


  1. Oracle kopieert gegevens naar een andere tabel

  2. Haal het juiste deel van een string in SQL Server (T-SQL)

  3. SQLite-JSON()

  4. MySQL PHP-incompatibiliteit