Edit: Como o @MaxVernon aponta, o seguinte não é de forma alguma uma sugestão para usar o NOLOCK , e eu muito bem deveria ter acabado de mencionar definir o nível da transação READ UNCOMMITED
e deixar a conotação negativa lá do que mencionar NOLOCK
em primeiro lugar. Então, como publicado originalmente:
O mais rápido e simples é "Sim, a primeira consulta bloqueará a segunda consulta, a menos que uma dica específica do índice seja especificada ( NOLOCK , às vezes chamada de" leitura suja ") ou o nível de isolamento da transação da segunda consulta esteja definido como READ UNCOMMITED
(que opera de forma idêntica), não, não tem."
Em resposta aos detalhes adicionais fornecidos na pergunta que envolvem a inclusão de uma WITH
cláusula na segunda SELECT
, sendo mutuamente exclusivos ou não, as interações entre as duas consultas serão praticamente as mesmas.
IF NOT EXISTS ( SELECT 1
FROM sys.objects
WHERE name = 'Foo'
AND type = 'U' )
BEGIN
--DROP TABLE dbo.Foo;
CREATE TABLE dbo.Foo
(
Foo_PK BIGINT IDENTITY( 1, 1 ) NOT NULL,
PRIMARY KEY ( Foo_PK ),
Bar BIT,
x BIT,
y BIT,
z BIT
);
CREATE NONCLUSTERED INDEX IX_Foo_x
ON dbo.Foo ( x );
INSERT INTO dbo.Foo ( Bar, x, y, z )
VALUES ( 1, 1, 1, 1 ), ( 0, 0, 0, 0 );
END;
GO
BEGIN TRANSACTION;
UPDATE dbo.Foo
SET y = 0
WHERE x = 1;
-- COMMIT TRANSACTION;
Em uma sessão separada, execute o seguinte:
SELECT *
FROM dbo.Foo WITH ( NOLOCK );
GO
SELECT *
FROM dbo.Foo;
Você pode examinar os bloqueios atualmente em execução executando sp_lock
, de preferência em mais uma sessão separada:
EXECUTE dbo.sp_lock;
Você verá um KEY
bloqueio de tipo sendo retido pelo spid executando a transação de inserção no modo X
(exclusivo), para não ser confundido com os outros IX
bloqueios (exclusivo de intenção). A documentação do bloqueio indica que, embora o KEY
bloqueio seja específico do intervalo, ele também impede que outras transações insiram ou atualizem as colunas afetadas, alterando os dados nela contidos, para que possam ficar dentro desse intervalo da consulta original. Como o próprio bloqueio sendo mantido é exclusivo, a primeira consulta está impedindo o acesso ao recurso de qualquer outra transação simultânea. Com efeito, todas as linhas da coluna estão bloqueadas, estejam ou não dentro do intervalo especificado pela primeira consulta.
O S
bloqueio que está sendo mantido pela segunda sessão será assim WAIT
até que o X
bloqueio seja liberado, impedindo que outro X
(ou U
) bloqueio seja recebido nesse recurso de um spid simultâneo diferente antes que a segunda sessão conclua sua operação de leitura, justificando a existência do S
bloqueio.
Agora, uma edição para maior clareza: a menos que eu esteja enganado no que é uma leitura suja, a partir da breve descrição dos riscos mencionados aqui ... Editar 3 : Acabei de perceber que não estou considerando o efeito de um ponto de verificação de plano de fundo que escreve como de transação ainda não confirmada em disco, então sim, minha explicação foi enganosa.
Na segunda consulta, o primeiro lote pode (e, nesse caso,) retornar dados não confirmados. O segundo lote, em execução no nível de isolamento de transação padrão READ COMMITED
, retornará somente depois que uma confirmação ou reversão for concluída na primeira sessão.
A partir daqui, você pode examinar seus planos de consulta e os níveis de bloqueio associados, mas, melhor ainda, pode ler tudo sobre bloqueios no SQL Server aqui .
SELECT * FROM Table1
se é exatamente isso que eu preciso?