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: