Обновление без блокировки записи

Задача:

Откройте первую транзакцию (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", но мы не можем обновить или удалить строку без эксклюзивной блокировки.

Другие вопросы по тегам