Como todos sabemos, READ UNCOMMITTED é o nível de isolamento mais baixo no qual coisas como leituras sujas e leituras fantasmas podem ser acumuladas. Qual é o melhor momento para usar esse nível de isolamento e por quais motivos ele pode ser usado?
Na verdade eu li as respostas antes, mas não consegui entender completamente porque não havia exemplos suficientes.
Eu uso
READ_UNCOMMITTED
(ouNOLOCK
) ao consultar bancos de dados de produção do SSMS, mas não rotineiramente do código do aplicativo. Essa prática (juntamente com uma dica de consulta MAXDOP 1) ajuda a garantir que consultas casuais para análise de dados e solução de problemas não afetem a carga de trabalho de produção, entendendo que os resultados podem não estar corretos.Infelizmente, vejo
READ_UNCOMMITTED
/NOLOCK
usado amplamente no código de produção para evitar o bloqueio em detrimento da integridade dos dados. A solução adequada é um nível de isolamento de versão de linha (SNAPSHOT
ouREAD_COMMITTED
com aREAD_COMMITTED_SNAPSHOT
opção de banco de dadosON
) e/ou atenção ao ajuste de consulta e índice.Recentemente, revisei o código de um proc em que a única alteração foi remover
NOLOCK
porque às vezes retornava resultados errados. A remoçãoNOLOCK
foi uma coisa boa, mas, sabendo que linhas perdidas ou duplicadas normalmente acontecem durante varreduras de ordem de alocação de tabelas grandes, sugeri também refatorar para usar umaUNION ALL
técnica para promover o uso eficiente do índice. A consulta agora é executada em alguns milissegundos com resultados corretos, o melhor de todos os mundos.Eu acho que está tudo bem em algumas circunstâncias, desde que você aceite as consequências e não tenha outras opções.
Para outras opções, eu levaria as pessoas a usar o Read Committed Snapshot Isolation (RCSI) para novos aplicativos ou SNAPSHOT ISOLATION (SI) para aplicativos mais antigos, onde você não pode testar facilmente toda a base de código para condições de corrida com RCSI.
No entanto, esses podem não ser um bom ajuste. Você pode precisar gastar algum tempo extra amando e cuidando do tempdb e certificando-se de que ninguém deixe uma transação aberta que faça o armazenamento de versão (e o tempdb) crescer e encher o disco.
Se você não tiver um DBA ou alguém cujo trabalho seja monitorar e gerenciar seu SQL Server, essas opções podem ser perigosas. De maneira mais geral, nem todos têm controle total do código que vai para o servidor, onde podem alterar a string de conexão ou o código para solicitar o SI para consultas de problemas.
Além disso, a maioria das pessoas não tem problemas de bloqueio com toda a sua aplicação . Eles têm problemas com coisas como relatórios de dados OLTP. Se você pode aceitar as compensações do NOLOCK/RU em troca desses relatórios não serem bloqueados pelos escritores, vá em frente.
Apenas certifique-se de entender o que isso significa. Isso não significa que sua consulta não tenha bloqueios, significa que não respeita os bloqueios retirados por outras consultas.
E, claro, se o seu problema for o bloqueio de gravador/gravador, a única opção que ajudará é o SI, mas seria necessário uma quantidade incrível de trabalho do desenvolvedor para implementar isso adequadamente com tratamento de erros, etc.
IMHO o único caso de uso válido para READ UNCOMMITTED em um sistema moderno é ao depurar uma sessão de outra em desenvolvimento, para que você possa ver o que está fazendo enquanto, por exemplo, um proc armazenado ainda está em execução. Normalmente, ele nunca seria usado em um sistema de produção. Pode haver algum ganho de desempenho menor, mas a longo prazo nunca valerá a pena.
Nós o usamos em cuidados de saúde o tempo todo.
É surpreendentemente raro que linhas individuais de dados mudem no meio da consulta, e a taxa de leitura/gravação é de 10.000/1 - e a maioria delas são inserções, não atualizações. Por exemplo, quando a interface do laboratório grava os resultados do laboratório de um paciente no banco de dados, esses valores nunca serão alterados.
Quando os dados mudam , eles mudam uma linha de cada vez. Ninguém está atualizando colunas inteiras (exceto um DBA, quando eles bagunçam muito).
Por outro lado, executamos um monte de consultas para verificar coisas como pacientes voltando ao pronto-socorro em 72 horas ou menos, o que absolutamente martela as mesas.
Em 10 anos de SQL de cuidados com a saúde, nunca vi um arquivo
Rollback Transaction
. Quero entrar e sair sem interromper a experiência do usuário final. Se houver um alto risco de desacelerar o banco de dados OLTP e um baixo risco de obter dados incorretos, farei NOLOCK.Devemos usá-lo? Talvez talvez não. De um modo geral, eu não diria que muitos dos bancos de dados de aplicativos em que trabalhei são bem projetados. Eles são normalmente repletos de anti-padrões.
Você pode estar interessado nesta postagem de blog bacana de Paul White sobre
READ UNCOMMITTED
, especialmente a seção "Ler dados corrompidos": O nível de isolamento não confirmado de leituraREAD_UNCOMMITTED/NOLOCK
é uma boa opção quando a precisão dos dados não é realmente o objetivo principal. Às vezes, quando uma contagem agregada aproximada é tudo o que é necessário. Por exemplo: Existem procedimentos armazenados que são usados para tabelas INSERT ou UPDATE. Às vezes o número de registros a serem atualizados ou inseridos é enorme (Milhares de registros). Durante essas execuções de procedimento armazenado, podemos executar uma consulta de seleção simplesNOLOCK
na tabela de destino periodicamente para ver se ela progride sem problemas (para consulta de atualização, se você tiver uma coluna de alteração de status para registros sendo atualizados, podemos usar essa coluna para executar agroup by
consulta comNOLOCK
para descobrir se a contagem de alterações de status está mudando constantemente).Esteja ciente de que READ UNCOMMITTED apresenta problemas de consistência adicionais, não apenas leituras sujas. Dependendo do método de acesso, você pode perder linhas ou até ler a mesma linha mais de uma vez. Se você estiver interessado nos detalhes, leia o artigo de Itzik Ben-Gan