Compartilhar via


Entendendo consultas com Hint NOLOCK

Em nosso dia-a-dia, usamos muitos hints de consulta para modificar a maneira como uma determinada consulta será executada.

Quando especificamos em uma consulta um hint, o SQL Server produz o plano otimizado usando este hint na consulta. Isso pode ser perigoso se não for testado antes em UAT como é conhecido fato do plano de consulta que o SQL Server faz usando seu otimizador, que é o seu bem mais valioso, o melhor.

O algoritmo que é escrito para este otimizador em baixo nível não é conhecido para as pessoas comuns, como é feito o melhor/otimizado plano com custo mais rentável não é conhecido pelo mundo exterior, mas sabemos que ele faz. Consultas com hints específicos sugerem como é utilizada toda consulta e afetam todos os operadores da instrução.

Um hint de consulta é o NOLOCK. Como o nome sugere, muitos usuários sentem que, quando esse hint é especificado na consulta, a operação não tem bloqueio (lock). Este não é o caso !

Vou demonstrar isso usando consulta simples. Eu criei uma tabela simples com o campo  "e_id" como PK e os campos "nome", "endereço" e "celular".

BEGIN TRAN   
  
SELECT   * FROM    dbo.employee WHERE   e_id = 'a1' 
    
EXEC   sp_lock

Se você olhar abaixo, esta operação tem o SPID 55 que é o ID do código que foi executado. Ele recebeu dois bloqueios "IS" e "S".

Na coluna "Mode"
S = Bloqueio Compartilhado
IS = Intenção Compartilhada

Na coluna "Type"
DB = Banco de Dados
TAB = Tabela

Agora vamos executar mesma consulta com o hint NOLOCK e ver se ele realmente tem qualquer bloqueio.

BEGIN TRAN   
  
SELECT   * FROM    dbo.employee WITH(NOLOCK) WHERE   e_id = 'a1' 
    
EXEC   sp_lock

Como podemos ver, o mesmo bloqueio ocorre na mesma tabela (veja a coluna "ObjId" nas figuras anteriores, eles tem o mesmo 1131151075). IS e S.

Assim, qual é a diferença entre uma consulta de executada com NOLOCK e uma que não é há qualquer referência de consulta NOLOCK ? 

A diferença vem quando ambos estão tentando selecionar dados da tabela que tomou bloqueio exclusivo, quero dizer, a diferença vem quando a consulta está tentando acessar a tabela que está bloqueada por executar um comando INSERT/UPDATE.

Vou mostrar isso consultando e executando um comando UPDATE na mesma tabela para a mesma linha.

BEGIN TRAN   
  
UPDATE   dbo.employee SET  e_name='SHASHANK'  WHERE   e_id = 'a1' 
    
EXEC   sp_lock

Agora eu executo esta mesma consulta na query1 e na query2

Query1 - Executando com o hint NOLOCK

Query2 - Executando com qualquer hint

Agora vamos ver a diferença: a consulta com hint NOLOCK produziu resultado, mas a consulta simples sem nenhum hint não produz qualquer resultado. Ela está bloqueada, o que pode ser visto através da execução sp_who2, com o resultado abaixo:

Como você pode ver, o SPID 56 está bloqueando o SPID 55. Então eu executei o comando DBCC INPUTBUFFER para encontrar texto correspondente a estes SPID,  que retornou o seguinte resultado:


A partir do resultado da consulta acima, fica claro que quando usamos o hint NOLOCK na consulta, a transação pode ler dados da tabela que está bloqueado por comandos UPDATE/INSERT/DELETE, tendo o bloqueio exclusivo (bloqueio exclusivo não é compatível com qualquer outro lock). Mas, se na mesma transação não usamos o hint de consulta (NOLOCK), então a consulta será bloqueada pelo comando UPDATE.

A desvantagem do NOLOCK é ler "sujeira". Portanto, não é aconselhável utilizar em ambiente de produção. Mas pode ser utilizado para ler dados de uma tabela de partição, que não serão atualizados quando executar um SELECT. Como você pode executar uma consulta para obter dados de uma Tabela particionada contendo dados de janeiro 2013, resumindo, onde não há registros para atualizar.


Veja Também


Outros Idiomas

Este artigo também está disponível nos seguintes idiomas: