Impasses in Azure SQL Database analyseren en voorkomen

Van toepassing op: Azure SQL Database

In dit artikel wordt beschreven hoe u impasses in Azure SQL Database kunt identificeren, impassegrafieken en Query Store kunt gebruiken om de query's in de impasse te identificeren en wijzigingen te plannen en te testen om te voorkomen dat impasses zich opnieuw voordoen.

Dit artikel is gericht op het identificeren en analyseren van impasses vanwege conflicten met vergrendelingen. Meer informatie over andere soorten impasses in resources die een impasse kunnen vormen.

Hoe impasses optreden in Azure SQL Database

Voor elke nieuwe database in Azure SQL Database is de standaardinstelling voor het lezen vastgelegde momentopname (RCSI) ingeschakeld. Blokkeren tussen sessies die gegevens lezen en sessies die gegevens schrijven, wordt geminimaliseerd onder RCSI, waarbij gebruik wordt gemaakt van rijversiebeheer om de gelijktijdigheid te verhogen. Blokkeringen en impasses kunnen echter nog steeds optreden in databases in Azure SQL Database, omdat:

  • Query's die gegevens wijzigen, kunnen elkaar blokkeren.
  • Query's kunnen worden uitgevoerd onder isolatieniveaus die de blokkering verhogen. Isolatieniveaus kunnen worden opgegeven via clientbibliotheekmethoden, queryhints of SET-instructies in Transact-SQL.
  • RCSI kan worden uitgeschakeld, waardoor de database gedeelde (S)-vergrendelingen gebruikt om SELECT-instructies te beveiligen die worden uitgevoerd op het niveau van de vastgelegde isolatie voor lezen. Dit kan leiden tot blokkeringen en impasses.

Een voorbeeld van een impasse

Er treedt een impasse op wanneer twee of meer taken elkaar permanent blokkeren, omdat elke taak een vergrendeling heeft op een resource die de andere taak probeert te vergrendelen. Een impasse wordt ook wel een cyclische afhankelijkheid genoemd: in het geval van een impasse met twee taken heeft transactie A een afhankelijkheid van transactie B en transactie B sluit de cirkel door een afhankelijkheid van transactie A te hebben.

Bijvoorbeeld:

  1. Sessie A begint een expliciete transactie en voert een update-instructie uit waarmee een updatevergrendeling (U) wordt verkregen op één rij in de tabel SalesLT.Product die wordt geconverteerd naar een exclusieve (X)-vergrendeling.
  2. Sessie B voert een update-instructie uit waarmee de SalesLT.ProductDescription tabel wordt gewijzigd. De update-instructie wordt samengevoegd met de SalesLT.Product tabel om de juiste rijen te vinden die moeten worden bijgewerkt.
    • Sessie B verkrijgt een updatevergrendeling (U) op 72 rijen in de SalesLT.ProductDescription tabel.
    • Sessie B heeft een gedeelde vergrendeling nodig voor rijen in de tabel SalesLT.Product, inclusief de rij die is vergrendeld door sessie A. Sessie B wordt geblokkeerd op SalesLT.Product.
  3. Sessie A gaat verder met de transactie en voert nu een update uit voor de SalesLT.ProductDescription tabel. Sessie A wordt geblokkeerd door sessie B op SalesLT.ProductDescription.

A diagram showing two sessions in a deadlock. Each session owns a resource that the other process needs in order to continue.

Alle transacties in een impasse wachten voor onbepaalde tijd, tenzij een van de deelnemende transacties wordt teruggedraaid, bijvoorbeeld omdat de sessie is beëindigd.

De impasse-monitor van de database-engine controleert periodiek op taken die zich in een impasse bevinden. Als de impassemonitor een cyclische afhankelijkheid detecteert, kiest deze een van de taken als slachtoffer en beëindigt de transactie met fout 1205, 'Transactie (proces-id N) is impasse op vergrendelingsbronnen met een ander proces en is gekozen als het impasseslachtoffer. Voer de transactie opnieuw uit. Door de impasse op deze manier te verbreken, kunnen de andere taken of taken in de impasse hun transacties voltooien.

Notitie

Meer informatie over de criteria voor het kiezen van een impasseslachtoffer in de lijst met impasses in dit artikel.

Overview of a deadlock between two sessions. One session has been chosen as the deadlock victim.

De toepassing met de transactie die als het slachtoffer van de impasse is gekozen, moet de transactie opnieuw proberen, die meestal wordt voltooid nadat de andere transactie of transacties die betrokken zijn bij de impasse zijn voltooid.

Het is een best practice om een korte, gerandomiseerde vertraging te introduceren voordat u opnieuw probeert te voorkomen dat dezelfde impasse opnieuw optreedt. Meer informatie over het ontwerpen van logica voor opnieuw proberen voor tijdelijke fouten.

Standaardisolatieniveau in Azure SQL Database

Voor nieuwe databases in Azure SQL Database is standaard rcsi (read committed snapshot) ingeschakeld. RCSI wijzigt het gedrag van het vastgelegde isolatieniveau voor lezen om rijversiebeheer te gebruiken om consistentie op instructieniveau te bieden zonder gebruik te maken van gedeelde (S)-vergrendelingen voor SELECT-instructies.

Met RCSI ingeschakeld:

  • Instructies die gegevens lezen, blokkeren geen instructies voor het wijzigen van gegevens.
  • Instructies die gegevens wijzigen, blokkeren geen instructies voor het lezen van gegevens.

Isolatieniveau voor momentopnamen is ook standaard ingeschakeld voor nieuwe databases in Azure SQL Database. Isolatie van momentopnamen is een extra isolatieniveau op basis van rijen dat consistentie op transactieniveau biedt voor gegevens en waarbij rijversies worden gebruikt om rijen te selecteren die moeten worden bijgewerkt. Als u isolatie van momentopnamen wilt gebruiken, moeten query's of verbindingen hun transactieisolatieniveau expliciet instellen op SNAPSHOT. Dit kan alleen worden gedaan wanneer isolatie van momentopnamen is ingeschakeld voor de database.

U kunt bepalen of RCSI en/of momentopname-isolatie zijn ingeschakeld met Transact-SQL. Verbinding maken naar uw database in Azure SQL Database en voer de volgende query uit:

SELECT name, is_read_committed_snapshot_on, snapshot_isolation_state_desc
FROM sys.databases
WHERE name = DB_NAME();
GO

Als RCSI is ingeschakeld, retourneert de is_read_committed_snapshot_on kolom de waarde 1. Als isolatie van momentopnamen is ingeschakeld, retourneert de snapshot_isolation_state_desc kolom de waarde AAN.

Als RCSI is uitgeschakeld voor een database in Azure SQL Database, onderzoekt u waarom RCSI is uitgeschakeld voordat u deze opnieuw inschakelt. Toepassingscode is mogelijk geschreven waarin wordt verwacht dat query's die gegevens lezen, worden geblokkeerd door query's die gegevens schrijven, wat resulteert in onjuiste resultaten van racevoorwaarden wanneer RCSI is ingeschakeld.

Impasse-gebeurtenissen interpreteren

Er wordt een impasse-gebeurtenis verzonden nadat de impassemanager in Azure SQL Database een impasse detecteert en een transactie als slachtoffer selecteert. Met andere woorden, als u waarschuwingen instelt voor impasses, wordt de melding geactiveerd nadat een afzonderlijke impasse is opgelost. Er is geen actie van de gebruiker die moet worden uitgevoerd voor die impasse. Toepassingen moeten worden geschreven om logica voor opnieuw proberen op te nemen, zodat ze automatisch doorgaan na ontvangst van fout 1205, 'Transactie (proces-id N) was impasse op vergrendelingsresources met een ander proces en is gekozen als het impasseslachtoffer. Voer de transactie opnieuw uit.

Het is echter handig om waarschuwingen in te stellen, omdat er mogelijk impasses optreden. Met impassewaarschuwingen kunt u onderzoeken of er een patroon van herhalende impasses in uw database plaatsvindt. In dat geval kunt u ervoor kiezen om actie te ondernemen om te voorkomen dat impasses opnieuw optreden. Meer informatie over waarschuwingen in de sectie Bewaking en waarschuwingen over impasses van dit artikel.

Belangrijkste methoden om impasses te voorkomen

De laagste risicobenadering om te voorkomen dat impasses opnieuw optreden, is over het algemeen om niet-geclusterde indexen af te stemmen om query's te optimaliseren die betrokken zijn bij de impasse.

  • Het risico is laag voor deze benadering omdat het afstemmen van niet-geclusterde indexen geen wijzigingen in de querycode zelf vereist, waardoor het risico van een gebruikersfout wordt verminderd bij het herschrijven van Transact-SQL, waardoor onjuiste gegevens naar de gebruiker worden geretourneerd.
  • Effectieve niet-geclusterde indexafstemming helpt query's de gegevens te vinden die efficiënter kunnen worden gelezen en gewijzigd. Door de hoeveelheid gegevens te verminderen waartoe een query toegang nodig heeft, wordt de kans op blokkeren verminderd en kunnen impasses vaak worden voorkomen.

In sommige gevallen kan het maken of afstemmen van een geclusterde index blokkeren en impasses verminderen. Omdat de geclusterde index is opgenomen in alle niet-geclusterde indexdefinities, kan het maken of wijzigen van een geclusterde index een I/O-intensieve en tijdrovende bewerking zijn voor grotere tabellen met bestaande niet-geclusterde indexen. Meer informatie over ontwerprichtlijnen voor geclusterde indexen.

Wanneer het afstemmen van indexen niet lukt om impasses te voorkomen, zijn er andere methoden beschikbaar:

  • Als de impasse alleen optreedt wanneer een bepaald plan wordt gekozen voor een van de query's die betrokken zijn bij de impasse, kan het afdwingen van een queryplan met Query Store verhinderen dat impasses opnieuw optreden.
  • Het herschrijven van Transact-SQL voor een of meer transacties die zijn betrokken bij de impasse, kunnen ook helpen impasses te voorkomen. Het splitsen van expliciete transacties in kleinere transacties vereist zorgvuldig coderen en testen om ervoor te zorgen dat gegevens geldig zijn wanneer gelijktijdige wijzigingen plaatsvinden.

Meer informatie over elk van deze benaderingen vindt u in de sectie Voorkomen dat er een impasse optreedt in dit artikel.

Impasses bewaken en waarschuwen

In dit artikel gebruiken we de AdventureWorksLT voorbeelddatabase om waarschuwingen in te stellen voor impasses, een voorbeeld van een impasse te veroorzaken, de impassegrafiek voor het voorbeeld van een impasse te analyseren en wijzigingen te testen om te voorkomen dat de impasse opnieuw optreedt.

In dit artikel gebruiken we de SSMS-client (SQL Server Management Studio), omdat deze functionaliteit bevat voor het weergeven van impassegrafieken in een interactieve visuele modus. U kunt andere clients zoals Azure Data Studio gebruiken om de voorbeelden te volgen, maar u kunt mogelijk alleen impassegrafieken weergeven als XML.

De AdventureWorksLT-database maken

Als u de voorbeelden wilt volgen, maakt u een nieuwe database in Azure SQL Database en selecteert u Voorbeeldgegevens als de gegevensbron.

Voor gedetailleerde instructies over het maken AdventureWorksLT met Azure Portal, Azure CLI of PowerShell selecteert u de methode van uw keuze in quickstart: Een individuele Azure SQL Database-database maken.

Impassewaarschuwingen instellen in Azure Portal

Als u waarschuwingen wilt instellen voor impasse-gebeurtenissen, volgt u de stappen in het artikel Waarschuwingen maken voor Azure SQL Database en Azure Synapse Analytics met behulp van Azure Portal.

Selecteer Impasses als de signaalnaam voor de waarschuwing. Configureer de actiegroep om u op de hoogte te stellen met behulp van de methode van uw keuze, zoals het actietype E-mail/SMS/Push/Spraak .

Impassegrafieken verzamelen in Azure SQL Database met uitgebreide gebeurtenissen

Impassegrafieken zijn een rijke bron van informatie over de processen en vergrendelingen die betrokken zijn bij een impasse. Als u impassegrafieken wilt verzamelen met uitgebreide gebeurtenissen (XEvents) in Azure SQL Database, legt u de sqlserver.database_xml_deadlock_report gebeurtenis vast.

U kunt impassegrafieken met XEvents verzamelen met behulp van het ringbufferdoel of een doel voor een gebeurtenisbestand. Overwegingen voor het selecteren van het juiste doeltype worden samengevat in de volgende tabel:

Methode Vergoedingen Overwegingen Gebruiksscenario's
Ringbufferdoel
  • Eenvoudige installatie met alleen Transact-SQL.
  • Gebeurtenisgegevens worden gewist wanneer de XEvents-sessie om welke reden dan ook wordt gestopt, zoals het offline halen van de database of een failover van een database.
  • Databasebronnen worden gebruikt om gegevens in de ringbuffer te onderhouden en om sessiegegevens op te vragen.
  • Verzamel voorbeeldtraceringsgegevens voor testen en leren.
  • Maak voor kortetermijnbehoeften als u een sessie niet direct kunt instellen met behulp van een doel voor een gebeurtenisbestand.
  • Gebruik dit als een 'landingspad' voor traceringsgegevens wanneer u een geautomatiseerd proces hebt ingesteld om traceringsgegevens in een tabel te behouden.
Doel van gebeurtenisbestand
  • Bewaart gebeurtenisgegevens naar een blob in Azure Storage, zodat gegevens beschikbaar zijn, zelfs nadat de sessie is gestopt.
  • Gebeurtenisbestanden kunnen worden gedownload vanuit Azure Portal of Azure Storage Explorer en lokaal worden geanalyseerd. Hiervoor is het niet nodig om databasebronnen te gebruiken om sessiegegevens op te vragen.
  • De installatie is complexer en vereist configuratie van een Azure Storage-container en databasereferentie in het bereik.
  • Algemeen gebruik wanneer u wilt dat gebeurtenisgegevens behouden blijven, zelfs nadat de gebeurtenissessie is gestopt.
  • U wilt een tracering uitvoeren waarmee grotere hoeveelheden gebeurtenisgegevens worden gegenereerd dan u in het geheugen wilt behouden.

Selecteer het doeltype dat u wilt gebruiken:

Het ringbufferdoel is handig en eenvoudig in te stellen, maar heeft een beperkte capaciteit, waardoor oudere gebeurtenissen verloren kunnen gaan. De ringbuffer bewaart geen gebeurtenissen voor opslag en het ringbufferdoel wordt gewist wanneer de XEvents-sessie wordt gestopt. Dit betekent dat alle verzamelde XEvents niet beschikbaar zijn wanneer de database-engine om welke reden dan ook opnieuw wordt opgestart, zoals een failover. Het ringbufferdoel is het meest geschikt voor leer- en kortetermijnbehoeften als u niet de mogelijkheid hebt om een XEvents-sessie onmiddellijk in te stellen op een gebeurtenisbestandsdoel.

Met deze voorbeeldcode maakt u een XEvents-sessie die impassegrafieken in het geheugen vastlegt met behulp van het ringbufferdoel. Het maximale geheugen dat is toegestaan voor het ringbufferdoel is 4 MB en de sessie wordt automatisch uitgevoerd wanneer de database online komt, bijvoorbeeld na een failover.

Als u een XEvents-sessie wilt maken en starten voor de sqlserver.database_xml_deadlock_report gebeurtenis die naar het ringbufferdoel schrijft, maakt u verbinding met uw database en voert u de volgende Transact-SQL uit:

CREATE EVENT SESSION [deadlocks] ON DATABASE 
ADD EVENT sqlserver.database_xml_deadlock_report
ADD TARGET package0.ring_buffer 
WITH (STARTUP_STATE=ON, MAX_MEMORY=4 MB)
GO

ALTER EVENT SESSION [deadlocks] ON DATABASE
    STATE = START;
GO

Een impasse veroorzaken in AdventureWorksLT

Notitie

Dit voorbeeld werkt in de AdventureWorksLT database met het standaardschema en de standaardgegevens wanneer RCSI is ingeschakeld. Zie De AdventureWorksLT-database maken voor instructies voor het maken van de database.

Als u een impasse wilt veroorzaken, moet u twee sessies verbinden met de AdventureWorksLT database. We verwijzen naar deze sessies als sessie A en sessie B.

Voer in sessie A de volgende Transact-SQL uit. Deze code begint met een expliciete transactie en voert één instructie uit waarmee de SalesLT.Product tabel wordt bijgewerkt. Hiervoor verkrijgt de transactie een updatevergrendeling (U) op één rij in een tabel SalesLT.Product die wordt geconverteerd naar een exclusieve (X)-vergrendeling. We laten de transactie open.

BEGIN TRAN

    UPDATE SalesLT.Product SET SellEndDate = SellEndDate + 1
        WHERE Color = 'Red';

Voer nu in sessie B de volgende Transact-SQL uit. Deze code begint niet expliciet met een transactie. In plaats daarvan werkt het in de automatische transactiemodus. Met deze instructie wordt de SalesLT.ProductDescription tabel bijgewerkt. Met de update wordt een updatevergrendeling (U) uitgeschakeld op 72 rijen in de SalesLT.ProductDescription tabel. De query wordt samengevoegd met andere tabellen, inclusief de SalesLT.Product tabel.

UPDATE SalesLT.ProductDescription SET Description = Description
    FROM SalesLT.ProductDescription as pd
    JOIN SalesLT.ProductModelProductDescription as pmpd on
        pd.ProductDescriptionID = pmpd.ProductDescriptionID
    JOIN SalesLT.ProductModel as pm on
        pmpd.ProductModelID = pm.ProductModelID
    JOIN SalesLT.Product as p on
        pm.ProductModelID=p.ProductModelID
    WHERE p.Color = 'Silver';

Om deze update te voltooien, heeft Sessie B een gedeelde vergrendeling (S) nodig voor rijen in de tabel SalesLT.Product, inclusief de rij die is vergrendeld door Sessie A. Sessie B wordt geblokkeerd op SalesLT.Product.

Ga terug naar sessie A. Voer de volgende Transact-SQL-instructie uit. Hiermee wordt een tweede UPDATE-instructie uitgevoerd als onderdeel van de open transactie.

    UPDATE SalesLT.ProductDescription SET Description = Description
        FROM SalesLT.ProductDescription as pd
        JOIN SalesLT.ProductModelProductDescription as pmpd on
            pd.ProductDescriptionID = pmpd.ProductDescriptionID
        JOIN SalesLT.ProductModel as pm on
            pmpd.ProductModelID = pm.ProductModelID
        JOIN SalesLT.Product as p on
            pm.ProductModelID=p.ProductModelID
        WHERE p.Color = 'Red';

De tweede update-instructie in sessie A wordt geblokkeerd door sessie B op de SalesLT.ProductDescription.

Sessie A en sessie B blokkeren elkaar nu wederzijds. Geen van beide transacties kan doorgaan, omdat ze elk een resource nodig hebben die door de andere is vergrendeld.

Na een paar seconden identificeert de impassemonitor dat de transacties in sessie A en sessie B elkaar wederzijds blokkeren en dat geen van beide vooruitgang kan boeken. U ziet dat er een impasse optreedt, met Sessie A gekozen als het impasseslachtoffer. Er wordt een foutbericht weergegeven in sessie A met tekst die er ongeveer als volgt uitziet:

Msg 1205, Niveau 13, State 51, Regel 7 Transactie (Proces-id 91) was impasse op vergrendelingsbronnen met een ander proces en is gekozen als het impasseslachtoffer. Voer de transactie opnieuw uit.

Sessie B wordt voltooid.

Als u impassewaarschuwingen instelt in Azure Portal, ontvangt u kort nadat de impasse is opgetreden een melding.

Impassegrafieken van een XEvents-sessie weergeven

Als u een XEvents-sessie hebt ingesteld om impasses te verzamelen en er een impasse is opgetreden nadat de sessie is gestart, kunt u een interactieve grafische weergave van de impassegrafiek en de XML voor de impassegrafiek bekijken.

Er zijn verschillende methoden beschikbaar om impassegegevens te verkrijgen voor het ringbufferdoel en gebeurtenisbestandsdoelen. Selecteer het doel dat u hebt gebruikt voor uw XEvents-sessie:

Als u een XEvents-sessie instelt die naar de ringbuffer wordt geschreven, kunt u impassegegevens opvragen met de volgende Transact-SQL. Voordat u de query uitvoert, vervangt u de waarde door @tracename de naam van uw xEvents-sessie.

DECLARE @tracename sysname = N'deadlocks';

WITH ring_buffer AS (
    SELECT CAST(target_data AS XML) as rb
    FROM sys.dm_xe_database_sessions AS s 
    JOIN sys.dm_xe_database_session_targets AS t 
        ON CAST(t.event_session_address AS BINARY(8)) = CAST(s.address AS BINARY(8))
    WHERE s.name = @tracename and
    t.target_name = N'ring_buffer'
), dx AS (
    SELECT 
        dxdr.evtdata.query('.') as deadlock_xml_deadlock_report
    FROM ring_buffer
    CROSS APPLY rb.nodes('/RingBufferTarget/event[@name=''database_xml_deadlock_report'']') AS dxdr(evtdata)
) 
SELECT 
    d.query('/event/data[@name=''deadlock_cycle_id'']/value').value('(/value)[1]', 'int') AS [deadlock_cycle_id],
    d.value('(/event/@timestamp)[1]', 'DateTime2') AS [deadlock_timestamp],
    d.query('/event/data[@name=''database_name'']/value').value('(/value)[1]', 'nvarchar(256)') AS [database_name],
    d.query('/event/data[@name=''xml_report'']/value/deadlock') AS deadlock_xml,
    LTRIM(RTRIM(REPLACE(REPLACE(d.value('.', 'nvarchar(2000)'),CHAR(10),' '),CHAR(13),' '))) as query_text
FROM dx
CROSS APPLY deadlock_xml_deadlock_report.nodes('(/event/data/value/deadlock/process-list/process/inputbuf)') AS ib(d)
ORDER BY [deadlock_timestamp] DESC;
GO

Een impassegrafiek weergeven en opslaan in XML

Door een impassegrafiek in XML-indeling te bekijken, kunt u de inputbuffer Transact-SQL-instructies kopiëren die betrokken zijn bij de impasse. U kunt ook liever impasses analyseren in een op tekst gebaseerde indeling.

Als u een Transact-SQL-query hebt gebruikt om impassegrafiekgegevens te retourneren, selecteert u de waarde in de kolom in een deadlock_xml willekeurige rij om de XML van de impassegrafiek in een nieuw venster in SSMS te openen.

De XML voor deze voorbeeld impassegrafiek is:

<deadlock>
  <victim-list>
    <victimProcess id="process24756e75088" />
  </victim-list>
  <process-list>
    <process id="process24756e75088" taskpriority="0" logused="6528" waitresource="KEY: 8:72057594045202432 (98ec012aa510)" waittime="192" ownerId="1011123" transactionname="user_transaction" lasttranstarted="2022-03-08T15:44:43.490" XDES="0x2475c980428" lockMode="U" schedulerid="3" kpid="30192" status="suspended" spid="89" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2022-03-08T15:44:49.250" lastbatchcompleted="2022-03-08T15:44:49.210" lastattention="1900-01-01T00:00:00.210" clientapp="Microsoft SQL Server Management Studio - Query" hostname="LAPTOP-CHRISQ" hostpid="16716" loginname="chrisqpublic" isolationlevel="read committed (2)" xactid="1011123" currentdb="8" currentdbname="AdventureWorksLT" lockTimeout="4294967295" clientoption1="671096864" clientoption2="128056">
      <executionStack>
        <frame procname="unknown" queryhash="0xef52b103e8b9b8ca" queryplanhash="0x02b0f58d7730f798" line="1" stmtstart="2" stmtend="792" sqlhandle="0x02000000c58b8f1e24e8f104a930776e21254b1771f92a520000000000000000000000000000000000000000">
unknown    </frame>
      </executionStack>
      <inputbuf>
    UPDATE SalesLT.ProductDescription SET Description = Description
        FROM SalesLT.ProductDescription as pd
        JOIN SalesLT.ProductModelProductDescription as pmpd on
            pd.ProductDescriptionID = pmpd.ProductDescriptionID
        JOIN SalesLT.ProductModel as pm on
            pmpd.ProductModelID = pm.ProductModelID
        JOIN SalesLT.Product as p on
            pm.ProductModelID=p.ProductModelID
        WHERE p.Color = 'Red'   </inputbuf>
    </process>
    <process id="process2476d07d088" taskpriority="0" logused="11360" waitresource="KEY: 8:72057594045267968 (39e18040972e)" waittime="2641" ownerId="1013536" transactionname="UPDATE" lasttranstarted="2022-03-08T15:44:46.807" XDES="0x2475ca80428" lockMode="S" schedulerid="2" kpid="94040" status="suspended" spid="95" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2022-03-08T15:44:46.807" lastbatchcompleted="2022-03-08T15:44:46.760" lastattention="1900-01-01T00:00:00.760" clientapp="Microsoft SQL Server Management Studio - Query" hostname="LAPTOP-CHRISQ" hostpid="16716" loginname="chrisqpublic" isolationlevel="read committed (2)" xactid="1013536" currentdb="8" currentdbname="AdventureWorksLT" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
      <executionStack>
        <frame procname="unknown" queryhash="0xef52b103e8b9b8ca" queryplanhash="0x02b0f58d7730f798" line="1" stmtstart="2" stmtend="798" sqlhandle="0x020000002c85bb06327c0852c0be840fc1e30efce2b7c8090000000000000000000000000000000000000000">
unknown    </frame>
      </executionStack>
      <inputbuf>
    UPDATE SalesLT.ProductDescription SET Description = Description
        FROM SalesLT.ProductDescription as pd
        JOIN SalesLT.ProductModelProductDescription as pmpd on
            pd.ProductDescriptionID = pmpd.ProductDescriptionID
        JOIN SalesLT.ProductModel as pm on
            pmpd.ProductModelID = pm.ProductModelID
        JOIN SalesLT.Product as p on
            pm.ProductModelID=p.ProductModelID
        WHERE p.Color = 'Silver';   </inputbuf>
    </process>
  </process-list>
  <resource-list>
    <keylock hobtid="72057594045202432" dbid="8" objectname="9e011567-2446-4213-9617-bad2624ccc30.SalesLT.ProductDescription" indexname="PK_ProductDescription_ProductDescriptionID" id="lock2474df12080" mode="U" associatedObjectId="72057594045202432">
      <owner-list>
        <owner id="process2476d07d088" mode="U" />
      </owner-list>
      <waiter-list>
        <waiter id="process24756e75088" mode="U" requestType="wait" />
      </waiter-list>
    </keylock>
    <keylock hobtid="72057594045267968" dbid="8" objectname="9e011567-2446-4213-9617-bad2624ccc30.SalesLT.Product" indexname="PK_Product_ProductID" id="lock2474b588580" mode="X" associatedObjectId="72057594045267968">
      <owner-list>
        <owner id="process24756e75088" mode="X" />
      </owner-list>
      <waiter-list>
        <waiter id="process2476d07d088" mode="S" requestType="wait" />
      </waiter-list>
    </keylock>
  </resource-list>
</deadlock>

De impassegrafiek opslaan als een XML-bestand:

  1. Selecteer Bestand en Opslaan als....
  2. Laat de waarde Opslaan als de standaard-XML-bestanden (*.xml) staan
  3. Stel de bestandsnaam in op de naam van uw keuze.
  4. Selecteer Opslaan.

Een impassegrafiek opslaan als een XDL-bestand dat interactief kan worden weergegeven in SSMS

Het weergeven van een interactieve weergave van een impassegrafiek kan handig zijn om een kort overzicht te krijgen van de processen en resources die betrokken zijn bij een impasse en het snel identificeren van het impasseslachtoffer.

Een impassegrafiek opslaan als een bestand dat grafisch kan worden weergegeven door SSMS:

  1. Selecteer de waarde in de deadlock_xml kolom in een willekeurige rij om de XML van de impassegrafiek te openen in een nieuw venster in SSMS.

  2. Selecteer Bestand en Opslaan als....

  3. Stel Opslaan als type in op Alle bestanden.

  4. Stel de bestandsnaam in op de naam van uw keuze, waarbij de extensie is ingesteld op .xdl.

  5. Selecteer Opslaan.

    A screenshot in SSMS of saving a deadlock graph XML file to a file with the xsd extension.

  6. Sluit het bestand door de X te selecteren op het tabblad boven aan het venster of door Bestand te selecteren en vervolgens Sluiten.

  7. Open het bestand opnieuw in SSMS door Bestand te selecteren en vervolgens Bestand te openen en vervolgens Bestand. Selecteer het bestand dat u hebt opgeslagen met de .xdl extensie.

    De impassegrafiek wordt nu weergegeven in SSMS met een visuele weergave van de processen en resources die betrokken zijn bij de impasse.

    Screenshot of an xdl file opened in SSMS. The deadlock graph is displayed graphically, with processes indicated by ovals and lock resources as rectangles.

Een impasse analyseren voor Azure SQL Database

Een impassegrafiek heeft doorgaans drie knooppunten:

  • Slachtofferslijst. De proces-id van het slachtoffer van de impasse.
  • Proceslijst. Informatie over alle processen die betrokken zijn bij de impasse. Impassegrafieken gebruiken de term 'proces' om een sessie weer te geven waarop een transactie wordt uitgevoerd.
  • Resourcelijst. Informatie over de resources die betrokken zijn bij de impasse.

Bij het analyseren van een impasse is het handig om deze knooppunten te doorlopen.

Lijst met slachtoffers van impasses

De lijst met impasseslachtoffers toont het proces dat is gekozen als het impasseslachtoffer. In de visuele weergave van een impassegrafiek worden processen weergegeven door ovalen. Het impasseslachtofferproces heeft een "X" getekend over het ovaal.

Screenshot of the visual display of a deadlock. The oval representing the process selected as victim has an X drawn across it.

In de XML-weergave van een impassegrafiek geeft het victim-list knooppunt een id voor het proces dat het slachtoffer was van de impasse.

In ons voorbeeld is de proces-id van het slachtoffer proces24756e75088. We kunnen deze id gebruiken bij het onderzoeken van de proceslijst- en resourcelijstknooppunten voor meer informatie over het slachtofferproces en de resources die het vergrendelen of aanvragen om te vergrendelen.

Lijst met impasseprocessen

De lijst met impasseprocessen is een uitgebreide bron van informatie over de transacties die betrokken zijn bij de impasse.

In de grafische weergave van de impassegrafiek ziet u slechts een subset met informatie in de XML van de impassegrafiek. De ovalen in de impassegrafiek vertegenwoordigen het proces en geven informatie weer, waaronder:

  • Serverproces-id, ook wel de sessie-id of SPID genoemd.

  • Impasseprioriteit van de sessie. Als twee sessies verschillende impasseprioriteiten hebben, wordt de sessie met de lagere prioriteit gekozen als het impasseslachtoffer. In dit voorbeeld hebben beide sessies dezelfde impasseprioriteit.

  • De hoeveelheid transactielogboek die door de sessie in bytes wordt gebruikt. Als beide sessies dezelfde impasseprioriteit hebben, kiest de impassemonitor de sessie die minder duur is om terug te draaien als het impasseslachtoffer. De kosten worden bepaald door het aantal logboekbytes te vergelijken dat naar dat punt in elke transactie is geschreven.

    In ons voorbeeld was session_id 89 een lager transactielogboek gebruikt en werd geselecteerd als het impasseslachtoffer.

Daarnaast kunt u de invoerbuffer voor de laatste instructie bekijken die in elke sessie vóór de impasse wordt uitgevoerd door de muisaanwijzer over elk proces te bewegen. De invoerbuffer wordt weergegeven in knopinfo.

Screenshot of a deadlock graph displayed visually in SSMS. Two ovals represent processes. The inputbuff for one process is shown.

Aanvullende informatie is beschikbaar voor processen in de XML-weergave van de impassegrafiek, waaronder:

  • Identificatiegegevens voor de sessie, zoals de clientnaam, hostnaam en aanmeldingsnaam.
  • De hash van het queryplan voor de laatste instructie die wordt uitgevoerd door elke sessie voorafgaand aan de impasse. De hash van het queryplan is handig voor het ophalen van meer informatie over de query uit Query Store.

In ons voorbeeld impasse:

  • We kunnen zien dat beide sessies werden uitgevoerd met behulp van de SSMS-client onder de chrisqpublic-aanmelding .
  • De hash van het queryplan van de laatste instructie wordt uitgevoerd vóór de impasse door ons impasseslachtoffer is 0x02b0f58d7730f798. De tekst van deze instructie wordt weergegeven in de invoerbuffer.
  • De hash van het queryplan van de laatste instructie die door de andere sessie in onze impasse wordt uitgevoerd, is ook 0x02b0f58d7730f798. De tekst van deze instructie wordt weergegeven in de invoerbuffer. In dit geval hebben beide query's dezelfde hash van het queryplan, omdat de query's identiek zijn, met uitzondering van een letterlijke waarde die wordt gebruikt als gelijkheidspredicaat.

Verderop in dit artikel gebruiken we deze waarden om aanvullende informatie te vinden in Query Store.

Beperkingen van de invoerbuffer in de lijst met impasseprocessen

Er zijn enkele beperkingen om rekening mee te houden met betrekking tot informatie over invoerbuffers in de lijst met impasseprocessen.

Querytekst kan worden afgekapt in de invoerbuffer. De invoerbuffer is beperkt tot de eerste 4000 tekens van de instructie die wordt uitgevoerd.

Daarnaast zijn sommige verklaringen die betrokken zijn bij de impasse mogelijk niet opgenomen in de impassegrafiek. In ons voorbeeld heeft Sessie A twee update-instructies uitgevoerd binnen één transactie. Alleen de tweede update-instructie, de update die de impasse heeft veroorzaakt, wordt opgenomen in de impassegrafiek. De eerste update-instructie die door Sessie A wordt uitgevoerd, speelde een rol in de impasse door sessie B te blokkeren. De invoerbuffer query_hashen gerelateerde informatie voor de eerste instructie die wordt uitgevoerd door Session A, is niet opgenomen in de impassegrafiek.

Als u de volledige Transact-SQL-uitvoering wilt identificeren in een transactie met meerdere instructies die betrokken zijn bij een impasse, moet u de relevante informatie vinden in de opgeslagen procedure of toepassingscode die de query heeft uitgevoerd, of een tracering uitvoeren met behulp van uitgebreide gebeurtenissen om volledige instructies vast te leggen die worden uitgevoerd door sessies die betrokken zijn bij een impasse terwijl deze zich voordoet. Als een instructie die is betrokken bij de impasse is afgekapt en alleen gedeeltelijk Transact-SQL wordt weergegeven in de invoerbuffer, kunt u de Transact-SQL vinden voor de instructie in Query Store met het uitvoeringsplan.

Lijst met impasseresources

In de lijst met impasseresources ziet u welke vergrendelingsresources eigendom zijn van en worden gewacht door de processen in de impasse.

Resources worden weergegeven door rechthoeken in de visuele weergave van de impasse:

Screenshot of a deadlock graph, displayed visually in SSMS. Rectangles show the resources that are involved in the deadlock.

Notitie

U ziet mogelijk dat databasenamen worden weergegeven als uniekedientifers in impassegrafieken voor databases in Azure SQL Database. Dit is de physical_database_name database die wordt vermeld in de sys.databases en sys.dm_user_db_resource_governance dynamische beheerweergaven.

In dit voorbeeld impasse:

  • Het impasseslachtoffer, dat we sessie A noemen:

    • Bezit een exclusieve (X)-vergrendeling op een sleutel in de PK_Product_ProductID index in de SalesLT.Product tabel.
    • Vraagt een updatevergrendeling (U) aan op een sleutel in de PK_ProductDescription_ProductDescriptionID index in de SalesLT.ProductDescription tabel.
  • Het andere proces, dat we sessie B noemen:

    • De eigenaar is van een updatevergrendeling (U) op een sleutel in de PK_ProductDescription_ProductDescriptionID index in de SalesLT.ProductDescription tabel.
    • Vraagt een gedeelde (S)-vergrendeling aan op een sleutel in de PK_ProductDescription_ProductDescriptionID index in de SalesLT.ProductDescription tabel.

We kunnen dezelfde informatie zien in de XML van de impassegrafiek in het knooppunt van de resourcelijst .

Queryuitvoeringsplannen zoeken in Query Store

Het is vaak handig om de uitvoeringsplannen voor query's te onderzoeken voor instructies die betrokken zijn bij de impasse. Deze uitvoeringsplannen zijn vaak te vinden in Query Store met behulp van de hash van het queryplan vanuit de XML-weergave van de proceslijst van de impassegrafiek.

Deze Transact-SQL-query zoekt naar queryplannen die overeenkomen met de hash van het queryplan die we hebben gevonden voor onze voorbeeld-impasse. Verbinding maken naar de gebruikersdatabase in Azure SQL Database om de query uit te voeren.

DECLARE @query_plan_hash binary(8) = 0x02b0f58d7730f798

SELECT 
    qrsi.end_time as interval_end_time,
    qs.query_id,
    qp.plan_id,
    qt.query_sql_text, 
    TRY_CAST(qp.query_plan as XML) as query_plan,
    qrs.count_executions
FROM sys.query_store_query as qs
JOIN sys.query_store_query_text as qt on qs.query_text_id=qt.query_text_id
JOIN sys.query_store_plan as qp on qs.query_id=qp.query_id
JOIN sys.query_store_runtime_stats qrs on qp.plan_id = qrs.plan_id
JOIN sys.query_store_runtime_stats_interval qrsi on qrs.runtime_stats_interval_id=qrsi.runtime_stats_interval_id
WHERE query_plan_hash =  @query_plan_hash
ORDER BY interval_end_time, query_id;
GO

Mogelijk kunt u geen queryuitvoeringsplan ophalen uit Query Store, afhankelijk van uw Query Store-CLEANUP_POLICY of QUERY_CAPTURE_MODE-instellingen. In dit geval kunt u vaak de benodigde informatie ophalen door het geschatte uitvoeringsplan voor de query weer te geven.

Zoeken naar patronen die de blokkering vergroten

Wanneer u queryuitvoeringsplannen bekijkt die betrokken zijn bij impasses, kijkt u naar patronen die kunnen bijdragen aan blokkeringen en impasses.

  • Tabel- of indexscans. Wanneer query's die gegevens wijzigen, worden uitgevoerd onder RCSI, wordt de selectie van rijen die moeten worden bijgewerkt uitgevoerd met behulp van een blokkerende scan waarbij een updatevergrendeling (U) wordt uitgevoerd op de gegevensrij wanneer gegevenswaarden worden gelezen. Als de gegevensrij niet voldoet aan de updatecriteria, wordt de updatevergrendeling vrijgegeven en wordt de volgende rij vergrendeld en gescand.

    Door indexen af te stemmen om query's te wijzigen, wordt het aantal uitgegeven updatevergrendelingen efficiënter verminderd. Dit vermindert de kans op blokkeren en impasses.

  • Geïndexeerde weergaven die verwijzen naar meer dan één tabel. Wanneer u een tabel wijzigt waarnaar wordt verwezen in een geïndexeerde weergave, moet de database-engine ook de geïndexeerde weergave behouden. Hiervoor moeten er meer vergrendelingen worden afgesloten en kan dit leiden tot meer blokkeringen en impasses. Geïndexeerde weergaven kunnen er ook toe leiden dat updatebewerkingen intern worden uitgevoerd onder het isolatieniveau voor lezen.

  • Wijzigingen in kolommen waarnaar wordt verwezen in beperkingen voor refererende sleutels. Wanneer u kolommen in een tabel wijzigt waarnaar wordt verwezen in een beperking REFERERENDE SLEUTEL, moet de database-engine zoeken naar gerelateerde rijen in de verwijzende tabel. Rijversies kunnen niet worden gebruikt voor deze leesbewerkingen. In gevallen waarin trapsgewijze updates of verwijderingen zijn ingeschakeld, kan het isolatieniveau worden geëscaleerd naar serializeerbaar gedurende de duur van de instructie om bescherming te bieden tegen fantoominvoegingen.

  • Hints vergrendelen. Zoek naar tabelhints die isolatieniveaus opgeven waarvoor meer vergrendelingen nodig zijn. Deze hints omvatten HOLDLOCK (wat gelijk is aan serialiseerbare), SERIALIZABLE( READCOMMITTEDLOCK waarmee RCSI wordt uitgeschakeld) en REPEATABLEREAD. Daarnaast kunnen hints zoals PAGLOCK, TABLOCKen UPDLOCKXLOCK kunnen de risico's van blokkeringen en impasses toenemen.

    Als deze hints aanwezig zijn, onderzoekt u waarom de hints zijn geïmplementeerd. Deze hints kunnen racevoorwaarden voorkomen en ervoor zorgen dat gegevens geldig zijn. Het is mogelijk om deze hints op de plaats te laten en toekomstige impasses te voorkomen met behulp van een alternatieve methode in de sectie Voorkomen dat een impasse indien nodig opnieuw optreedt in dit artikel.

    Notitie

    Meer informatie over gedrag bij het wijzigen van gegevens met behulp van rijversiebeheer in de handleiding voor transactievergrendeling en rijversiebeheer.

Wanneer u de volledige code voor een transactie bekijkt, hetzij in een uitvoeringsplan of in toepassingsquerycode, zoekt u naar aanvullende problematische patronen:

  • Gebruikersinteractie in transacties. Gebruikersinteractie binnen een expliciete transactie met meerdere instructies verhoogt de duur van transacties aanzienlijk. Dit maakt het waarschijnlijker dat deze transacties elkaar overlappen en dat er blokkeringen en impasses optreden.

    Op dezelfde manier verhoogt het houden van een open transactie en het uitvoeren van query's op een niet-gerelateerde database of systeem mid-transaction de kans op blokkeringen en impasses aanzienlijk.

  • Transacties die toegang hebben tot objecten in verschillende orders. Impasses zijn minder waarschijnlijk wanneer gelijktijdige expliciete transacties met meerdere instructies dezelfde patronen volgen en objecten in dezelfde volgorde openen.

Voorkomen dat een impasse opnieuw optreedt

Er zijn meerdere technieken beschikbaar om te voorkomen dat impasses opnieuw worden uitgevoerd, waaronder het afstemmen van indexen, het afdwingen van plannen met Query Store en het wijzigen van Transact-SQL-query's.

  • Controleer de geclusterde index van de tabel. De meeste tabellen profiteren van geclusterde indexen, maar vaak worden tabellen per ongeluk geïmplementeerd als hoop .

    Een manier om te controleren op een geclusterde index is met behulp van de sp_helpindex systeem opgeslagen procedure. We kunnen bijvoorbeeld een samenvatting van de indexen in de SalesLT.Product tabel bekijken door de volgende instructie uit te voeren:

    exec sp_helpindex 'SalesLT.Product';
    GO
    

    Controleer de kolom index_description. Een tabel kan slechts één geclusterde index hebben. Als een geclusterde index is geïmplementeerd voor de tabel, bevat de index_description het woord 'geclusterd'.

    Als er geen geclusterde index aanwezig is, is de tabel een heap. Controleer in dit geval of de tabel opzettelijk is gemaakt als een heap om een specifiek prestatieprobleem op te lossen. Overweeg om een geclusterde index te implementeren op basis van de richtlijnen voor het ontwerpen van geclusterde indexen.

    In sommige gevallen kan het maken of afstemmen van een geclusterde index blokkeren in impasses verminderen of elimineren. In andere gevallen moet u mogelijk een extra techniek gebruiken, zoals de andere in deze lijst.

  • Niet-geclusterde indexen maken of wijzigen. Het afstemmen van niet-geclusterde indexen kan uw wijzigingsquery's helpen om de gegevens sneller te vinden, waardoor het aantal vereiste updatevergrendelingen wordt verminderd.

    In het voorbeeld van een impasse bevat het queryuitvoeringsplan in Query Store een geclusterde indexscan voor de PK_Product_ProductID index. De impassegrafiek geeft aan dat een gedeelde (S)-vergrendeling wacht op deze index een onderdeel is in de impasse.

    Screenshot of a query execution plan. A clustered index scan is being performed against the PK_Product_ProductID index on the Product table.

    Deze indexscan wordt uitgevoerd omdat onze updatequery een geïndexeerde weergave met de naam vProductAndDescriptionmoet wijzigen. Zoals vermeld in de zoekfunctie voor patronen die het blokkerende gedeelte van dit artikel vergroten, kunnen geïndexeerde weergaven die verwijzen naar meerdere tabellen, de blokkering vergroten en de kans op impasses.

    Als we de volgende niet-geclusterde index maken in de AdventureWorksLT database die de kolommen 'dekt' van SalesLT.Product waarnaar wordt verwezen door de geïndexeerde weergave, helpt dit de query veel efficiënter rijen te vinden:

    CREATE INDEX ix_Product_ProductID_Name_ProductModelID on SalesLT.Product (ProductID, Name, ProductModelID);
    GO
    

    Nadat u deze index hebt gemaakt, treedt de impasse niet meer op.

    Wanneer impasses betrekking hebben op wijzigingen in kolommen waarnaar wordt verwezen in beperkingen voor refererende sleutels, moet u ervoor zorgen dat indexen in de verwijzende tabel van de REFERERENDE SLEUTEL efficiënt gerelateerde rijen vinden.

    Hoewel indexen in sommige gevallen de queryprestaties aanzienlijk kunnen verbeteren, hebben indexen ook overhead- en beheerkosten. Bekijk algemene richtlijnen voor indexontwerp om het voordeel van indexen te beoordelen voordat u indexen maakt, met name brede indexen en indexen op grote tabellen.

  • Beoordeel de waarde van geïndexeerde weergaven. Een andere optie om te voorkomen dat het voorbeeld van een impasse opnieuw optreedt, is door de SalesLT.vProductAndDescription geïndexeerde weergave te verwijderen. Als deze geïndexeerde weergave niet wordt gebruikt, vermindert dit de overhead van het onderhouden van de geïndexeerde weergave in de loop van de tijd.

  • Gebruik isolatie van momentopnamen. In sommige gevallen kan het instellen van het niveau van transactieisolatie op momentopname voor een of meer van de transacties in een impasse verhinderen dat blokkeringen en impasses opnieuw optreden.

    Deze techniek is waarschijnlijk geslaagd wanneer deze wordt gebruikt in SELECT-instructies wanneer de vastgelegde momentopname wordt gelezen, is uitgeschakeld in een database. Wanneer de vastgelegde momentopname voor lezen is uitgeschakeld, vereisen SELECT-query's die gebruikmaken van het isolatieniveau met leesbewerkingen gedeelde (S)-vergrendelingen. Als u isolatie van momentopnamen voor deze transacties gebruikt, hoeft u geen gedeelde vergrendelingen te gebruiken, waardoor blokkeren en impasses kunnen worden voorkomen.

    In databases waarvoor isolatie van vastgelegde momentopnamen is ingeschakeld, vereisen SELECT-query's geen gedeelde (S)-vergrendelingen, zodat impasses waarschijnlijker optreden tussen transacties die gegevens wijzigen. In gevallen waarin impasses optreden tussen meerdere transacties die gegevens wijzigen, kan isolatie van momentopnamen leiden tot een updateconflict in plaats van een impasse. Hiervoor is een van de transacties vereist om de bewerking opnieuw uit te voeren.

  • Dwing een plan af met Query Store. U kunt merken dat een van de query's in de impasse meerdere uitvoeringsplannen heeft en dat de impasse alleen optreedt wanneer een specifiek plan wordt gebruikt. U kunt voorkomen dat de impasse opnieuw optreedt door een plan af te dwingen in Query Store.

  • Wijzig de Transact-SQL. Mogelijk moet u Transact-SQL wijzigen om te voorkomen dat de impasse opnieuw optreedt. Het wijzigen van Transact-SQL moet zorgvuldig worden uitgevoerd en wijzigingen moeten grondig worden getest om ervoor te zorgen dat gegevens correct zijn wanneer wijzigingen gelijktijdig worden uitgevoerd. Overweeg het volgende bij het herschrijven van Transact-SQL:

    • Orderinstructies in transacties, zodat ze toegang hebben tot objecten in dezelfde volgorde.
    • Als u transacties in kleinere transacties opsplitst, indien mogelijk.
    • Gebruik zo nodig queryhints om de prestaties te optimaliseren. U kunt hints toepassen zonder toepassingscode te wijzigen met Behulp van Query Store.

Zoek meer manieren om impasses in de handleiding Impasses te minimaliseren.

Notitie

In sommige gevallen kunt u de impasseprioriteit van een of meer sessies die betrokken zijn bij een impasse aanpassen als het belangrijk is dat een van de sessies succesvol kan worden voltooid zonder opnieuw te proberen, of wanneer een van de query's die betrokken zijn bij de impasse niet kritiek is en altijd als slachtoffer moet worden gekozen. Hoewel dit niet verhindert dat de impasse opnieuw optreedt, kan dit de impact van toekomstige impasses verminderen.

Een XEvents-sessie verwijderen

U kunt een XEvents-sessie verlaten die impassegegevens verzamelt die gedurende lange perioden worden uitgevoerd op kritieke databases. Houd er rekening mee dat als u een doel voor een gebeurtenisbestand gebruikt, dit kan leiden tot grote bestanden als er meerdere impasses optreden. U kunt blobbestanden verwijderen uit Azure Storage voor een actieve trace, met uitzondering van het bestand waarnaar momenteel wordt geschreven.

Wanneer u een XEvents-sessie wilt verwijderen, is de Transact-SQL-sessie hetzelfde, ongeacht het geselecteerde doeltype.

Als u een XEvents-sessie wilt verwijderen, voert u de volgende Transact-SQL uit. Voordat u de code uitvoert, vervangt u de naam van de sessie door de juiste waarde.

ALTER EVENT SESSION [deadlocks] ON DATABASE
    STATE = STOP;
GO

DROP EVENT SESSION [deadlocks] ON DATABASE;
GO

Azure Storage Explorer gebruiken

Azure Storage Explorer is een zelfstandige toepassing die het werken met gebeurtenisbestandsdoelen vereenvoudigt die zijn opgeslagen in blobs in Azure Storage. U kunt Storage Explorer gebruiken voor het volgende:

Download Azure Storage Explorer..

Volgende stappen

Meer informatie over prestaties in Azure SQL Database: