Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Si applica a:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Azure Synapse Analytics
Sistema di Piattaforma Analitica (PDW)
Database SQL in Microsoft Fabric
Questo articolo illustra in dettaglio i deadlock nel motore di database. I deadlock sono generati da blocchi concorrenti e simultanei nel database, spesso presenti in transazioni con più passaggi. Per ulteriori informazioni su blocco delle transazioni e versionamento delle righe, vedere Guida al blocco delle transazioni e al versionamento delle righe.
Per informazioni più specifiche sull'identificazione e la prevenzione dei deadlock nel database SQL di Azure e nel database SQL in Fabric, vedere Analizzare e prevenire deadlock nel database SQL di Azure e nel database SQL di Fabric.
Informazioni sui deadlock
Un deadlock si verifica quando due o più task si bloccano reciprocamente in modo permanente, in quanto ognuno dei task prevede un blocco su una risorsa che gli altri task stanno cercando di bloccare. Per esempio:
La transazione A acquisisce un blocco condiviso sulla riga 1.
La transazione B acquisisce un blocco condiviso sulla riga 2.
La transazione A richiede ora un blocco esclusivo sulla riga 2 ed è bloccata fino al completamento della transazione B e del relativo rilascio del blocco condiviso sulla riga 2.
La transazione B richiede ora un blocco esclusivo sulla riga 1 ed è bloccata fino al completamento della transazione A e del relativo rilascio del blocco condiviso sulla riga 1.
La transazione A non può essere completata fino al completamento della transazione B, ma la transazione B è bloccata dalla transazione A. Questa condizione viene anche denominata dipendenza ciclica: la transazione A è dipendente dalla transazione B e la transazione B chiude il cerchio con una dipendenza rispetto alla transazione A.
Entrambe le transazioni in un deadlock restano in attesa per sempre fino a quando il deadlock non viene interrotto da un processo esterno. Il monitoraggio dei deadlock del motore di database verifica periodicamente la presenza di attività in un deadlock. Se viene rilevata una dipendenza ciclica, una delle attività viene scelta come vittima e le relative transazioni vengono terminate con un errore. In questo modo l'altra attività potrà completare la propria transazione. L'applicazione la cui transazione è stata terminata con un errore può eseguire un nuovo tentativo di transazione, che viene in genere completato al termine dell'altra transazione bloccata dal deadlock.
Spesso la condizione di deadlock viene confusa con il blocco normale. Quando una transazione richiede un blocco in una risorsa bloccata da un'altra transazione, la transazione che ha eseguito la richiesta resta in attesa fino quando il blocco non viene rilasciato. Per impostazione predefinita, le transazioni nel motore del database non scadono, a meno che non LOCK_TIMEOUT sia impostato. La transazione che ha eseguito la richiesta viene bloccata, ma non tramite un deadlock, in quanto non ha tentato di bloccare la transazione proprietaria del blocco. La transazione proprietaria del blocco completa e rilascia il blocco e quindi il blocco viene assegnato alla transazione che ha eseguito la richiesta, che può procedere. I deadlock vengono risolti quasi immediatamente, mentre il bloccaggio può, in teoria, rimanere indefinito. I deadlock sono a volte definiti anche blocchi critici.
Un deadlock si può verificare in qualsiasi sistema con più thread e non soltanto in un sistema di gestione di database relazionali, e può interessare anche risorse diverse dai blocchi negli oggetti di database. Un thread, ad esempio, in un sistema operativo a thread multipli può acquisire una o più risorse, ad esempio blocchi di memoria. Se la risorsa che viene acquisita è già utilizzata da un altro thread, il primo thread deve aspettare che la risorsa target venga rilasciata dal thread di appartenenza. Il thread in attesa è considerato dipendente dal thread proprietario della risorsa richiesta. In un'istanza del motore di database, le sessioni possono bloccarsi durante l'acquisizione di risorse non di database, ad esempio memoria o thread.
Nell'illustrazione la transazione T1 è dipendente dalla transazione T2 per la risorsa di blocco della tabella Part. In modo analogo, la transazione T2 presenta una dipendenza dalla transazione T1 per la risorsa di blocco della tabella Supplier. Poiché queste dipendenze creano un ciclo, si verifica un deadlock tra le transazioni T1 e T2.
Ecco un'illustrazione più generale di un deadlock:
L'attività T1 prevede un blocco sulla risorsa R1, indicato dalla freccia da R1 a T1, e ha richiesto un blocco sulla risorsa R2, indicato dalla freccia da T1 a R2.
L'attività T2 prevede un blocco sulla risorsa R2, indicato dalla freccia da R2 a T2, e ha richiesto un blocco sulla risorsa R1, indicato dalla freccia da T2 a R1.
Poiché nessuna attività può continuare fino a quando una risorsa diventa disponibile e nessuna risorsa può essere rilasciata fino a quando l'attività continua, si verifica una stato di deadlock.
Note
Il motore di database rileva automaticamente i cicli di deadlock. Sceglie una delle transazioni come vittima del deadlock e la termina con un errore per interrompere il deadlock.
Risorse che possono generare un deadlock
Per conto di ogni sessione utente possono essere in esecuzione uno o più task e ogni task può acquisire o attendere di acquisire risorse. Di seguito sono elencati i tipi di risorse che possono causare blocchi che potrebbero provocare un deadlock.
Locks. L'attesa di acquisizione di blocchi sulle risorse, ad esempio oggetti, pagine, righe, metadati e applicazioni, può generare un deadlock. Ad esempio, la transazione T1 ha un blocco condiviso (
S) sulla riga r1 ed è in attesa di ottenere un blocco esclusivo (X) su r2. Transaction T2 ha un blocco condiviso (S) su r2 ed è in attesa di ottenere un blocco esclusivo (X) sulla riga r1. Il risultato è un ciclo di blocco in cui T1 e T2 attendono che le risorse bloccate vengano rilasciate dall'altra attività.Thread di lavoro. Un'attività in coda in attesa di un thread di lavoro disponibile può generare un deadlock. Se l'attività in coda è proprietaria di risorse che bloccano tutti i thread di lavoro, si verifica un deadlock. Ad esempio, la sessione S1 avvia una transazione e acquisisce un blocco condiviso (
S) sulla riga r1 e quindi passa alla sospensione. Le sessioni attive in esecuzione in tutti i thread di lavoro disponibili tentano di acquisire blocchi esclusivi (X) sulla riga r1. Poiché la sessione S1 non riesce ad acquisire un thread di lavoro, non può eseguire la transazione e rilasciare il blocco sulla riga r1. Di conseguenza, si verifica un deadlock.Memory. Quando richieste simultanee sono in attesa di concessioni di memoria che non possono essere soddisfatte con la memoria disponibile, può verificarsi un deadlock. Due query simultanee, Q1 e Q2, vengono ad esempio eseguite come funzioni definite dall'utente che acquisiscono rispettivamente 10 MB e 20 MB di memoria. Se per ogni query sono necessari 30 MB e la memoria disponibile totale è di 20 MB, Q1 e Q2 devono attendere che ognuna rilasci memoria e di conseguenza si verifica un deadlock.
Risorse per l'esecuzione di query in parallelo. Thread coordinator, producer o utente associati a una porta di scambio possono bloccarsi a vicenda generando un deadlock, di solito quando almeno un altro processo che non fa parte della query parallela è incluso. Inoltre, quando una query parallela avvia l'esecuzione, il motore di database determina il grado di parallelismo e il numero di thread di lavoro necessari, in base al carico di lavoro corrente. Se il carico di lavoro del sistema cambia inaspettatamente, ad esempio per l'avvio di nuove query o per l'esaurimento dei thread di lavoro, è possibile che si verifichi un deadlock.
Risorse MARS (Multiple Active Result Sets). Queste risorse sono utilizzate per controllare in che modo più richieste attive vengono intercalate con il servizio MARS. Per ulteriori informazioni. Per altre informazioni, vedere Uso di MARS (Multiple Active Result Set) in SQL Server Native Client.
Risorsa utente. Quando un thread è in attesa di una risorsa che è potenzialmente controllata da un'applicazione utente, la risorsa viene considerata risorsa esterna o utente e viene trattata come un blocco.
Sessione mutex Le attività in esecuzione in una sessione vengono intercalate, ovvero solo un'attività può essere eseguita in una sessione in un determinato momento. Per poter essere eseguita, l'attività deve disporre di accesso esclusivo al mutex della sessione.
Mutex delle transazioni. Tutte le attività in esecuzione in una transazione vengono intercalate, ovvero solo un'attività può essere eseguita in una transazione in un determinato momento. Per poter essere eseguita, l'attività deve disporre di accesso esclusivo al mutex della transazione.
Per essere eseguita in un servizio MARS, l'attività deve acquisire il mutex della sessione. Se l'attività è in esecuzione in una transazione, deve acquisire il mutex della transazione. Questo consente di garantire che sia attiva una sola attività per volta in una determinata sessione e in una determinata transazione. Dopo che i mutex richiesti sono stati acquisiti, l'attività può essere eseguita. Quando l'attività termine, oppure restituisce il risultato a metà della richiesta, viene rilasciato prima il mutex della transazione, seguito da quello della sessione, in ordine inverso rispetto a quello di acquisizione. In queste risorse, tuttavia, possono verificarsi deadlock. Il seguente esempio di pseudocodice mostra due task, richiesta utente U1 e richiesta utente U2, in esecuzione nella stessa sessione.
U1: Rs1=Command1.Execute("insert sometable EXEC usp_someproc"); U2: Rs2=Command2.Execute("select colA from sometable");La stored procedure in esecuzione dall'attività richiesta utente U1 ha acquisito il mutex della sessione. Se l'esecuzione della stored procedure richiede molto tempo, il motore di database presuppone che la stored procedure sia in attesa di input dall'utente. La richiesta utente U2 è in attesa del mutex della sessione mentre l'utente è in attesa del set di risultati da U2 e U1 è in attesa di una risorsa utente. La rappresentazione logica di tale condizione di deadlock è la seguente:
I deadlock possono verificarsi anche quando una tabella è partizionata e l'impostazione LOCK_ESCALATION di ALTER TABLE è impostata su AUTO. Quando LOCK_ESCALATION è impostato su AUTO, la concorrenza aumenta consentendo al motore di database di bloccare le partizioni di tabella a livello di HoBT anziché a livello di tabella. Tuttavia, quando transazioni separate contengono blocchi di partizioni in una tabella e richiedono un blocco in un punto nella partizione delle altre transazioni, si verifica un deadlock. Questo tipo di deadlock può essere evitato impostando LOCK_ESCALATION su TABLE. Tuttavia, questa impostazione riduce la concorrenza forzando gli aggiornamenti di grandi dimensioni in una partizione ad attendere un blocco di tabella.
Rilevamento deadlock
Tutte le risorse elencate nella sezione Risorse che possono causare deadlock partecipano allo schema di rilevamento dei deadlock del motore di database. Il rilevamento dei deadlock viene eseguito da un thread di monitoraggio blocchi che avvia periodicamente una ricerca attraverso tutte le attività di un'istanza del Database Engine. Il processo di ricerca è descritto dai punti seguenti:
L'intervallo predefinito è 5 secondi.
Se tramite il thread di monitoraggio dei blocchi vengono individuati deadlock, l'intervallo di rilevamento dei deadlock scende da 5 secondi a un minimo di 100 millisecondi, in base alla frequenza dei deadlock.
Se il thread di monitoraggio dei blocchi smette di trovare deadlock, il Motore di Database aumenta gli intervalli tra le ricerche a 5 secondi.
Se viene rilevato un deadlock, si presuppone che i nuovi thread che devono attendere un blocco entrino nel ciclo di deadlock. La prima coppia di attese di blocco dopo il rilevamento di un deadlock genera immediatamente una ricerca di deadlock senza che venga atteso l'intervallo successivo di rilevamento dei deadlock. Se, ad esempio, l'intervallo attuale è di 5 secondi ed è appena stato rilevato un deadlock, l'attesa di blocco successiva provoca l'avvio immediato della funzionalità di rilevamento di deadlock. Se l'attesa del blocco fa parte di un deadlock, viene rilevata immediatamente, anziché durante la ricerca del deadlock successiva.
Il motore di database esegue in genere solo il rilevamento periodico dei deadlock. Poiché il numero di deadlock rilevati nel sistema è in genere ridotto, il rilevamento periodico dei deadlock consente di ridurre il sovraccarico del rilevamento dei deadlock nel sistema.
Dopo l'avvio di una ricerca di deadlock per un thread specifico, viene identificata la risorsa di cui il thread è in attesa e vengono individuati il proprietario o i proprietari della risorsa. La ricerca di deadlock viene quindi ripetuta in modo ricorsivo per gli stessi thread fino all'individuazione di un ciclo. Un ciclo identificato in questo modo crea un deadlock.
Dopo aver rilevato un deadlock, il motore di database termina un deadlock scegliendo uno dei thread come vittima del deadlock. Il motore di database termina il batch corrente eseguito per il thread, esegue il rollback della transazione della vittima del deadlock e restituisce l'errore 1205 all'applicazione. Tramite il rollback della transazione per la vittima del deadlock vengono rilasciati tutti i blocchi della transazione. In questo modo, le transazioni degli altri thread vengono sbloccate e possono continuare. L'errore 1205 (vittima del deadlock) registra informazioni sul tipo di risorse coinvolte in un deadlock.
Per impostazione predefinita, il motore di database sceglie come vittima del deadlock la transazione meno costosa da ripristinare. In alternativa, è possibile specificare la priorità delle sessioni in una situazione di deadlock usando l'istruzione SET DEADLOCK_PRIORITY.
DEADLOCK_PRIORITYpuò essere impostato su , LOWo NORMALoppure in alternativa può essere impostato HIGHsu qualsiasi valore intero compreso nell'intervallo compreso tra -10 e 10. In alcuni casi, il motore di database potrebbe scegliere di modificare la priorità del deadlock per una breve durata per ottenere una concorrenza migliore.
Per impostazione predefinita, la priorità del deadlock è NORMAL, o 0. Se due sessioni hanno priorità di deadlock diverse, la transazione nella sessione con la priorità più bassa viene scelta come vittima del deadlock. Se entrambe le sessioni hanno la stessa priorità di deadlock, viene scelta la transazione meno costosa da annullare. Se le sessioni coinvolte nel ciclo di deadlock hanno la stessa priorità di deadlock e lo stesso costo, la vittima viene scelta in modo casuale. Un'attività in cui è in corso l'esecuzione del rollback non può essere scelta come vittima del deadlock.
Quando si usa Common Language Runtime (CLR), il monitoraggio dei deadlock rileva automaticamente i deadlock per le risorse di sincronizzazione (monitoraggi, blocco lettore/writer e join di thread) a cui si accede all'interno di procedure gestite. Il deadlock viene tuttavia risolto generando un'eccezione nella procedura selezionata come vittima del deadlock. È importante comprendere che l'eccezione non comporta il rilascio automatico delle risorse attualmente di proprietà della vittima, ma le risorse devono essere rilasciate esplicitamente. In modo coerente con il comportamento dell'eccezione, l'eccezione utilizzata per identificare una vittima del deadlock può essere intercettata e ignorata.
Strumenti di informazione sui deadlock
Per visualizzare le informazioni sui deadlock, il motore di database fornisce strumenti di monitoraggio sotto forma di xml_deadlock_report evento esteso, due flag di traccia e l'evento deadlock graph in SQL Profiler.
L'xml_deadlock_report evento esteso è il metodo consigliato per l'acquisizione di informazioni sui deadlock.
Evento esteso di stallo
In SQL Server 2012 (11.x) e versioni successive, l'evento xml_deadlock_report esteso deve essere usato anziché la classe di evento deadlock graph in Traccia SQL o SQL Profiler.
La sessione eventi system_health acquisisce xml_deadlock_report gli eventi per impostazione predefinita. Questi eventi contengono il grafico deadlock. Poiché la system_health sessione è abilitata per impostazione predefinita, non è necessario configurare una sessione eventi separata per acquisire informazioni sui deadlock.
L'evento Deadlock Graph acquisito include in genere tre nodi distinti:
-
victim-list. Identificatore di processo della vittima del deadlock. -
process-list. Informazioni su tutti i processi coinvolti nel deadlock. -
resource-list. Informazioni sulle risorse coinvolte nel deadlock.
È possibile visualizzare i event_file dati di destinazione della system_health sessione in Management Studio.
xml_deadlock_report Se si verificano eventi, Management Studio presenta una rappresentazione grafica delle attività e delle risorse coinvolte in un deadlock, come illustrato nell'esempio seguente:
La query seguente può visualizzare tutti gli eventi deadlock acquisiti dalla ring_buffer destinazione della system_health sessione:
SELECT xdr.value('@timestamp', 'datetime') AS deadlock_time,
xdr.query('.') AS event_data
FROM (SELECT CAST ([target_data] AS XML) AS target_data
FROM sys.dm_xe_session_targets AS xt
INNER JOIN sys.dm_xe_sessions AS xs
ON xs.address = xt.event_session_address
WHERE xs.name = N'system_health'
AND xt.target_name = N'ring_buffer') AS XML_Data
CROSS APPLY Target_Data.nodes('RingBufferTarget/event[@name="xml_deadlock_report"]') AS XEventData(xdr)
ORDER BY deadlock_time DESC;
Il set di risultati è il seguente.
Nell'esempio seguente viene illustrato un esempio dell'output della event_data colonna :
<event name="xml_deadlock_report" package="sqlserver" timestamp="2022-02-18T08:26:24.698Z">
<data name="xml_report">
<type name="xml" package="package0" />
<value>
<deadlock>
<victim-list>
<victimProcess id="process27b9b0b9848" />
</victim-list>
<process-list>
<process id="process27b9b0b9848" taskpriority="0" logused="0" waitresource="KEY: 5:72057594214350848 (1a39e6095155)" waittime="1631" ownerId="11088595" transactionname="SELECT" lasttranstarted="2022-02-18T00:26:23.073" XDES="0x27b9f79fac0" lockMode="S" schedulerid="9" kpid="15336" status="suspended" spid="62" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2022-02-18T00:26:22.893" lastbatchcompleted="2022-02-18T00:26:22.890" lastattention="1900-01-01T00:00:00.890" clientapp="SQLCMD" hostname="ContosoServer" hostpid="7908" loginname="CONTOSO\user" isolationlevel="read committed (2)" xactid="11088595" currentdb="5" lockTimeout="4294967295" clientoption1="538968096" clientoption2="128056">
<executionStack>
<frame procname="AdventureWorks2022.dbo.p1" line="3" stmtstart="78" stmtend="180" sqlhandle="0x0300050020766505ca3e07008ba8000001000000000000000000000000000000000000000000000000000000">
SELECT c2, c3 FROM t1 WHERE c2 BETWEEN @p1 AND @p1+ </frame>
<frame procname="adhoc" line="4" stmtstart="82" stmtend="98" sqlhandle="0x020000006263ec01ebb919c335024a072a2699958d3fcce60000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
SET NOCOUNT ON
WHILE (1=1)
BEGIN
EXEC p1 4
END
</inputbuf>
</process>
<process id="process27b9ee33c28" taskpriority="0" logused="252" waitresource="KEY: 5:72057594214416384 (e5b3d7e750dd)" waittime="1631" ownerId="11088593" transactionname="UPDATE" lasttranstarted="2022-02-18T00:26:23.073" XDES="0x27ba15a4490" lockMode="X" schedulerid="6" kpid="5584" status="suspended" spid="58" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2022-02-18T00:26:22.890" lastbatchcompleted="2022-02-18T00:26:22.890" lastattention="1900-01-01T00:00:00.890" clientapp="SQLCMD" hostname="ContosoServer" hostpid="15316" loginname="CONTOSO\user" isolationlevel="read committed (2)" xactid="11088593" currentdb="5" lockTimeout="4294967295" clientoption1="538968096" clientoption2="128056">
<executionStack>
<frame procname="AdventureWorks2022.dbo.p2" line="3" stmtstart="76" stmtend="150" sqlhandle="0x03000500599a5906ce3e07008ba8000001000000000000000000000000000000000000000000000000000000">
UPDATE t1 SET c2 = c2+1 WHERE c1 = @p </frame>
<frame procname="adhoc" line="4" stmtstart="82" stmtend="98" sqlhandle="0x02000000008fe521e5fb1099410048c5743ff7da04b2047b0000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
SET NOCOUNT ON
WHILE (1=1)
BEGIN
EXEC p2 4
END
</inputbuf>
</process>
</process-list>
<resource-list>
<keylock hobtid="72057594214350848" dbid="5" objectname="AdventureWorks2022.dbo.t1" indexname="cidx" id="lock27b9dd26a00" mode="X" associatedObjectId="72057594214350848">
<owner-list>
<owner id="process27b9ee33c28" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process27b9b0b9848" mode="S" requestType="wait" />
</waiter-list>
</keylock>
<keylock hobtid="72057594214416384" dbid="5" objectname="AdventureWorks2022.dbo.t1" indexname="idx1" id="lock27afa392600" mode="S" associatedObjectId="72057594214416384">
<owner-list>
<owner id="process27b9b0b9848" mode="S" />
</owner-list>
<waiter-list>
<waiter id="process27b9ee33c28" mode="X" requestType="wait" />
</waiter-list>
</keylock>
</resource-list>
</deadlock>
</value>
</data>
</event>
Flag di traccia 1204 e flag di traccia 1222
Quando si verificano deadlock e sono abilitati i flag di traccia 1204 o 1222, i dettagli del deadlock vengono segnalati nel registro errori di SQL Server. Il flag di traccia 1204 segnala informazioni sul deadlock formattate da ogni nodo coinvolto nel deadlock. Il flag di traccia 1222 formatta le informazioni sui deadlock, prima dai processi e quindi dalle risorse. È possibile attivare entrambi i flag di traccia per ottenere due diverse rappresentazioni dello stesso evento di deadlock.
Important
Evitare di usare i flag di traccia 1204 e 1222 nei sistemi ad alta intensità di carico che riscontrano deadlock. L'uso di questi flag di traccia può comportare problemi di prestazioni. Usare invece l'evento esteso Deadlock per acquisire le informazioni necessarie.
Oltre a definire le proprietà dei flag di traccia 1204 e 1222, la tabella seguente illustra anche le analogie e le differenze.
| Property | Flag di traccia 1204 e flag di traccia 1222 | Solo flag di traccia 1204 | Solo flag di traccia 1222 |
|---|---|---|---|
| Formato di output | L'output viene acquisito nel log degli errori di SQL Server. | Mirato ai nodi interessati dal deadlock. Ogni nodo ha una sezione dedicata e la sezione finale descrive la vittima del deadlock. | Restituisce informazioni in un formato simile all'XML ma non conforme a uno schema XSD (XML Schema Definition). Il formato presenta tre sezioni principali. Nella prima sezione viene dichiarata la vittima del deadlock. Nella seconda sezione viene descritto ogni processo interessato dal deadlock. La terza sezione descrive le risorse che sono equivalenti a nodi nella flag di traccia 1204. |
| Identificazione degli attributi |
SPID:<x> ECID:<x>. Identifica il thread ID sessione nei casi di processi paralleli. La voce SPID:<x> ECID:0, dove <x> viene sostituita dal valore di SPID, rappresenta il thread principale. La voce SPID:<x> ECID:<y>, dove <x> viene sostituita dal valore SPID ed <y> è maggiore di 0, rappresenta il contesto di esecuzione per lo stesso SPID.BatchID (sbid per il flag di traccia 1222). Identifica il batch da cui l'esecuzione del codice richiede o mantiene un blocco. Quando MARS (Multiple Active Result Set) è disabilitato, il valore di BatchID è 0. Quando MARS è abilitato, il valore per i batch attivi è compreso tra 1 e n. Se la sessione non contiene batch attivi, BatchID è 0.Mode Specifica il tipo di blocco per una determinata risorsa richiesta, concessa o attesa da un thread. La modalità può essere Intento Condiviso (IS), Condiviso (S), Aggiornamento (U), Intento Esclusivo (IX), Condiviso con Intento Esclusivo (SIX) e Esclusivo (X).Line # (line per il flag di traccia 1222). Elenca il numero di riga del batch di istruzioni corrente che era in esecuzione quando si è verificato il deadlock.Input Buf (inputbuf per il flag di traccia 1222). Elenca tutte le istruzioni del batch corrente. |
Node Rappresenta il numero di voce nella catena del deadlock.Lists Il proprietario del blocco può essere parte degli elenchi seguenti:Grant List Enumera i proprietari correnti della risorsa.Convert List Enumera i proprietari correnti che stanno tentando di convertire i propri blocchi a un livello superiore.Wait List Enumera le nuove richieste di blocco correnti per la risorsa.Statement Type Descrive il tipo di istruzione (SELECT, INSERT, UPDATEo DELETE) in cui i thread dispongono delle autorizzazioni.Victim Resource Owner Specifica il thread partecipante scelto dal motore di database come vittima per interrompere il ciclo di deadlock. Il thread scelto e tutti i relativi contesti di esecuzione vengono terminati.Next Branch Rappresenta i due o più contesti di esecuzione dello stesso SPID coinvolto nel ciclo di deadlock. |
deadlock victim rappresenta l'indirizzo di memoria fisica del task (vedere sys.dm_os_tasks) selezionato come vittima del deadlock. Il valore potrebbe essere zero nel caso di un deadlock non risolto.executionstack Rappresenta lo stack di chiamate Transact-SQL che viene eseguito al momento in cui si verifica il deadlock.priority Rappresenta la priorità del deadlock.logused Spazio del log utilizzato dal task.owner id ID della transazione che ha il controllo della richiesta.status Stato del task. Per altre informazioni, vedere sys.dm_os_tasks.waitresource Risorsa necessaria per il task.waittime Tempo, in millisecondi, di attesa per la risorsa.schedulerid Il pianificatore associato a questo compito. Vedere sys.dm_os_schedulers.hostname Nome della workstation.isolationlevel Livello di isolamento della transazione corrente.Xactid ID della transazione che ha il controllo della richiesta.currentdb ID del database.lastbatchstarted Ultima volta in cui un processo client ha avviato un'esecuzione del batch.lastbatchcompleted Ultima volta in cui un processo client ha completato un'esecuzione del batch.clientoption1 e clientoption2 Le opzioni impostate in questa sessione. Questi valori sono maschere di bit che rappresentano le opzioni di solito controllate da istruzioni come SET, SET NOCOUNT, e SET XACTABORT. Per altre informazioni, vedere @@OPTIONS.associatedObjectId Rappresenta l'ID di HoBT (heap o albero B). |
| Attributi risorsa |
RID identifica la singola riga di una tabella su cui un blocco viene mantenuto o richiesto. RID è rappresentato come RID: db_id:file_id:page_no:row_no. Ad esempio: RID: 6:1:20789:0.OBJECT identifica la tabella su cui un blocco viene mantenuto o richiesto.
OBJECT è rappresentata come OBJECT: db_id:object_id. Ad esempio: TAB: 6:2009058193.KEY Identifica l'intervallo di chiavi di un indice su cui un blocco viene mantenuto o richiesto. KEY è rappresentato come KEY: db_id:hobt_id (valore hash della chiave di indice). Ad esempio: KEY: 6:72057594057457664 (350007a4d329).PAG Identifica la risorsa di pagina su cui un blocco viene mantenuto o richiesto.
PAG è rappresentata come PAG: db_id:file_id:page_no. Ad esempio: PAG: 6:1:20789.EXT Identifica la struttura extent.
EXT è rappresentata come EXT: db_id:file_id:extent_no. Ad esempio: EXT: 6:1:9.DB Identifica il blocco del database.
DB è rappresentato in uno dei modi seguenti:DB: db_idDB: db_id[BULK-OP-DB], che identifica il blocco del database eseguito dal backup del database.DB: db_id[BULK-OP-LOG], che identifica il blocco eseguito dal backup del log.APP Rileva un blocco dell'applicazione.
APP è rappresentata come APP: lock_resource. Ad esempio: APP: Formf370f478.METADATA Rappresenta le risorse di metadati interessate da un deadlock. Poiché METADATA ha molte sottorisorse, il valore restituito dipende dalla sottorisorsa interessata dal deadlock. Ad esempio METADATA.USER_TYPE restituisce user_type_id = *integer_value*. Per altre informazioni sulle risorse e le sottorisorse METADATA, vedere sys.dm_tran_locks.HOBT Rappresenta un heap o albero B interessato da un deadlock. |
Nessuna esclusiva di questo flag di traccia. | Nessuna esclusiva di questo flag di traccia. |
Esempio di trace flag 1204
L'esempio seguente mostra l'output quando il flag di traccia 1204 è attivato. In questo caso, la tabella in Node 1 è un heap senza indici e la tabella in Node 2 è un heap con un indice non cluster. La chiave di indice in Node 2 è in corso di aggiornamento quando si verifica il deadlock.
Deadlock encountered .... Printing deadlock information
Wait-for graph
Node:1
RID: 6:1:20789:0 CleanCnt:3 Mode:X Flags: 0x2
Grant List 0:
Owner:0x0315D6A0 Mode: X
Flg:0x0 Ref:0 Life:02000000 SPID:55 ECID:0 XactLockInfo: 0x04D9E27C
SPID: 55 ECID: 0 Statement Type: UPDATE Line #: 6
Input Buf: Language Event:
BEGIN TRANSACTION
EXEC usp_p2
Requested By:
ResType:LockOwner Stype:'OR'Xdes:0x03A3DAD0
Mode: U SPID:54 BatchID:0 ECID:0 TaskProxy:(0x04976374) Value:0x315d200 Cost:(0/868)
Node:2
KEY: 6:72057594057457664 (350007a4d329) CleanCnt:2 Mode:X Flags: 0x0
Grant List 0:
Owner:0x0315D140 Mode: X
Flg:0x0 Ref:0 Life:02000000 SPID:54 ECID:0 XactLockInfo: 0x03A3DAF4
SPID: 54 ECID: 0 Statement Type: UPDATE Line #: 6
Input Buf: Language Event:
BEGIN TRANSACTION
EXEC usp_p1
Requested By:
ResType:LockOwner Stype:'OR'Xdes:0x04D9E258
Mode: U SPID:55 BatchID:0 ECID:0 TaskProxy:(0x0475E374) Value:0x315d4a0 Cost:(0/380)
Victim Resource Owner:
ResType:LockOwner Stype:'OR'Xdes:0x04D9E258
Mode: U SPID:55 BatchID:0 ECID:0 TaskProxy:(0x0475E374) Value:0x315d4a0 Cost:(0/380)
Esempio del trace flag 1222
L'esempio seguente mostra l'output quando il flag di traccia 1222 è attivato. In questo caso, una tabella è un heap senza indici e l'altra tabella è un heap con un indice non cluster. Nella seconda tabella, la chiave di indice è in corso di aggiornamento quando si verifica il deadlock.
deadlock-list
deadlock victim=process689978
process-list
process id=process6891f8 taskpriority=0 logused=868
waitresource=RID: 6:1:20789:0 waittime=1359 ownerId=310444
transactionname=user_transaction
lasttranstarted=2022-02-05T11:22:42.733 XDES=0x3a3dad0
lockMode=U schedulerid=1 kpid=1952 status=suspended spid=54
sbid=0 ecid=0 priority=0 transcount=2
lastbatchstarted=2022-02-05T11:22:42.733
lastbatchcompleted=2022-02-05T11:22:42.733
clientapp=Microsoft SQL Server Management Studio - Query
hostname=TEST_SERVER hostpid=2216 loginname=DOMAIN\user
isolationlevel=read committed (2) xactid=310444 currentdb=6
lockTimeout=4294967295 clientoption1=671090784 clientoption2=390200
executionStack
frame procname=AdventureWorks2022.dbo.usp_p1 line=6 stmtstart=202
sqlhandle=0x0300060013e6446b027cbb00c69600000100000000000000
UPDATE T2 SET COL1 = 3 WHERE COL1 = 1;
frame procname=adhoc line=3 stmtstart=44
sqlhandle=0x01000600856aa70f503b8104000000000000000000000000
EXEC usp_p1
inputbuf
BEGIN TRANSACTION
EXEC usp_p1
process id=process689978 taskpriority=0 logused=380
waitresource=KEY: 6:72057594057457664 (350007a4d329)
waittime=5015 ownerId=310462 transactionname=user_transaction
lasttranstarted=2022-02-05T11:22:44.077 XDES=0x4d9e258 lockMode=U
schedulerid=1 kpid=3024 status=suspended spid=55 sbid=0 ecid=0
priority=0 transcount=2 lastbatchstarted=2022-02-05T11:22:44.077
lastbatchcompleted=2022-02-05T11:22:44.077
clientapp=Microsoft SQL Server Management Studio - Query
hostname=TEST_SERVER hostpid=2216 loginname=DOMAIN\user
isolationlevel=read committed (2) xactid=310462 currentdb=6
lockTimeout=4294967295 clientoption1=671090784 clientoption2=390200
executionStack
frame procname=AdventureWorks2022.dbo.usp_p2 line=6 stmtstart=200
sqlhandle=0x030006004c0a396c027cbb00c69600000100000000000000
UPDATE T1 SET COL1 = 4 WHERE COL1 = 1;
frame procname=adhoc line=3 stmtstart=44
sqlhandle=0x01000600d688e709b85f8904000000000000000000000000
EXEC usp_p2
inputbuf
BEGIN TRANSACTION
EXEC usp_p2
resource-list
ridlock fileid=1 pageid=20789 dbid=6 objectname=AdventureWorks2022.dbo.T2
id=lock3136940 mode=X associatedObjectId=72057594057392128
owner-list
owner id=process689978 mode=X
waiter-list
waiter id=process6891f8 mode=U requestType=wait
keylock hobtid=72057594057457664 dbid=6 objectname=AdventureWorks2022.dbo.T1
indexname=nci_T1_COL1 id=lock3136fc0 mode=X
associatedObjectId=72057594057457664
owner-list
owner id=process6891f8 mode=X
waiter-list
waiter id=process689978 mode=U requestType=wait
Evento Deadlock Graph di Profiler
SQL Profiler ha un evento che presenta una rappresentazione grafica delle attività e delle risorse coinvolte in un deadlock. L'esempio seguente illustra l'output prodotto da SQL Profiler quando l'evento Deadlock Graph è attivo.
Le funzionalità SQL Profiler e Traccia SQL sono deprecate e sostituite da Eventi Estesi. Gli eventi estesi hanno un sovraccarico delle prestazioni inferiore ed è più configurabile rispetto a Traccia SQL. Prendere in considerazione l'uso dell'evento di deadlock degli Extended Events invece di tracciare i deadlock in SQL Profiler.
Per altre informazioni sull'evento deadlock, vedere Classe di evento Lock:Deadlock. Per altre informazioni sui grafici deadlock di SQL Profiler, vedere Salvare grafici deadlock (SQL Server Profiler).
Gli Extended Events forniscono equivalenti alle classi evento di SQL Trace. Per altre informazioni, vedere Visualizzare gli eventi estesi equivalenti alle classi di evento di traccia SQL. Gli eventi estesi sono consigliati al posto della traccia SQL.
Gestire i deadlock
Quando un'istanza del motore di database sceglie una transazione come vittima del deadlock, termina il batch corrente, esegue il rollback della transazione e restituisce l'errore 1205 all'applicazione. Il messaggio restituito è strutturato come segue:
Your transaction (process ID #...) was deadlocked on {lock | communication buffer | thread} resources with another process and has been chosen as the deadlock victim. Rerun your transaction.
Poiché qualsiasi applicazione che invia Transact-SQL query può essere scelta come vittima del deadlock, le applicazioni devono avere un gestore errori in grado di gestire l'errore 1205. Se un'applicazione non gestisce l'errore, l'applicazione può continuare a non essere a conoscenza del rollback della transazione.
L'implementazione di un gestore errori che intercetta l'errore 1205 consente a un'applicazione di gestire i deadlock ed eseguire un'azione correttiva, ad esempio reinserito automaticamente la query coinvolta nel deadlock.
È consigliabile sospendere brevemente l'applicazione prima di reinviarne la query. In questo modo, l'altra transazione coinvolta nel deadlock ha la possibilità di completare e rilasciare i blocchi. La sequenza casuale della durata della pausa riduce al minimo la probabilità di ricorsione del deadlock quando la query sottoposta di nuovo richiede i blocchi. Ad esempio, il gestore degli errori potrebbe essere codificato per sospendere per una durata casuale compresa tra uno e tre secondi.
Gestire con TRY... CATCH
È possibile usare TRY... CATCH per gestire i deadlock. L'errore 1205 può essere intercettato dal blocco CATCH.
Per altre informazioni, vedere Gestione dei deadlock.
Ridurre al minimo i blocchi deadlock
I deadlock non possono essere evitati completamente. È tuttavia possibile ridurre il rischio di insorgenza di un deadlock attenendosi a determinate convenzioni di scrittura codice. La riduzione del numero di deadlock comporta un aumento della velocità effettiva delle transazioni e una diminuzione dell'overhead del sistema, in quanto il numero di transazioni su cui è necessario eseguire le operazioni seguenti risulta minimo:
- Rollback, con il conseguente annullamento del lavoro eseguito.
- Riesecuzione tramite l'applicazione, in quanto in corrispondenza del deadlock è stato eseguito il rollback.
Per ridurre il numero di deadlock, è possibile:
- Accedere sempre agli oggetti in base allo stesso ordine.
- Escludere l'interazione dell'utente nelle transazioni.
- Ridurre la lunghezza delle transazioni e inserirle in un solo batch.
- Evitare livelli di isolamento più elevati,
REPEATABLE READad esempio eSERIALIZABLEquando non necessario. - Utilizzare un livello di isolamento basato sul controllo delle versioni delle righe.
- Abilitare l'opzione del database
READ_COMMITTED_SNAPSHOTper utilizzare il versionamento delle righe per le transazioni con il livello di isolamentoREAD COMMITTED. - Usare le transazioni di isolamento dello snapshot.
- Abilitare l'opzione del database
- Usare connessioni legate.
Accedere agli oggetti in base allo stesso ordine
Se tutte le transazioni simultanee accedono agli oggetti nello stesso ordine, la possibilità che si verifichi un deadlock risulta notevolmente ridotta. Se, ad esempio, due transazioni simultanee ottengono un blocco prima nella tabella Supplier, quindi nella tabella Part, una transazione rimane bloccata sulla tabella Supplier fino al completamento dell'altra transazione. Dopo il commit o il rollback della prima transazione, l'esecuzione della seconda continua e non si verifica alcun deadlock. L'utilizzo di stored procedure per tutte le modifiche ai dati consente di standardizzare l'ordine di accesso agli oggetti.
Escludere l'interazione dell'utente nelle transazioni
Evitare transazioni che includono l'interazione dell'utente, perché la velocità dei batch in esecuzione senza l'intervento dell'utente è molto più veloce rispetto alla velocità con cui un utente deve rispondere manualmente alle query, ad esempio rispondere a una richiesta di un parametro richiesto da un'applicazione. Questa situazione comporta una riduzione della velocità effettiva del sistema, in quanto i blocchi mantenuti attivi dalla transazione vengono rilasciati solo in corrispondenza del commit o del rollback della transazione. Anche se non si verifica un deadlock, altre transazioni che accedono alle stesse risorse vengono bloccate durante l'attesa del completamento della transazione.
Ridurre la lunghezza delle transazioni e inserirle in un solo batch.
Il deadlock si verifica in genere quando nello stesso database vengono eseguite contemporaneamente numerose transazioni estese. La lunghezza della transazione è direttamente proporzionale alla durata dei blocchi esclusivi o di aggiornamento che bloccano qualsiasi altra attività e che possono generare una situazione di deadlock.
Mantenere le transazioni in un batch riduce al minimo i round trip di rete durante una transazione, riducendo i possibili ritardi nel completamento della transazione a causa dell'elaborazione client.
Evitare livelli di isolamento più elevati
È importante determinare se una transazione è eseguibile a un livello di isolamento inferiore. L'utilizzo READ COMMITTED consente a una transazione di leggere i dati letti in precedenza (ma non modificati) da un'altra transazione senza attendere il completamento della transazione.
READ COMMITTED detiene blocchi condivisi per una durata più breve rispetto a un livello di isolamento superiore, ad esempio SERIALIZABLE. Ciò riduce la contesa di blocco.
Utilizzare un livello di isolamento basato sul controllo delle versioni delle righe
Quando l'opzione READ_COMMITTED_SNAPSHOT di database è impostata ON, una transazione in esecuzione nel livello di isolamento READ COMMITTED usa il versioning delle righe anziché i blocchi condivisi durante le operazioni di lettura.
Suggerimento
Microsoft consiglia il livello di isolamento basato sul versionamento delle righe READ COMMITTED per tutte le applicazioni, a meno che un'applicazione non si basi sul comportamento di blocco del livello di isolamento READ COMMITTED.
Anche il livello di isolamento dello snapshot utilizza il controllo delle versioni delle righe, che non si avvale dei blocchi condivisi durante le operazioni di lettura. Affinché sia possibile eseguire transazioni con il livello di isolamento dello snapshot, è necessario impostare l'opzione di database ALLOW_SNAPSHOT_ISOLATION su ON.
Usare i livelli di isolamento basati sul controllo delle versioni delle righe per ridurre al minimo i deadlock che possono verificarsi tra operazioni di lettura e scrittura.
Usare le connessioni associate
L'utilizzo di connessioni associate garantisce la cooperazione tra due o più connessioni aperte dalla stessa applicazione. I blocchi acquisiti dalle connessioni secondarie vengono gestiti come se fossero stati acquisiti dalla connessione primaria e viceversa. Pertanto, non si bloccano l'un l'altro.
Generare un deadlock
Potrebbe essere necessario causare un deadlock a scopo di apprendimento o dimostrazione.
L'esempio AdventureWorksLT2019 seguente funziona nel database di esempio con lo schema e i dati predefiniti quando READ_COMMITTED_SNAPSHOT è stato abilitato. Per scaricare questo esempio, visitare Database di esempio di AdventureWorks.
Per un esempio che causa un deadlock quando è abilitato il blocco ottimizzato, vedere Blocchi ottimizzati e deadlock.
Per generare un deadlock, è necessario connettere due sessioni al database AdventureWorksLT2019. Si fa riferimento a queste sessioni come Sessione A e Sessione B. È possibile creare queste due sessioni creando due finestre di query in SQL Server Management Studio (SSMS).
Nella sessione A eseguire il batch seguente. Questo codice inizia una transazione esplicita ed esegue un'istruzione che aggiorna la SalesLT.Product tabella. A tale scopo, la transazione acquisisce un blocco di aggiornamento (U) sulle righe qualificate nella tabella SalesLT.Product che vengono quindi convertite in blocchi esclusivi (X). Lasciare la transazione aperta.
BEGIN TRANSACTION;
UPDATE SalesLT.Product
SET SellEndDate = SellEndDate + 1
WHERE Color = 'Red';
Ora, nella sessione B, eseguire il batch seguente. Questo codice non avvia in modo esplicito una transazione. Funziona invece in modalità di transazione con commit automatico. Questa istruzione aggiorna la tabella SalesLT.ProductDescription. L'aggiornamento accetta un blocco di aggiornamento (U) sulle righe qualificate nella SalesLT.ProductDescription tabella. La query viene aggiunta ad altre tabelle, inclusa la tabella SalesLT.Product.
UPDATE SalesLT.ProductDescription
SET Description = Description
FROM SalesLT.ProductDescription AS pd
INNER JOIN SalesLT.ProductModelProductDescription AS pmpd
ON pd.ProductDescriptionID = pmpd.ProductDescriptionID
INNER JOIN SalesLT.ProductModel AS pm
ON pmpd.ProductModelID = pm.ProductModelID
INNER JOIN SalesLT.Product AS p
ON pm.ProductModelID = p.ProductModelID
WHERE p.Color = 'Silver';
Per completare questo aggiornamento, la sessione B richiede blocchi condivisi (S) sulle righe della tabella SalesLT.Product, incluse le righe bloccate dalla sessione A. La sessione B è bloccata in SalesLT.Product.
Tornare alla sessione A. Eseguire l'istruzione seguente UPDATE . Questa istruzione viene eseguita come parte della transazione aperta in precedenza.
UPDATE SalesLT.ProductDescription
SET Description = Description
FROM SalesLT.ProductDescription AS pd
INNER JOIN SalesLT.ProductModelProductDescription AS pmpd
ON pd.ProductDescriptionID = pmpd.ProductDescriptionID
INNER JOIN SalesLT.ProductModel AS pm
ON pmpd.ProductModelID = pm.ProductModelID
INNER JOIN SalesLT.Product AS p
ON pm.ProductModelID = p.ProductModelID
WHERE p.Color = 'Red';
Il secondo rapporto di aggiornamento nella sessione A viene bloccata dalla sessione B in SalesLT.ProductDescription.
La sessione A e la sessione B si bloccano a vicenda. Nessuna delle transazioni può continuare, perché ognuna necessita di una risorsa bloccata dall'altra.
Dopo alcuni secondi, il monitoraggio dei deadlock identifica che le transazioni nella sessione A e nella sessione B si bloccano reciprocamente e che nessuna delle due può continuare. Viene visualizzato un deadlock, con Session A scelto come vittima del deadlock. La sessione B viene completata correttamente. Viene visualizzato un messaggio di errore nella finestra di query della sessione A con testo simile all'esempio seguente:
Msg 1205, Level 13, State 51, Line 7
Transaction (Process ID 51) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
Se non viene generato un deadlock, verificare che READ_COMMITTED_SNAPSHOT sia abilitato nel database di esempio. I deadlock possono verificarsi in qualsiasi configurazione del database, ma in questo esempio è necessario abilitare READ_COMMITTED_SNAPSHOT.
È possibile visualizzare i dettagli del deadlock nella ring_buffer destinazione della system_health sessione eventi, che per impostazione predefinita è abilitata e attiva in SQL Server e Azure SQL Managed Instance. Si consideri la query seguente:
WITH cteDeadLocks ([Deadlock_XML])
AS (SELECT CAST (target_data AS XML) AS [Deadlock_XML]
FROM sys.dm_xe_sessions AS xs
INNER JOIN sys.dm_xe_session_targets AS xst
ON xs.[address] = xst.event_session_address
WHERE xs.[name] = 'system_health'
AND xst.target_name = 'ring_buffer')
SELECT x.Graph.query('(event/data/value/deadlock)[1]') AS Deadlock_XML,
x.Graph.value('(event/data/value/deadlock/process-list/process/@lastbatchstarted)[1]', 'datetime2(3)') AS when_occurred,
DB_Name(x.Graph.value('(event/data/value/deadlock/process-list/process/@currentdb)[1]', 'int')) AS DB --Current database of the first listed process
FROM (SELECT Graph.query('.') AS Graph
FROM cteDeadLocks AS c
CROSS APPLY c.[Deadlock_XML].nodes('RingBufferTarget/event[@name="xml_deadlock_report"]') AS Deadlock_Report(Graph)) AS x
ORDER BY when_occurred DESC;
È possibile visualizzare il codice XML nella colonna Deadlock_XML all'interno di SSMS selezionando la cella che viene visualizzata come collegamento ipertestuale. Salvare questo output come un file .xdl, chiudere, quindi riaprire il file .xdl in SSMS per un grafico visivo dei deadlock. Il grafico deadlock dovrebbe essere simile all'immagine seguente.
Blocchi ottimizzati e deadlock
Con il blocco ottimizzato, i blocchi di pagina e di riga non vengono mantenuti fino alla fine della transazione. Vengono rilasciati non appena viene aggiornata una riga. Inoltre, se READ_COMMITTED_SNAPSHOT è abilitato, i blocchi di aggiornamento (U) non vengono usati. Di conseguenza, la probabilità di deadlock viene ridotta.
L'esempio precedente non causa un deadlock quando è abilitato il blocco ottimizzato perché si basa sui blocchi di aggiornamento (U).
L'esempio seguente può essere usato per causare un deadlock in un database con ottimizzazione abilitata per il blocco.
Creare prima di tutto una tabella di esempio e aggiungere dati.
CREATE TABLE t2
(
a INT PRIMARY KEY NOT NULL,
b INT NULL
);
INSERT INTO t2
VALUES (1, 10),
(2, 20),
(3, 30);
I batch T-SQL seguenti, eseguiti in sequenza in due sessioni separate, creano un deadlock.
Nella sessione 1:
BEGIN TRANSACTION xactA;
UPDATE t2
SET b = b + 10
WHERE a = 1;
Nella sessione 2:
BEGIN TRANSACTION xactB;
UPDATE t2
SET b = b + 10
WHERE a = 2;
Nella sessione 1:
UPDATE t2
SET b = b + 100
WHERE a = 2;
Nella sessione 2:
UPDATE t2
SET b = b + 20
WHERE a = 1;
In questo caso, ogni sessione contiene un blocco esclusivo (X) sulla propria risorsa ID transazione (TID) ed è in attesa del blocco condiviso (S) sull'altro TID, causando un deadlock.
Il report di deadlock abbreviato seguente contiene elementi e attributi specifici per il blocco ottimizzato. In ogni risorsa del report <resource-list>deadlock ogni <xactlock> elemento segnala le risorse sottostanti e le informazioni di blocco TID di ogni membro di un deadlock.
<deadlock>
<victim-list>
<victimProcess id="process12994344c58" />
</victim-list>
<process-list>
<process id="process12994344c58" taskpriority="0" logused="272" waitresource="XACT: 23:2476:0 KEY: 23:72057594049593344 (8194443284a0)" waittime="447" ownerId="3234906" transactionname="xactA" lasttranstarted="2025-10-08T21:36:34.063" XDES="0x12984ba0480" lockMode="S" schedulerid="2" kpid="204928" status="suspended" spid="95" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2025-10-08T21:36:40.857" lastbatchcompleted="2025-10-08T21:36:34.063" lastattention="2025-10-08T21:36:11.340" clientapp="Microsoft SQL Server Management Studio - Query" hostname="WS1" hostpid="23380" loginname="user1" isolationlevel="read committed (2)" xactid="3234906" currentdb="23" currentdbname="AdventureWorksLT" lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200">
<inputbuf>
UPDATE t2
SET b = b + 20
WHERE a = 1;
</inputbuf>
</process>
<process id="process1299c969828" taskpriority="0" logused="272" waitresource="XACT: 23:2477:0 KEY: 23:72057594049593344 (61a06abd401c)" waittime="3083" ownerId="3234886" transactionname="xactB" lasttranstarted="2025-10-08T21:36:30.303" XDES="0x12995c84480" lockMode="S" schedulerid="2" kpid="63348" status="suspended" spid="88" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2025-10-08T21:36:38.223" lastbatchcompleted="2025-10-08T21:36:30.303" lastattention="1900-01-01T00:00:00.303" clientapp="Microsoft SQL Server Management Studio - Query" hostname="WS1" hostpid="23380" loginname="user1" isolationlevel="read committed (2)" xactid="3234886" currentdb="23" currentdbname="AdventureWorksLT" lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200">
<inputbuf>
UPDATE t2
SET b = b + 100
WHERE a = 2;
</inputbuf>
</process>
</process-list>
<resource-list>
<xactlock xdesIdLow="2476" xdesIdHigh="0" dbid="23" id="lock1299fa06c00" mode="X">
<UnderlyingResource>
<keylock hobtid="72057594049593344" dbid="23" objectname="e6fc405e-1ee8-49df-a2b3-54ee0151d851.dbo.t2" indexname="PK__t2__3BD0198ED3CBA65E" />
</UnderlyingResource>
<owner-list>
<owner id="process1299c969828" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process12994344c58" mode="S" requestType="wait" />
</waiter-list>
</xactlock>
<xactlock xdesIdLow="2477" xdesIdHigh="0" dbid="23" id="lock129940b2380" mode="X">
<UnderlyingResource>
<keylock hobtid="72057594049593344" dbid="23" objectname="e6fc405e-1ee8-49df-a2b3-54ee0151d851.dbo.t2" indexname="PK__t2__3BD0198ED3CBA65E" />
</UnderlyingResource>
<owner-list>
<owner id="process12994344c58" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process1299c969828" mode="S" requestType="wait" />
</waiter-list>
</xactlock>
</resource-list>
</deadlock>
Contenuti correlati
- Panoramica degli eventi estesi
- sys.dm_tran_locks (Transact-SQL)
- Classe di evento Deadlock Graph
- Deadlock con livello di isolamento di lettura ripetibile
- Classe di evento Lock:Deadlock Chain
- Classe di evento Lock:Deadlock
- SET DEADLOCK_PRIORITY (Transact-SQL)
- Analizzare e impedire deadlock nel database SQL di Azure e nel database SQL di Fabric
- Aprire, visualizzare e stampare un file deadlock in SQL Server Management Studio (SSMS)