- o processo 9196a8 tem a página 151867 slot 174 no modo X e quer a página 140302 slot 31 no modo S
- o processo 88b5b8 tem a página 140302 slot 31 no modo X e quer a página 151867 slot 174 no modo S
- as duas exclusões são executadas em
isolationlevel="repeatable read (3)"
Portanto, o deadlock ocorre no heap base da tabela (bloqueios RID em vez de bloqueios de chave implicam um heap e não um Btree). O alto nível de isolamento (provavelmente causado pelo DTC, a julgar pelo nome xact) torna a configuração RCSI irrelevante.
De que tipo são as colunas PARTYEXTERNALREF e PARTYTYPE? Os parâmetros passados são NVARCHAR (ou seja, Unicode) e se as colunas são VARCHAR (ou seja, ASCII), então devido às regras de precedência do tipo de dados o índice NC não seria usado. Por causa da varredura de tabela envolvida, juntamente com o alto nível de isolamento em uso, um deadlock é quase inevitável.
A solução seria usar parâmetros do tipo VARCHAR para @P0 e @P1 para que o índice NC fosse aproveitado para evitar a varredura da tabela.
Se os parâmetros já são do tipo VARCHAR e você pode confirmar no plano de execução que uma busca no NC é usada, a minha primeira pergunta seria o que mais a transação está fazendo, além das instruções de exclusão?
BTW, você apenas fornece o nome do índice NC, mas presumo que esteja em
(PARTYEXTERNALREF, ISCOUNTERPARTY, PARTYID)
. Atualizar
Já que seu comentário diz que as colunas são NVARCHAR então a hipótese de varredura de tabelas provavelmente está errada. Existem mais três possibilidades para causar um impasse que precisa de investigação:
- qualquer outra instrução executada pela transação antes do DELETE (este é o mais provável)
- qualquer sobreposição nas linhas selecionadas por duas instruções DELETE envolvidas no impasse
- colisão de hash
Para as duas primeiras hipóteses, só você pode fazer alguma coisa agora (investigar se elas estão corretas). Para o último, posso dizer como verificá-lo, mas não é trivial. É improvável que aconteça e um pouco difícil de provar, mas é possível. Como você conhece como caso de deadlock (o XML em anexo), use-o como base de investigação:
- restaure uma cópia pontual do banco de dados com stop at 2011-09-02T19:00:29.690
- execute
DBCC TRACEON(3604,-1)
- usando
DBCC PAGE (
inspecione os valores no slot 174, 1, 151867, 3) - usando DBCC PAGE(, 1, 140302, 3)` inspecione os valores no slot 31
- execute
SELECT %%lockres%% FROM PARTIES WHERE PARTYEXTERNALREF =... AND ISCOUNTERPARTY='N' e PARTYID=...
e passe os valores lidos acima - compara os valores de hash de bloqueio resultantes, se eles corresponderem, você terá uma colisão de hash e isso causou o impasse.