NOLOCK do SQL Server e ingressa

153

Antecedentes: tenho uma consulta crítica ao desempenho que gostaria de executar e não me importo com leituras sujas.

Minha pergunta é; Se eu estiver usando junções, também preciso especificar a dica NOLOCK?

Por exemplo; é:

SELECT * FROM table1 a WITH (NOLOCK)
INNER JOIN table2 b WITH (NOLOCK) ON a.ID = b.ID

Equivalente a:

SELECT * FROM table1 a WITH (NOLOCK)
INNER JOIN table2 b ON a.ID = b.ID

Ou precisarei especificar a (NOLOCK)dica na associação para garantir que não estou bloqueando a tabela unida?

DanP
fonte

Respostas:

166

Não vou abordar o READ UNCOMMITTED argumento, apenas sua pergunta original.

Sim, você precisa WITH(NOLOCK)em cada tabela da associação. Não, suas consultas não são as mesmas.

Tente este exercício. Inicie uma transação e insira uma linha na tabela1 e tabela2. Não confirme ou reverta a transação ainda. Nesse ponto, sua primeira consulta retornará com sucesso e incluirá as linhas não confirmadas; sua segunda consulta não retornará porque table2 não tem a WITH(NOLOCK)dica.

codeConcussion
fonte
18

Eu tinha certeza de que você precisa especificar o NOLOCKpara cada um JOINna consulta. Mas minha experiência foi limitada ao SQL Server 2005.

Quando procurei o MSDN apenas para confirmar, não consegui encontrar nada definitivo. As declarações abaixo parecem me fazer pensar que, para 2008, suas duas declarações acima são equivalentes, embora em 2005 não seja o caso:

[SQL Server 2008 R2]

Todas as dicas de bloqueio são propagadas para todas as tabelas e visualizações acessadas pelo plano de consulta , incluindo tabelas e visualizações mencionadas em uma visualização. Além disso, o SQL Server executa as verificações de consistência de bloqueio correspondentes.

[SQL Server 2005]

No SQL Server 2005, todas as dicas de bloqueio são propagadas para todas as tabelas e modos de exibição mencionados em um modo de exibição. Além disso, o SQL Server executa as verificações de consistência de bloqueio correspondentes.

Além disso, aponte para observação - e isso se aplica a 2005 e 2008:

As dicas da tabela serão ignoradas se a tabela não for acessada pelo plano de consulta. Isso pode ser causado pela opção do otimizador de não acessar a tabela, ou porque uma exibição indexada é acessada. No último caso, o acesso a uma exibição indexada pode ser evitado usando a OPTION (EXPAND VIEWS)dica de consulta.

Jagmag
fonte
@ Em Sane: Interessante ... obrigado por isso ... Estou assumindo que não estou fazendo mal ao incluí-lo no JOINS, mesmo que não seja totalmente necessário? A documentação do NOLOCK é bastante esparsa, como você mencionou; Eu tive problemas para encontrar algo conclusivo.
DanP
2
@ InSane: De onde você tirou essas informações? Parece ir contra a resposta aceita.
Jay Sullivan
1
@notfed - consulte o link do technet technet.microsoft.com/en-us/library/ms187373(v=sql.105).aspx - você pode alterar a versão do banco de dados na parte superior para comparar o mesmo artigo em diferentes versões do db
Jagmag
2
O texto de 2005 fala sobre VIEWS. Portanto, se você "do myview com (nolock)", ele diz que o nolock é propagado para todas as tabelas e visualizações envolvidas no myview (você pode ter 10 junções). Não tenho certeza do significado exato do texto de 2008, pois adiciona "acessado pelo plano de consulta" além das visualizações.
Thierry_S
9

Nem. Você define o nível de isolamento paraREAD UNCOMMITTED sempre melhor do que fornecer dicas de bloqueio individuais. Ou, melhor ainda, se você se preocupa com detalhes como consistência , use o isolamento de instantâneo .

Remus Rusanu
fonte
@Remus: Não tenho certeza se posso usar READ UNCOMMITTED no meu caso, porque estou acessando a conexão através do NHibernate para executar uma chamada ADO.NET bruta especial; isso pode ser especificado em linha na consulta ou obedecerá ao nível de transação presente na transação NHibernate?
DanP
Encerre a chamada using (TransactionScope scope=new TransactionScope(..., TransactionOptions) {...}e defina as IsolationLevelopções: msdn.microsoft.com/en-us/library/…
Remus Rusanu
@Remus: Infelizmente, o gerenciamento de transações é tratado em um nível muito mais alto do que isso, portanto, isso também não é uma opção.
DanP
Entendo. Em seguida, para responder à sua pergunta: NOLOCK é uma dica de tabela e, como tal, se aplica ao conjunto de linhas ao qual está sendo adicionado (tabela, exibição, TVF etc.). Se você tiver vários conjuntos de linhas unidos em uma consulta, cada um deles precisará de sua própria dica NOLOCK.
Remus Rusanu
2
Mas você já considerou o isolamento de instantâneo? ALTER DATABASE ... SET READ_COMMITTED_SNAPSHOT ON;. Os resultados são espetaculares, pois todas as leituras normais de leitura confirmada se transformam em leituras de instantâneo, bloqueando-as de maneira livre e consistente. O custo é uma tempdbcarga aumentada : msdn.microsoft.com/en-us/library/ms175492.aspx
Remus Rusanu