Deadlock sull'istruzione Delete


11

Ottengo un deadlock quando viene eseguito un processo di SQL Server. Il deadlock si verifica su una semplice istruzione DELETE. Avrei pensato che ci sarebbe stata una query SELECT / UPDATE in esecuzione per causare il deadlock? Ma sembra che sia il deadlock DELETE / DELETE ...

Quello che sto cercando è perché sto ottenendo un deadlock DELETE / DELETE. (A mia conoscenza) sta passando parametri diversi.

Qualche idea? Grazie.

deadlock-list
2014-05-20 07:30:09.66 spid25s      deadlock victim=process409048
2014-05-20 07:30:09.66 spid25s       process-list
2014-05-20 07:30:09.66 spid25s        process id=process409048 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127294 waittime=4352 ownerId=629860973 transactionname=DELETE lasttranstarted=2014-05-20T07:30:05.307 XDES=0x397219620 lockMode=U schedulerid=5 kpid=3792 status=suspended spid=150 sbid=0 ecid=3 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:05.307 lastbatchcompleted=2014-05-20T07:30:05.307 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629860973 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2
2014-05-20 07:30:09.66 spid25s     DELETE FROM dbo.UserDetailsData WHERE        (Username = @P1) AND (UserDate = @P2)     
2014-05-20 07:30:09.66 spid25s          frame procname=unknown line=1 sqlhandle=0x000000000000000000000000000000000000000000000000
2014-05-20 07:30:09.66 spid25s     unknown     
2014-05-20 07:30:09.66 spid25s         inputbuf
2014-05-20 07:30:09.66 spid25s        process id=process432e08 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127916 waittime=2648 ownerId=629859744 transactionname=DELETE lasttranstarted=2014-05-20T07:30:04.833 XDES=0x4c3426b50 lockMode=U schedulerid=6 kpid=5988 status=suspended spid=146 sbid=0 ecid=3 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:04.833 lastbatchcompleted=2014-05-20T07:30:04.820 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629859744 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2
2014-05-20 07:30:09.66 spid25s     DELETE FROM dbo.UserDetailsData WHERE        (Username = @P1) AND (UserDate = @P2)     
2014-05-20 07:30:09.66 spid25s          frame procname=unknown line=1 sqlhandle=0x000000000000000000000000000000000000000000000000
2014-05-20 07:30:09.66 spid25s     unknown     
2014-05-20 07:30:09.66 spid25s         inputbuf
2014-05-20 07:30:09.66 spid25s        process id=process39ea562c8 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127916 waittime=4352 ownerId=629860973 transactionname=DELETE lasttranstarted=2014-05-20T07:30:05.307 XDES=0x13e0e4b50 lockMode=U schedulerid=2 kpid=7124 status=suspended spid=150 sbid=0 ecid=1 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:05.307 lastbatchcompleted=2014-05-20T07:30:05.307 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629860973 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2

5
No, un deadlock può verificarsi in altri scenari al di fuori di SELECT / UPDATE. Tutto ciò di cui hai veramente bisogno sono due processi che richiedono ciascuno una risorsa che l'altro detiene. (1) Le istruzioni DELETE fanno parte di una transazione più ampia? (2) È possibile pubblicare l'XML deadlock da qualche parte, anziché il testo del registro degli errori scadente?
Aaron Bertrand

Potresti pubblicare lo schema della tabella dbo.UserDetailsDataincludendo tutti gli indici? Inoltre, sai se tali istruzioni vengono chiamate con gli stessi parametri? Dato che entrambi hanno zero log utilizzato, mi chiedo se tutto ciò che devi fare è serializzare le chiamate perché si stanno calpestando.
Jon Seigel

Come posso ottenere l'XML? Ottenuto l'errore dai log degli errori di SQL Server. Le istruzioni vengono chiamate con parametri diversi. Di recente abbiamo aggiunto una serie di indici filtrati che filtrano nel campo UserDate.
K09,

Cattura l'evento grafico deadlock in Profiler. Quindi, dopo averlo catturato, fai clic con il pulsante destro del mouse sulla riga -> estrai dati evento -> salvalo come .xdl da qualche parte e pubblica il suo contenuto (è un xml) su Pastebin (o da qualche parte simile).
Marian,

1
Ciao, XML pubblicato qui ... spero che questo ti aiuti! dl.dropboxusercontent.com/u/16953128/DeadlockTest.xdl
K09

Risposte:


14

Quello che sto cercando è perché sto ottenendo un deadlock DELETE / DELETE.

Sembra che il deadlock si verifichi perché:

  1. spid 54 ecid 0acquisisce un Ublocco della pagina update ( ) attivatoPAGE: 12:1:5147422
  2. spid 166 ecid 3richiede un Ublocco della pagina di aggiornamento ( ) sulla stessa pagina e viene bloccato
  3. spid 54 ecid 2richiede un Ublocco di pagina update ( ) sulla stessa pagina ...

Le pagine vengono precaricate per la query, con i blocchi di aggiornamento acquisiti da ecid 0. Questo è il passaggio 1 sopra. Nel passaggio 3, un thread figlio della stessa query parallela ( ecid 2) richiede lo stesso blocco. Normalmente questo non sarebbe un problema. SQL Server conosce ecid 0e ecid 2sono thread dello stesso processo padre. Sfortunatamente, il passaggio 2 si oppone a questo e si ottiene un deadlock.

Detto questo, non dovresti davvero preoccuparti molto del perché si verifica lo stallo, la domanda importante è come evitarlo. La risposta è fornire un percorso di accesso efficiente per DELETE. L'istruzione deve trovare le righe WHERE Username = @P1 AND UserDate = @P2, quindi è necessario disporre di un indice digitato su queste colonne.

E ovviamente hai un tale indice. La vera domanda è perché i problemi hanno iniziato a verificarsi dopo aver aggiunto gli indici filtrati.

La risposta a queste sono informazioni aggiuntive sulla colonna per individuare le righe dell'indice filtrate da eliminare (e per controllare i loro predicati). Se la query utilizza un piano di esecuzione ristretto / per riga , il motore di esecuzione non è in grado di recuperare le colonne aggiuntive nell'operatore Elimina indice cluster, come farebbe in un piano largo / per indice.

Puoi trovare maggiori dettagli a riguardo e un esempio funzionante in questo post del blog .

In questo caso, le informazioni sulla colonna devono provenire dalla parte del piano a destra dell'eliminazione dell'indice cluster, quindi viene utilizzata una scansione dell'indice cluster parallelo e si ottiene una query lenta con un elevato potenziale di deadlock.

La risposta è effettuare una delle seguenti operazioni:

  1. Rimuovi gli indici filtrati
  2. Aggiungi le colonne dell'indice filtrato / include / predicate all'indice nome / data esistente
  3. Forzare un piano di aggiornamento ampio (nessun modo supportato per farlo)
  4. Esegui la query in isolamento snapshot (non RCSI)

L'opzione 2 sarebbe la mia forte preferenza.

L'opzione 4 (grazie a Jack Douglas) ha il vantaggio di rimuovere i deadlock e non dovrebbe causare "conflitti di aggiornamento", data la natura disgiunta delle modifiche, ma richiede l'abilitazione dell'isolamento dello snapshot a livello di database, cambiando esplicitamente il livello di isolamento, e non risolverà il problema di fondo : finirai comunque con una dispendiosa scansione della tabella parallela, in cui una buona ricerca dell'indice è ciò che desideri davvero.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.