Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Perché questa query di SQL Server si blocca?

  • il processo 9196a8 ha pagina 151867 slot 174 in modalità X e vuole pagina 140302 slot 31 in modalità S
  • il processo 88b5b8 ha pagina 140302 slot 31 in modalità X e vuole pagina 151867 slot 174 in modalità S
  • le due eliminazioni vengono eseguite in isolationlevel="repeatable read (3)"

Quindi il deadlock si verifica nell'heap di base della tabella (i blocchi RID anziché i blocchi chiave implicano un heap non un Btree). L'elevato livello di isolamento (probabilmente causato da DTC, a giudicare dal nome xact) rende irrilevante l'impostazione RCSI.

Di che tipo sono le colonne PARTYEXTERNALREF e PARTYTYPE? I parametri passati sono NVARCHAR (es. Unicode) e se le colonne sono VARCHAR (es. Ascii) allora a causa delle regole di precedenza del tipo di dati l'indice NC non verrebbe utilizzato. A causa della scansione della tabella coinvolta, insieme all'elevato livello di isolamento in uso, un deadlock è quasi inevitabile.

La soluzione sarebbe utilizzare i parametri di tipo VARCHAR per @P0 e @P1 in modo che l'indice NC venga sfruttato per evitare la scansione della tabella.

Se i parametri sono già di tipo VARCHAR e puoi confermare dal piano di esecuzione che viene utilizzata una ricerca sul CN, la mia prima domanda sarebbe cosa altro sta facendo la transazione, a parte le istruzioni di eliminazione?

A proposito, dai solo il nome dell'indice NC ma suppongo sia su (PARTYEXTERNALREF, ISCOUNTERPARTY, PARTYID) .

Aggiorna

Dal momento che il tuo commento dice che le colonne sono NVARCHAR quindi l'ipotesi di scansione delle tabelle è probabilmente sbagliata. Ci sono altre tre possibilità per causare un deadlock che richiedono un'indagine:

  • qualsiasi altra istruzione eseguita dalla transazione prima di DELETE (questa è la più probabile)
  • qualsiasi sovrapposizione nelle righe selezionate da due istruzioni DELETE coinvolte nel deadlock
  • collisione di hash

Per le prime due ipotesi solo tu puoi fare qualcosa in questo momento (indaga se sono corrette). Per l'ultimo posso dirti come verificarlo, ma non è banale. È improbabile che accada e un po' difficile da dimostrare, ma è possibile. Dal momento che conosci un caso di deadlock (l'XML allegato), utilizzalo come base di indagine:

  • ripristinare una copia puntuale del database con stop a 2011-09-02T19:00:29.690
  • esegui DBCC TRACEON(3604,-1)
  • utilizzando DBCC PAGE (<restored db id>, 1, 151867, 3) ispezionare i valori nello slot 174
  • utilizzando DBCC PAGE(, 1, 140302, 3)` controlla i valori nello slot 31
  • esegui SELECT %%lockres%% FROM PARTIES WHERE PARTYEXTERNALREF = ... AND ISCOUNTERPARTY='N' and PARTYID=... e passa i valori letti sopra
  • confronta i valori hash di blocco risultanti, se corrispondono, si verifica una collisione di hash e questo ha causato il deadlock.