O Falso Nolock

Boa tarde pessoal, como eu disse antes queria fazer o último post técnico do ano, talvez ainda não seja esse o último temos mais alguns dias pela frente rs.

Bom essa vai ser uma dica rápida e bem interessante, bom a maioria de vocês já deve conhecer e bem o tão criticado e muito utilizado hint de tabela ‘Nolock’, em palavras resumidas ele não emiti locks para leitura e não fica bloqueado por operações de Updates podendo fazer o que chamamos de leitura ‘suja’ que é equivalente ao nível de isolamento READUNCOMMITTED.

Sabemos que em diversos casos o ‘Nolock’ pode nos ajudar bastante, já prestei serviços em ambientes que o uso do ‘Nolock’ é obrigatório, vamos ver um exemplo sobre seu uso.

Para o exemplo vou utilizar um banco de dados meu já existente.

Esse é o uso tradicional do Hint ‘Nolock’, especificado pela cláusula WITH.

— Na primeira sessão abra a transação de UPDATE

begin tran
update TB_JOGADORES set NOME = ‘teste’ where APELIDO = ‘rafa’

–Na segunda sessão execute o SELECT

SELECT * FROM TB_JOGADORES With(nolock) where APELIDO = ‘rafa’

Porém sabemos que o nosso amigo ‘NOLOCK’ funciona também sem a cláusula ‘WITH’

SELECT * FROM TB_JOGADORES (nolock) where APELIDO = ‘rafa’

Os dois SELECTs acima funcionam e realizam a leitura suja normalmente e  retornam a informação rapidamente.

Há algum tempo atrás peguei alguns SELECTs rodando da seguinte forma na empresa que trabalhava.

SELECT * FROM TB_JOGADORES nolock where APELIDO = ‘rafa’

Sem os parênteses () e que em algumas ocasiões eu via o mesmo sendo bloqueado por outra operação de Update, hum algo estranho estava acontecendo ai rs. Bom vamos ver o plano de execução dessa query então.

screen-shot-12-28-16-at-01-10-pm

Aparentemente tudo normal, fazendo uma operação de Scan na tabela ‘TB_JOGADORES’, vamos ver mais detalhes desse operador Clustered Index Scan.

screen-shot-12-28-16-at-12-09-pm

Quando cheguei aqui, o mistério estava resolvido, o Hint ‘Nolock’ sem a cláusula ‘WITH’ e sem os parênteses () não é mas entendido como um Hint pelo otimizador de consultas do SQL Server e o Nolock vira o ‘Apelido’ da tabela e consequentemente esse SELECT vai ficar bloqueado, tanto que você pode fazer esse tipo de consulta.

SELECT * FROM TB_JOGADORES nolock where nolock.APELIDO = ‘rafa’

O otimizador entende que o Nolock é a sua tabela, então se você ver por ai  algum caso onde o ‘Nolock’ estiver sem parênteses () de uma olhada no seu plano de execução, provavelmente vai ser mais um caso do ‘Falso Nolock’, prefira sempre utilizar a cláusula ‘WITH (Nolock)’.

Não sei exatamente a versão do SQL Server que mudou isso, eu testei nas versões 2000, 2008 R2, 2012, 2014 e 2016, não sei se um dia isso chegou a funcionar. Futuramente o ‘(Nolock)’ sem a cláusula ‘WITH’ será descontinuada também.

Bom é isso galera, até a próxima dica.

 

Dica de leitura:

https://www.mssqltips.com/sqlservertip/2470/understanding-the-sql-server-nolock-hint/

Reginaldo Silva

Anúncios

5 comentários sobre “O Falso Nolock

  1. O nolock não deveria nunca ser utilizado. Desenvolvedores tem a ilusão de que o nolock apenas pode causar problemas se alguma de suas transações fizerem rollback, um risco aceitável. Mas não é verdade.

    Por não fazer lock algum, o nolock lê a tabela mesmo quando o SQL Server está realizando tarefas de manutenção, tal como um page split. Lendo as informações em meio a ocorrência de um page split, o nolock pode pular registros ou ler registros duplicados sem que isso tenha nenhuma causa no negócio. O resultado de uma query com nolock é totalmente instável, por isso deve-se utilizar locks otimistas ao invés de nolock.

    Curtido por 1 pessoa

    • Fala Dennes, obrigado por deixar seu comentário, concordo com você, mas sabemos que a realidade é outra né, como mencionei ali em cima, em alguns clientes o Nolock era obrigatório pelo time de desenvolvimento, e não foi só em um lugar que vi isso não rs.
      O Grande problema do Nolock é que a maioria das pessoas que usa não sabe dos riscos por traz, sabendo dos riscos e que não impacte em resultados o seu uso pode até ser aceitável sim.

      Curtir

      • É exatamente isso que comentei: É impossível se determinar que o nolock “não impacte em resultados”. Isso é uma ilusão de desenvolvedores que acreditam que o nolock impacta apenas em situações de rollback transacional.

        Como expliquei, o nolock afeta ocorrências de page splits. Isso é absolutamente impossível de ser previsto, faz com que qualquer resultado possa ser afetado pelo nolock e por isso o nolock não deve NUNCA ser utilizado, é um erro técnico. Deve-se utilizar isolamento otimista no lugar de nolock.

        Curtido por 1 pessoa

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s