- 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.