Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Por que essa consulta do SQL Server está travando?

  • 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 (, 1, 151867, 3) inspecione os valores no slot 174
  • 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.