Suponha que eu tenha a seguinte consulta de longa duração
UPDATE [Table1]
SET [Col1] = 'some value'
WHERE [Col2] -- some clause which selects thousands of rows
e suponha que a consulta a seguir seja executada enquanto a consulta acima estiver em execução
SELECT *
FROM [Table1]
A primeira consulta impede a execução da segunda consulta até que a primeira seja concluída? Nesse caso, a primeira consulta impede que a segunda consulta seja executada em todas as linhas ou apenas nas linhas envolvidas na cláusula WHERE?
EDITAR:
Suponha que a segunda consulta seja
SELECT [Col1], [Col2]
FROM [Table1]
WHERE [Col2] -- some clause whose matching elements overlap those from
-- the clause in the first query and which has additional matching elements
fonte
SELECT * FROM Table1
se é exatamente isso que eu preciso?*
por si só, é uma prática ruim porque, quando a estrutura da tabela é alterada, o aplicativo geralmente quebra (colunas inesperadas aparecem no resultado).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 mencionarNOLOCK
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 segundaSELECT
, sendo mutuamente exclusivos ou não, as interações entre as duas consultas serão praticamente as mesmas.Em uma sessão separada, execute o seguinte:
Você pode examinar os bloqueios atualmente em execução executando
sp_lock
, de preferência em mais uma sessão separada:Você verá um
KEY
bloqueio de tipo sendo retido pelo spid executando a transação de inserção no modoX
(exclusivo), para não ser confundido com os outrosIX
bloqueios (exclusivo de intenção). A documentação do bloqueio indica que, embora oKEY
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á assimWAIT
até que oX
bloqueio seja liberado, impedindo que outroX
(ouU
) 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 doS
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 .
fonte
WITH (NOLOCK)
seria útil neste caso. Veja brentozar.com/archive/2011/11/… e brentozar.com/archive/2013/02/… para mais informações.WITH (NOLOCK)
dica não retorna páginas sujas da memória que não foram confirmadas. Na verdade, ele lê as linhas da tabela (em disco ou armazenadas em cache na memória) sem impedir que os gravadores atualizem ou adicionem linhas às páginas usadas pela tabela.