Causa de um processo ser uma vítima de deadlock

105

Tenho um processo com Select que demora muito para terminar, da ordem de 5 a 10 minutos.
No momento, não estou usando o NOLOCK como uma dica para o mecanismo de banco de dados MS SQL.
Ao mesmo tempo, temos outro processo fazendo atualizações e inserções no mesmo banco de dados e nas mesmas tabelas.
O primeiro processo começou, recentemente para terminar prematuramente com uma mensagem

SQLEXCEPTION: A transação foi travada em recursos de bloqueio com outro processo e foi escolhida como a vítima de impasse.

Este primeiro processo está sendo executado em outros sites em condições idênticas, mas com bancos de dados menores e, portanto, a instrução select em questão leva um período de tempo muito mais curto (da ordem de 30 segundos ou mais). Nesses outros sites, não recebo a mensagem de deadlock nesses outros sites. Também não recebi essa mensagem no site que está tendo o problema inicialmente, mas, presumo que, à medida que o banco de dados cresceu, acredito que devo ter ultrapassado algum limite. Aqui estão minhas perguntas:

  1. O tempo que leva para uma transação ser executada pode tornar o processo associado mais provável de ser sinalizado como uma vítima de deadlock.
  2. Se eu executar o select com uma dica NOLOCK, isso removerá o problema?
  3. Suspeito que um campo datetime que é verificado como parte da cláusula WHERE na instrução select está causando o tempo de pesquisa lento. Posso criar um índice com base neste campo? É aconselhável?
Elliott
fonte
Resposta parcial ao ponto 1: Não confunda um impasse com um tempo limite. Se você estava sofrendo um tempo limite, o tempo envolvido na conclusão de uma transação pode ser responsável pelo abending de outra. Além disso, seria útil saber em qual recurso você está travando (é um índice ou uma tabela?).
NealB
1
SET DEADLOCK_PRIORITY HIGH ALTER DATABASE dbname SET MULTI_USER;
gstackoverflow

Respostas:

128

P1: O tempo que leva para uma transação ser executada pode tornar o processo associado mais provável de ser sinalizado como vítima de deadlock.

Não. O SELECT é a vítima porque tinha apenas dados lidos, portanto a transação tem um custo menor associado a ela, por isso é escolhida como vítima:

Por padrão, o Mecanismo de Banco de Dados escolhe como vítima de deadlock a sessão que executa a transação que é menos cara para reverter . Como alternativa, um usuário pode especificar a prioridade das sessões em uma situação de conflito usando a SET DEADLOCK_PRIORITYinstrução. DEADLOCK_PRIORITY pode ser definido como LOW, NORMAL ou HIGH ou, alternativamente, pode ser definido como qualquer valor inteiro no intervalo (-10 a 10).

2º trimestre. Se eu executar o select com uma dica NOLOCK, isso removerá o problema?

Não. Por vários motivos:

3º trimestre. Suspeito que um campo datetime que é verificado como parte da cláusula WHERE na instrução select está causando o tempo de pesquisa lento. Posso criar um índice com base neste campo? É aconselhável?

Provavelmente. A causa do conflito é quase muito provável que seja um banco de dados mal indexado. Consultas de 10 minutos são aceitáveis ​​em condições tão restritas, que estou 100% certo que no seu caso não é aceitável.

Com 99% de confiança, declaro que seu impasse é causado por uma grande verificação de tabela em conflito com atualizações. Comece capturando o gráfico de conflito para analisar a causa. Muito provavelmente, você terá que otimizar o esquema de seu banco de dados. Antes de fazer qualquer modificação, leia este tópico Criando índices e os sub-artigos.

Remus Rusanu
fonte
Obrigado por sua resposta completa. Acho que ainda tenho uma pergunta. Por que eu estaria obtendo a situação de deadlock apenas em um ambiente e não em outro? Mesmo que o software seja o mesmo. Sua resposta sugere que o período de tempo para executar a consulta Select não faz diferença e é o fato de que é uma consulta Select per se que está causando a falha do processo. Mas então, por que apenas quando a consulta de seleção leva muito tempo para ser executada?
Elliott
4
A duração da consulta não faz diferença na escolha da vítima de deadlock . Faz diferença em causar o impasse por pelo menos dois fatores: 1) probabilidades simples. Quanto mais longa a consulta, maior a probabilidade de sobrepor atualizações simultâneas e gerar deadlocks. 2) uma tabela maior pode usar um plano de consulta completamente diferente, que é suscetível a deadlocks.
Remus Rusanu
12

Aqui está como esse problema específico de deadlock realmente ocorreu e como foi realmente resolvido. Este é um banco de dados bastante ativo com 130 mil transações ocorrendo diariamente. Os índices nas tabelas deste banco de dados foram originalmente agrupados. O cliente solicitou que tornássemos os índices não clusterizados. Assim que o fizemos, o impasse começou. Quando restabelecemos os índices como clusterizados, o conflito parou.

Elliott
fonte
34
Alguém pode explicar por quê? (Soluções mágicas não são muito úteis)
OGrandeDiEnne
1
Esse cara explica isso em sua postagem: mssqltips.com/sqlservertip/2517/…
siga0984
6

Vale a pena tentar as respostas aqui, mas você também deve revisar seu código. Especificamente, leia a resposta da Polyfun aqui: Como se livrar do impasse em um aplicativo SQL Server 2005 e C #?

Ele explica o problema de simultaneidade e como o uso de "with (updlock)" em suas consultas pode corrigir sua situação de deadlock - dependendo realmente do que exatamente seu código está fazendo. Se o seu código seguir este padrão, esta é provavelmente a melhor solução a fazer, antes de recorrer a leituras sujas, etc.

Peter Barton
fonte