Clique no banner para conhecer e adquirir o meu treinamento de Bancos de Dados no Azure

SQL Server – NOLOCK vs READPAST: Você sabe a diferença entre os dois ?

Visualizações: 3.752 views
Tempo de Leitura: 4 minutos

Fala galera!
Nesse artigo eu gostaria de demonstrar na prática, o uso de 2 query hints bastante utilizados pelos desenvolvedores para evitar locks na leitura de dados, que são o NOLOCK e o READPAST, e demonstrar efetivamente qual o efeito desses hints em uma consulta.

A ideia de escrever esse artigo veio através de uma dúvida enviada no grupo “SQL Server – DBA”, do Telegram, e também num desejo antigo de escrever sobre isso sempre que vejo ambientes onde quase todas as consultas tem NOLOCK.

Depois de ler esse post, você será capaz de entender exatamente como esses 2 hints funcionam e vai utilizá-los sabiamente e apenas quando conveniente. Nada de sair colocando NOLOCK/READPAST em todas as suas consultas hein!

Caso seu ambiente tenha uma grande concorrência e os locks, blocks e deadlocks sejam frequentes e um problema para você, sugiro pensar numa abordagem mais completa que utilizar esse hints, que seria utilizar o modo de isolamento Read Committed Snapshot (RCSI), que permite utilizar o modo Read Commited sem travar as leituras quando ocorrem transações abertas. Como nem tudo são flores, existem alguns efeitos colaterais ao se utilizar esse modo, como possível queda de performance. Caso você queira saber mais sobre ele, sugiro a leitura do artigo Read Committed Snapshot Isolation: Writers Block Writers (RCSI), do grande mestre Brent Ozar.

Para demonstrar como funciona o NOLOCK e o READPAST, vamos criar uma tabela com alguns registros:

Tabela atual:

[Vídeo] – NOLOCK vs READPAST

NOLOCK ou READ UNCOMMITED

Modo de isolamento bem conhecimento pelos DEVs, que permite retornar os dados atuais da tabela sem ter que aguardar o fim das transações em andamento, fazendo a “leitura suja” dos dados, isto é, caso existam transações alterando os dados das tabelas que estão sendo consultadas, esses registros serão retornados da forma que estão, mesmo que as transações ainda estejam abertas (não foi feito commit ou rollback) e esses dados não sejam definitivos ainda.

Esse tipo de leitura pode ser bem útil em casos de alta concorrência e ocorrência de locks e deadlocks no ambiente, mas tenha em mente os efeitos colaterais de utilizar o hint NOLOCK (equivalente ao comando SET TRANSACTION ISOLATION LEVEL READ UNCOMMITED ou WITH(READUNCOMMITTED)).

Exemplo prático do NOLOCK

Em uma sessão do SQL Server Management Studio (SSMS), execute o comando abaixo:

Abra mais uma sessão no SSMS e execute o comando abaixo:

Reparem que essas 2 sessões abriram uma transação, efetuaram alterações nos dados, mas ainda não foi feito commit e nem o rollback, ou seja, esses dados modificados ainda podem ser considerados como dados “temporários”, uma vez que eles não são dados commitados e confirmados. Caso haja algum problema no fluxo ou simplesmente o usuário deseje desfazer essas alterações, ele pode fazer o rollback dessas transações e esses dados inseridos/alterados nunca existiram “oficialmente”.

Mesmo assim, se ainda nesse cenário, você abrir uma nova sessão e tentar consultar os dados, verá que a sua sessão ficará aguardando indefinidamente, até que as transações sejam finalizadas com COMMIT ou ROLLBACK. Isso ocorre porque o modo de leitura padrão do SQL Server é o READ COMMITED, ou seja, retorna apenas os dados que já foram commitados no banco.

Utilizando o hint NOLOCK, você poderá retornar os dados sem ter que aguardar a finalização dessas transações, mas os dados que ainda nem foram commitados serão retornados como se fossem dados já definitivos:

Caso essas sessões realizem um ROLLBACK dos dados, você acabou consultando dados que nunca existiram de fato. Isso em um relatório poderia acabar produzindo resultados incorretos.

READPAST

Outra forma de conseguir ler dados de tabelas que estão sendo alteradas por transações em aberto sem ter que esperar o término dessas transações, é utilizar o hint READPAST. Diferente do NOLOCK, o READPAST não permite leituras sujas (salve exceções), mas entenda como ele funciona: O READPAST vai retornar apenas os dados que não estão sendo afetados por transações em aberto.

Exemplo prático do NOLOCK

Em uma sessão do SQL Server Management Studio (SSMS), execute o comando abaixo:

Abra mais uma sessão no SSMS e execute o comando abaixo:

E agora, vamos tentar ler os dados utilizando o hint READPAST e ver como os registros não commitados serão retornados:

Utilizando o hint READPAST, você poderá retornar os dados sem ter que aguardar a finalização dessas transações, mas os dados que ainda não foram commitados não serão retornados pelo SELECT, ou seja, registros podem ser ignorados nesse modo de leitura. Quando você está utilizando funções de agregação, como SUM, MAX, MIN, nesse modo de leitura, os valores finais podem ser bem diferentes dos valores reais, já que registros podem ser ignorados.

NOLOCK ou READPAST?

Para finalizar e resumir esse artigo, tanto o NOLOCK quanto o READPAST tem como principal justificativa de uso, a possibilidade de ler dados em tabelas sem ter que esperar que as transações ativas sejam finalizadas, minimizando a ocorrência de locks e blocks, mesmo que esses registros estejam sendo alterados por essas transações.

Ao utilizar o NOLOCK (ou READ UNCOMMITED), caso a tabela tenha 10 linhas e 3 estejam sendo alteradas por UPDATE/DELETE, o comando de SELECT vai retornar todas as 10 linhas, já com os dados “atualizados”. Novas linhas inseridas que ainda não foram commitadas também serão retornadas pelo SELECT.

Ao utilizar o READPAST, caso a tabela tenha 10 linhas e 3 estejam sendo alteradas por UPDATE/DELETE, o comando de SELECT vai retornar apenas as 7 linhas que não estão sendo alteradas. Novas linhas inseridas que ainda não foram commitadas NÃO serão retornadas pelo SELECT.

Referências:
https://docs.microsoft.com/pt-br/sql/t-sql/language-elements/transaction-isolation-levels?view=sql-server-2017
https://www.tiagoneves.net/blog/isolation-level-no-sql-server/
http://www.diegonogare.net/2013/01/transaction-isolation-level-voc-est-usando-certo/
https://imasters.com.br/data/entendendo-transaction-isolation-level-no-sql-server