Melhor situação para usar o nível de isolamento READ UNCOMMITTED

10

Como todos sabemos, READ UNCOMMITTED é o nível de isolamento mais baixo no qual coisas como leituras sujas e leituras fantasmas podem ocorrer. Quando é o melhor momento para usar esse nível de isolamento e por que razões ele pode ser usado?

Na verdade, li as respostas antes, mas não conseguia entendê-las completamente porque não havia exemplos suficientes.

Peter Mortensen
fonte

Respostas:

20

Uso READ_UNCOMMITTED(ou NOLOCK) ao consultar bancos de dados de produção do SSMS, mas não rotineiramente do código do aplicativo. Essa prática (junto com uma dica de consulta do 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, com o entendimento de que os resultados podem não estar corretos.

Infelizmente, vejo READ_UNCOMMITTED/ NOLOCKuso amplamente no código de produção para evitar o bloqueio à custa da integridade dos dados. A solução adequada é um nível de isolamento de versão de linha ( SNAPSHOTou READ_COMMITTEDcom a READ_COMMITTED_SNAPSHOTopção de banco de dados ON) e / ou atenção à consulta e ajuste de índice.

Recentemente, revisei um processo em um processo em que a única alteração foi removida NOLOCKporque às vezes retornava resultados incorretos. A remoção NOLOCKfoi uma coisa boa, mas, sabendo que as linhas perdidas ou duplicadas geralmente acontecem durante as verificações de ordem de alocação de tabelas grandes, sugeri também a refatoração para usar uma UNION ALLtécnica para promover o uso eficiente do índice. A consulta agora é executada em alguns milissegundos com resultados corretos, o melhor de todos os mundos.

Dan Guzman
fonte
7

Eu acho que está bom em algumas circunstâncias, desde que você aceite as consequências e não tenha outras opções.

Para outras opções, eu incentivaria as pessoas a usar o RCSI (Read Committed Snapshot Isolation) para novos aplicativos ou o SNAPSHOT ISOLATION (SI) para aplicativos mais antigos, onde você não pode testar facilmente toda a base de códigos para condições de corrida com RCSI.

No entanto, esses podem não ser um bom ajuste. Pode ser necessário gastar um tempo extra amando e cuidando do tempdb e garantindo que ninguém deixe uma transação aberta que faça com que o armazenamento de versões (e o tempdb) cresça e encha o disco.

Se você não possui um DBA ou alguém cujo trabalho é 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 acessando o servidor, onde podem alterar a cadeia de conexão ou o código para solicitar a SI para consultas de problemas.

Além disso, a maioria das pessoas não tem problemas de bloqueio com todo o aplicativo . Eles têm problemas com coisas como relatórios sobre dados OLTP. Se você puder aceitar as compensações do NOLOCK / RU em troca de os relatórios não serem bloqueados pelos escritores, faça isso.

Apenas certifique-se de entender o que isso significa. Isso não significa que sua consulta não aceita bloqueios, mas não respeita os bloqueios removidos 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 implementá-lo adequadamente com o tratamento de erros, etc.

Erik Darling
fonte
5
E se o problema realmente está apenas relatando dados OLTP, transfira-os para um secundário somente leitura de algum tipo (AG, envio de logs, replicação ou faça você mesmo).
Aaron Bertrand
3
@AaronBertrand E então eles têm um segundo servidor para o monitor;)
Erik Darling
5

IMHO, o único caso de uso válido para READ UNCOMMITTED em um sistema moderno é ao depurar uma sessão da outra em desenvolvimento, para que você possa ver o que está fazendo enquanto, por exemplo, um processo armazenado ainda está em execução. Normalmente nunca seria usado em um sistema de produção. Pode haver um pequeno ganho de desempenho, mas a longo prazo, nunca valerá a pena.

Gaius
fonte
3

Nós o usamos na área da saúde o tempo todo.

É surpreendentemente raro que linhas individuais de dados alterem a consulta central e a taxa de leitura / gravação é de 10.000 / 1 - e a maioria delas é 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 faz a mudança, ele muda uma linha de cada vez. Ninguém está atualizando colunas inteiras (exceto um DBA, quando elas estragam muito).

Por outro lado, fazemos várias consultas para procurar coisas como pacientes que retornam ao pronto-socorro em 72 horas ou menos, o que martela absolutamente as mesas.

Em 10 anos de SQL em assistência médica, nunca vi um Rollback Transaction. Quero entrar e sair sem atrapalhar 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, eu irei 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 normalmente estão repletos de antipadrões.

James
fonte
4
apenas para sua informação, é possível ler linhas parcialmente escritas com nolock.
Max Maxon
1
Oof! Eu realmente preciso que meu chefe me compre outro servidor para que eu possa logar enviar essas coisas ... #
James
3
Você pode estar interessado neste post bacana do blog de Paul White sobre LEITES NÃO COMPROMETIDOS, especialmente a seção "Leitura de dados corrompidos": O nível de isolamento de leitura não confirmada
Josh Darnell
1

READ_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 do procedimento armazenado, podemos executar uma consulta de seleção simples NOLOCKperiodicamente na tabela de destino para verificar se ela progride sem problemas (para a consulta de atualização, se você tiver uma coluna de alteração de status para registros sendo atualizados, podemos usar essa coluna para executar a group byconsulta com NOLOCKpara descobrir se a contagem de alterações de status está constantemente mudando).

GirKarr
fonte
0

Esteja ciente de que READ UNCOMMITTED apresenta problemas adicionais de consistência, 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

SQLRaptor
fonte
3
Linhas ausentes e linhas de leitura mais de uma vez também são possíveis no nível confirmado de leitura padrão. Se uma coluna da chave de índice for atualizada durante a verificação e ela se mover.
Martin Smith
Discussões secundárias sobre esta resposta foram movidas para o bate-papo .
Paul White 9