Обновление без блокировки записи
Задача:
Откройте первую транзакцию (T1), которая обновляет некоторые строки и выполняет откат (всегда)
В то же время (после открытия T1, но до отката) другая транзакция T2 может изменить те же строки и зафиксировать их
В этом случае T2 ждет T1 (используется уровень изоляции READ_COMMITTED_SNAPSHOT)
Это можно сделать без ожидания?
Пример: первое окно запроса
IF NOT EXISTS ( SELECT *
FROM sysobjects
WHERE name = 'TestLockTable'
AND xtype = 'U' )
BEGIN
CREATE TABLE TestLockTable
(
Id INT NOT NULL ,
Name VARCHAR(64) NOT NULL
)
END
INSERT INTO dbo.TestLockTable
( Id, Name )
VALUES ( 1, 'test' )
BEGIN TRANSACTION T1
UPDATE dbo.TestLockTable
SET Name = 'test1'
WHERE Id = 1;
Во-вторых:
BEGIN TRANSACTION T2
SELECT *
FROM dbo.TestLockTable
WHERE Id = 1; --Select 'test' without wait
UPDATE dbo.TestLockTable
SET Name = 'test2'
WHERE Id = 1; --This T2 hang on
COMMIT TRANSACTION T2
И последнее:
ROLLBACK TRANSACTION T1
После отката T1, T2 может зафиксировать, и мы получаем 'test2' в строке
2 ответа
Все DML принимают X-блокировки, всегда. Это сделано для того, чтобы откаты выполнялись надежно. Обойти это невозможно, это основной принцип работы двигателя.
Вам нужен другой подход. В любом случае делать экзотические вещи с замками не рекомендуется, потому что это трудно понять правильно и сложно проверить.
Не зная, что вы пытаетесь достичь, я не могу предложить лучшую альтернативу.
Мы можем прочитать строку без ожидания, используя "with (nolock)" или "READ_COMMITTED_SNAPSHOT = false", но мы не можем обновить или удалить строку без эксклюзивной блокировки.