Como reproduzir "Não foi possível continuar a verificação com NOLOCK devido à movimentação de dados"

10

Ocasionalmente, recebo "Não foi possível continuar a verificação NOLOCKdevido à movimentação de dados" em alguns trabalhos grandes, que existem WITH (NOLOCK)nas consultas selecionadas.

Entendo que isso tem algo a ver com a tentativa de selecionar dados quando houve uma divisão de página que fez com que os dados não estivessem mais onde deveriam estar - presumo que é isso que está acontecendo no meu ambiente.

Como eu reproduzi isso?

Estou tentando fazer uma solução alternativa de curto prazo para detectar o erro e tentar novamente quando isso acontecer, mas não posso testá-lo se não conseguir reproduzi-lo. Existe uma maneira razoavelmente confiável de causar isso?

Quando isso acontece, a execução da consulta novamente resulta em sucesso - então eu realmente não tenho nenhuma preocupação sobre os dados ou banco de dados reais estarem permanentemente corrompidos. Algumas das tabelas da consulta (junto com seus índices) são descartadas, recriadas e repovoadas com frequência, então estou assumindo que é algo relacionado a isso.

A remoção NOLOCKé o meu problema de longo prazo. O motivo NOLOCKfoi colocado lá em primeiro lugar, porque as consultas são tão ruins que estavam travando as transações diárias, assim NOLOCKcomo um band-aid para interromper os impasses (que funcionavam). Então, eu preciso de um band-aid em um band-aid até que possamos fazer uma solução permanente.

Se eu pudesse reproduzi-lo com um Hello World, provavelmente planejaria colocar o curativo no trabalho em menos de uma hora. Não é possível fazer uma remoção de pesquisar e substituir NOLOCK, porque eu começaria a obter os impasses do aplicativo novamente, o que é pior para mim do que um trabalho ocasional com falha.

Usar o isolamento de snapshot confirmado por leitura é uma boa possibilidade - terei que trabalhar com nossa equipe de banco de dados para obter mais detalhes sobre isso. Parte do nosso problema é que não temos um especialista em SQL Server para lidar com esse tipo de coisa e não entendo os níveis de isolamento suficientemente bem para fazer essa alteração agora.

wookie23
fonte
11
Você já pensou em simplesmente remover NOLOCKesses trabalhos? 601 deve ser a menor das suas preocupações se os resultados dessas consultas forem precisos . Paul White mostra um exemplo particularmente terrível de leitura de dados que não deveria ser possível aqui .
Aaron Bertrand
3
Você pode definir DEADLOCK_PRIORITYpara LOWnos postos de trabalho, de modo que se houver impasses, os postos de trabalho irá falhar, e não as aplicações. Depois disso, você pode pesquisar os impasses e descobrir por que eles estão acontecendo e resolver o problema. Pode ser uma correção muito simples, como trocar a ordem de duas instruções. Qualquer que seja o problema, essa nãoNOLOCK é a solução , então pare de tentar forçá-lo a ser apenas porque é mais fácil.
Aaron Bertrand
@AaronBertrand Obrigado, não sabia sobre o DEADLOCK_PRIORITY - vou analisar isso. Tentamos rastrear os impasses, mas esses ocorreram em vários momentos aparentemente aleatórios, e apenas uma ou duas vezes por dia, e nunca são reproduzíveis sob demanda - nossos trabalhos agendados executam dezenas de milhares de consultas a cada hora e nosso aplicativo executa centenas de consultas sempre que apenas carrega uma página ou salva algo, e não rastreamos qual consulta de ambos os lados está envolvida no impasse. Eu não tinha a intenção de deixar o NOLOCK lá para sempre, e é por isso que estamos pesquisando melhores soluções a longo prazo.
wookie23
11
Você mencionou que estava tendo dificuldades para rastrear os impasses. Como você está no 2008 R2, você pode procurar aqui: sqlservercentral.com/articles/deadlock/65658 Jonathan Kehayias examina as informações de deadlock do buffer do anel.
Kenneth Fisher
As respostas e os comentários abordam bem o problema subjacente, mas você ainda está interessado em encontrar uma maneira de reproduzir isso como um exercício intelectual?
James L

Respostas:

8

Como um possível "band-aid" para os problemas do NOLOCK é parar de usar o NOLOCK e começar a usar o isolamento READ_COMMITTED_SNAPSHOT, quero apontar para a postagem do blog em http://www.brentozar.com por Kendra Little: Implementando Snapshot ou Read Committed Isolamento de instantâneo no SQL Server: um guia .

A Kendra fornece uma quantidade razoável de detalhes sobre benefícios e riscos ao usar o nível de isolamento READ_COMMITTED_SNAPSHOT.

  1. Esse nível de isolamento se torna o nível de isolamento padrão para o código do banco de dados.
  2. Você precisa ter apenas um usuário no banco de dados para fazer a alteração no nível de isolamento READ_COMMITTED_SNAPSHOT.
  3. Mesmo se você usar o isolamento READ_COMMITTED_SNAPSHOT , ainda será necessário remover as dicas NOLOCK, pois elas substituem o padrão.
  4. Alguns dos seus códigos podem ter problemas que precisam ser corrigidos.

Alguns anos atrás, implementamos o isolamento READ_COMMITTED_SNAPSHOT em um banco de dados que sofria severamente com o bloqueio . Porém, uma vez que alteramos o nível de isolamento, começamos a obter impasses em algumas áreas críticas.

Por quê isso aconteceu? Como o nível de isolamento anterior causou bloqueio intenso, o código "nunca" pode chegar ao ponto de conflito. No entanto, com o isolamento READ_COMMITTED_SNAPSHOT, as consultas podem continuar avançando. No entanto, alguma porcentagem das transações que não aguardavam mais começou a entrar em conflito.

Felizmente, nosso caso foi resolvido rapidamente, determinando os pontos de conflito e ajustando os índices em algumas tabelas para ter uma ordem de coluna mais racional. Isso reduziu bastante nossos problemas de travamento.

RLF
fonte