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.

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

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

Av. Cassiano Ricardo, 319 | Sala 1702 - 1703 | Jd. Aquarius
CEP: 12.246-870 | São José dos Campos - SP

  • Facebook Dataside
  • Instagram Dataside