SQL Server na prática

NOLOCK: uma resposta rápida pode estar errada

Reproduza uma leitura suja com duas sessões, entenda os bloqueios restantes e substitua NOLOCK preservando a exatidão dos relatórios.

Um relatório que termina em dois segundos pode ser menos útil que outro que espera cinco se o total apresentado nunca existiu nos dados confirmados. NOLOCK altera aquilo que uma leitura pode observar. Em faturamento, estoque e decisões operacionais, isso muda o significado do resultado. Não é apenas uma maneira mais barata de executar a mesma consulta.

Reproduzir uma leitura incorreta

Use um banco descartável e duas janelas conectadas ao mesmo banco. Execute a preparação uma única vez. Na janela A, abra a transação e mantenha-a ativa. Na janela B, execute a consulta NOLOCK antes de voltar para A e desfazer a alteração.

CREATE TABLE dbo.NolockDemo (Id int PRIMARY KEY, Balance int NOT NULL);
INSERT dbo.NolockDemo VALUES (1, 100);
BEGIN TRAN;
UPDATE dbo.NolockDemo SET Balance = 900 WHERE Id = 1;
-- Run the reader in window B, then execute:
-- ROLLBACK;
SELECT Balance FROM dbo.NolockDemo WITH (NOLOCK) WHERE Id = 1;

B pode mostrar 900 mesmo que esse saldo nunca seja confirmado. Após o rollback, o saldo confirmado continua sendo 100. Uma leitura normal com READ COMMITTED baseado em bloqueios pode esperar durante o experimento. Se READ_COMMITTED_SNAPSHOT estiver habilitado, ela pode ler a versão anteriormente confirmada. Confira essa configuração antes de interpretar o comportamento. Uma resposta imediata não comprova que NOLOCK era necessário.

O problema fica mais difícil de perceber quando o relatório combina diversas tabelas. Um saldo pode vir de uma etapa da transação, enquanto os lançamentos associados refletem outra etapa. Mudanças físicas concorrentes também podem fazer uma leitura NOLOCK perder linhas ou encontrá-las mais de uma vez. Uma segunda execução correta não torna aceitável o primeiro resultado. A intermitência dificulta bastante a investigação em produção.

Investigar a espera original

NOLOCK ainda precisa de bloqueios de estabilidade de esquema durante compilação e execução. Uma alteração de esquema pode bloquear a consulta, e uma consulta demorada pode atrasar essa alteração. O hint também não elimina consumo de CPU, derramamentos de ordenação, leituras de disco ou transferência pela rede. Examine o tipo efetivo de espera antes de mudar o isolamento.

Capture o leitor, o bloqueador principal, as instruções e a idade da transação. Uma transação mantida aberta durante uma chamada externa exige corrigir sua duração no aplicativo. Uma varredura que lê milhões de linhas irrelevantes exige revisar filtros e índices. Um painel que consulta todo o histórico para exibir poucos números pode precisar de uma agregação atualizada separadamente. Cada causa exige uma intervenção própria.

Defina então o contrato de consistência. Uma visão confirmada por instrução é suficiente? Várias instruções precisam observar o mesmo estado? Um retrato explicitamente antigo é aceitável? READ_COMMITTED_SNAPSHOT fornece consistência por instrução; SNAPSHOT pode fornecer consistência por transação. Uma réplica de leitura pode estar atrasada em relação ao primário e não torna automaticamente consistente qualquer sequência de consultas.

Substituir com critérios claros

Comece com um relatório cujo resultado possa ser verificado de maneira independente. Remova NOLOCK em um ambiente representativo, meça duração e leituras lógicas e introduza gravações concorrentes. Se considerar versionamento, avalie espaço para versões, leitores prolongados e transações de escrita existentes. Uma configuração para o banco inteiro afeta muito mais que o relatório inicial.

O teste de aceitação deve repetir o exemplo do saldo e garantir que o valor não confirmado nunca seja publicado. Acrescente uma transação sobre várias tabelas que reproduza a sequência real do aplicativo. Verifique uma regra de negócio, como a igualdade entre o total da fatura e a soma dos itens. Um retorno HTTP 200 não demonstra essa propriedade.

Registre desempenho e exatidão separadamente. A substituição funciona quando entrega uma visão confirmada aceitável durante atividade concorrente e atende ao prazo esperado. Encerre explicitamente a transação de demonstração com ROLLBACK e remova a tabela depois do exercício. NOLOCK deve ser uma concessão consciente para uma necessidade específica, nunca um padrão invisível copiado para toda consulta.

Referências técnicas: Microsoft Learn: Table hints · Microsoft Learn: Transaction isolation.

Pergunte sobre este artigo

Tem alguma dúvida sobre este tema?

Conte o que você está avaliando ou onde encontrou dificuldades. Responderemos com uma recomendação prática.

Inquiries are not enabled in this preview.

Fazer uma pergunta sobre este artigo