Редагувати: як зазначає @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
) блокування на цьому ресурсі від іншого одночасного шпіона до того, як другий сеанс завершить свою операцію читання, виправдовуючи існування S
блокування.
Тепер редагування для ясності: Якщо я не помиляюся з тим, що брудне прочитання - це короткий опис згаданих тут ризиків ... Edit 3 : Я щойно зрозумів, що не розглядаю ефект фонової контрольної точки, яка пише як ще не підтвердженої транзакції на диску, так що так, моє пояснення було вводити в оману.
У другому запиті перша партія може (і в цьому випадку буде) повертати незапущені дані. Друга партія, що працює на рівні ізоляції транзакцій за замовчуванням READ COMMITED
, повернеться лише після того, як фіксація або відкат буде виконано в першому сеансі.
Звідси ви можете переглянути свої плани запитів та пов'язані з ними рівні блокування, але ще краще, про все про блокування на SQL Server ви можете прочитати тут .
SELECT * FROM Table1
якщо це саме те, що мені потрібно?