Sou um desenvolvedor de relatórios que deseja tornar minhas consultas o mais eficientes possível. Eu trabalhava com um DBA que me dizia - acredito porque sempre lidava com relatórios em um servidor de produção - para usar NOLOCK
em todas as consultas.
Agora, trabalho com um DBA que baniu NOLOCK
em qualquer circunstância - mesmo quando um relatório meu (devido a uma falta considerável de índices em algumas tabelas) está interrompendo a replicação e as atualizações do sistema. Na minha opinião, neste caso, a NOLOCK
seria uma coisa boa.
Como a maior parte do meu treinamento em SQL veio de vários DBAs com opiniões muito diferentes, gostaria de perguntar isso a uma grande variedade de DBAs.
Nem sempre é ruim.
É claro que permite que você leia valores não confirmados (que podem ser revertidos e, portanto, nunca existiram logicamente), além de permitir fenômenos como ler valores várias vezes ou não.
Os únicos níveis de isolamento que garantem que você não encontrará tais anomalias são serializáveis/instantâneos. Os valores de leitura repetível podem ser perdidos se uma linha for movida (devido a uma atualização de chave) antes que a verificação alcance essa linha, os valores confirmados de leitura podem ser lidos duas vezes se uma atualização de chave fizer com que uma linha lida anteriormente avance.
No entanto, é mais provável que esses problemas surjam
nolock
porque, por padrão, nesse nível de isolamento, ele usará uma verificação ordenada de alocação quando estimar que há mais de 64 páginas a serem lidas . Assim como a categoria de problemas que surgem quando as linhas se movem entre as páginas devido a atualizações de chave de índice, essas varreduras ordenadas de alocação também são vulneráveis a problemas com divisões de página (onde as linhas podem ser perdidas se a página recém-alocada for anterior no arquivo do que o ponto já digitalizada ou lida duas vezes se uma página já digitalizada for dividida em uma página posterior no arquivo).Pelo menos para consultas simples (tabela única), é possível desencorajar o uso dessas verificações e obter uma verificação ordenada de chave
nolock
simplesmente adicionando umORDER BY index_key
à consulta para que aOrdered
propriedade doIndexScan
sejatrue
.Mas se o seu aplicativo de relatório não precisar de números absolutamente precisos e puder tolerar a maior probabilidade de tais inconsistências, pode ser aceitável.
Mas certamente você não deve jogá-lo em todas as consultas na esperança de que seja um botão "turbo" mágico. Além da maior probabilidade de encontrar resultados anômalos nesse nível de isolamento ou nenhum resultado (erro "Não foi possível continuar a varredura com NOLOCK devido à movimentação de dados"), existem até casos em que o desempenho
nolock
pode ser muito pior .Se o seu relatório bloquear atualizações de que seu DBA está certo: você absolutamente não deve usar
NOLOCK
. O próprio fato de haver conflitos é uma indicação clara de que, se você usasse leituras sujas, obteria relatórios incorretos.Na minha opinião, sempre há alternativas melhores do que
NOLOCK
:SET TRANSACTION ISOLATION LEVEL
, não uma dica de consulta. Será mais fácil corrigir posteriormente o nível de isolamento em vez de modificar cada consulta.Seus clientes toleram resultados inconsistentes em relatórios? Se a resposta for não, você não deve usar NOLOCK - você pode obter resultados errados em simultaneidade. Escrevi alguns exemplos aqui , aqui e aqui . Esses exemplos mostram saída inconsistente em READ COMMITTED e REPEATABLE READ, mas você pode ajustá-los e obter resultados errados com NOLOCK também.
Se for esse o caso, você tem mais uma opção possível:
em vez de executar suas consultas no banco de dados de produção e mexer com bloqueios e
NOLOCK
, você pode executar seus relatórios a partir de uma cópia do banco de dados de produção.Você pode configurá-lo para que seja restaurado automaticamente a partir de um backup todas as noites .
Aparentemente, seus relatórios estão sendo executados em servidores nos sites dos clientes, então não sei se essa configuração seria uma solução viável para você.
(mas, novamente ... eles devem ter backups de qualquer maneira, então tudo que você precisa é de algum espaço no servidor para restaurá-los)
Sou um desenvolvedor interno, então isso é mais fácil para mim porque tenho controle total sobre os servidores e bancos de dados.
Você pode fazer isso pelo menos para os relatórios que precisam apenas de dados de ontem e mais antigos. Talvez alguns relatórios tenham que ficar no banco de dados de produção, mas pelo menos você move parte da carga para outro banco de dados (ou melhor ainda, outro servidor).
Eu também tenho a mesma situação no trabalho:
estamos usando uma cópia de banco de dados de produção como esta para quase todos os relatórios, mas há algumas consultas que exigem os dados de hoje.