Редактировать: Как указывает @MaxVernon , следующее ни в коем случае не является предложением использовать NOLOCK , и я очень хорошо должен был упомянуть, что установил уровень транзакции READ UNCOMMITED
и позволил негативной коннотации стоять там, чем NOLOCK
подниматься в первую очередь. Итак, как первоначально размещено:
Быстрый и простой ответ: «Да, первый запрос заблокирует второй запрос, если не указана определенная подсказка индекса ( NOLOCK , иногда называемая« грязным чтением »), или если уровень изоляции транзакции второго запроса установлен на READ UNCOMMITED
(который работает идентично), нет."
В ответ на дополнительные детали, представленные в вопросе, которые влекут за собой включение WITH
второго предложения SELECT
, являющегося взаимоисключающим или иным образом, взаимодействия между этими двумя запросами будут в основном одинаковыми.
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;
В отдельном сеансе выполните следующее:
SELECT *
FROM dbo.Foo WITH ( NOLOCK );
GO
SELECT *
FROM dbo.Foo;
Вы можете проверить блокировки, которые в настоящее время удерживаются, запустив sp_lock
, желательно в еще одном отдельном сеансе:
EXECUTE dbo.sp_lock;
Вы должны увидеть, что KEY
блокировка типа удерживается спидом, выполняющим транзакцию вставки в X
(исключительном) режиме, не путаясь с другими IX
( намеренно исключающими ) блокировками. Документация о блокировке указывает, что хотя KEY
блокировка зависит от диапазона, она также не позволяет другим транзакциям вставлять или обновлять затронутые столбцы, изменяя содержащиеся в них данные, чтобы они могли попадать в этот диапазон исходного запроса. Поскольку удерживаемая блокировка является исключительной, первый запрос запрещает доступ к ресурсу из любой другой параллельной транзакции. Фактически все строки столбца блокируются независимо от того, попадают ли они в диапазон, указанный в первом запросе.
Таким образом, S
блокировка, удерживаемая вторым сеансом, будет WAIT
действовать до тех пор, пока X
блокировка не будет снята , не позволяя другой X
(или U
) блокировке принять этот ресурс с другого параллельного spid до того, как второй сеанс завершит свою операцию чтения, оправдывая существование S
блокировки.
Теперь отредактируйте для ясности: если я не ошибаюсь в том, что грязное чтение взято из краткого описания рисков, упомянутых здесь ... Редактировать 3 : Я только что понял, что не рассматриваю эффект фоновой контрольной точки, которая пишет как о еще не совершенной транзакции на диск, так что да, мое объяснение вводило в заблуждение.
Во втором запросе первая партия может (и в этом случае будет) возвращать незафиксированные данные. Второй пакет, работающий с уровнем изоляции транзакции по умолчанию READ COMMITED
, вернется только после завершения фиксации или отката в первом сеансе.
Отсюда вы можете посмотреть свои планы запросов и соответствующие уровни блокировки, но, что еще лучше, вы можете прочитать все о блокировках в SQL Server здесь .
SELECT * FROM Table1
если это именно то, что мне нужно?