Efeitos Colaterais do WITH (NOLOCK) – Parte II

Como havia mostrado no post anterior, o uso do NOLOCK pode causar comportamentos estranhos. Nesse post, vou concentrar a atenção para o ERRO 601.

 Msg 601, Level 12, State 3, Line 1
Could not continue scan with NOLOCK due to data movement.

A interpretação usual é que o erro foi decorrente de uma situação de acesso concorrente, na qual as estruturas são modificadas durante uma operação de Table/Index Scan. O próprio Books Online orienta a aplicação a executar o comando novamente ( If you receive the error message 601 when READUNCOMMITTED is specified … retry your statement ). Como o NOLOCK acessa a tabela sem locks, pode acontecer erros de acesso simultâneo. Esse é o famoso comportamento denominado by design.

(No SQL 2000, havia uma situação semelhante relacionada com o Bookmark Lookup. Esse comportamento foi resolvido no SQL2005/2008 com a mudança do operador de Bookmark Lookup para um Nested Loop)

Links relacionados

Qual o outro problema do NOLOCK?

Essa mensagem de erro possui um comportamento bastante inconveniente, que é sua baixa severidade (Msg 601, Level 12, State 3). Quando Table/Index Scans são realizados com a hint NOLOCK, os erros de consistência de dados gerados pelo Access Manager ou Buffer Manager são automaticamente convertidos no erro 601 – ou deveria dizer, encobertos?

A situação que me deparei essa semana foi uma corrupção de banco de dados (erro extremamente crítico!), que foi convertido no erro 601.

Rodamos o comando:

 SELECT * FROM tabela 

O resultado foi uma mensagem de corrupção de banco de dados com severidade 24 e os erros foram registrados no ERRORLOG.

Msg 824, Level 24, State 2, Line 2

SQL Server detected a logical consistency-based I/O error: incorrect pageid (expected 1:153; actual 257:16843009). It occurred during a read of page (1:153) in database ID 11 at offset 0x00000000132000 in file 'D:\MSSQL\DATA\impcustDb.mdf'. Additional messages in the SQL Server error log or system event log may provide more detail. This is a severe error condition that threatens database integrity and must be corrected immediately. Complete a full database consistency check (DBCC CHECKDB). This error can be caused by many factors; for more information, see SQL Server Books Online.

Porém, a aplicação usava a hint NOLOCK:

 SELECT * FROM tabela (NOLOCK)

Durante a execução da query, retornava-se a mensagem abaixo e ninguém foi notificado sobre o problema.

 Msg 601, Level 12, State 3, Line 1
Could not continue scan with NOLOCK due to data movement.

Isso significa que o erro 601 pode mascarar erros críticos!

Uma alternativa para o uso do NOLOCK seria habilitar a opção de READ COMMITTED SNAPSHOT do banco de dados.

 ALTER DATABASE <Database> SET READ_COMMITTED_SNAPSHOT ON 

As leituras versionadas não causam bloqueios ou deadlocks nas operações de escrita (Update, Insert, Delete). Existe, no entanto, um custo adicional ao utilizar a opção de snapshot, que seria a utilização do TempDB para armazenamento de versões.

 

Conclusão

Encontrou erros 601?

  • Verifique a frequência dos erros. Se o problema ocorre sempre, então vale a pena verificar a integridade dos dados com DBCC CHECKDB ou CHECKTABLE.
  • Faça um teste sem NOLOCK para verificar se a query funciona corretamente
  • Utilize o READ_COMMITTED_SNAPSHOT como uma alternativa ao NOLOCK