Я настраиваю тестовый пример, чтобы доказать определенный тупиковый сценарий и требовать некоторого понимания того, что происходит. У меня есть таблица кучи, условно называемая HeapTable. Эта таблица обновляется 2 транзакциями одновременно.
Транзакция 1:
BEGIN TRAN
UPDATE HeapTable
SET FirstName = 'Dylan'
WHERE FirstName = 'Ovidiu';
WAITFOR DELAY '00:00:15';
UPDATE HeapTable
SET FirstName = 'Bob'
WHERE FirstName = 'Thierry';
ROLLBACK TRANSACTION
Транзакция 2:
BEGIN TRAN
UPDATE HeapTable
SET FirstName = 'Pierre'
WHERE FirstName = 'Michael';
ROLLBACK TRAN
Сначала я запускаю транзакцию 1, за которой следует транзакция 2. Как и ожидалось, транзакция 1 потребует несколько исключительных блокировок, а также некоторые намеренные эксклюзивные блокировки. Транзакция 2 придет и запросит блокировку обновления для того же RID:
spid dbid ObjId IndId Type Resource Mode Status
55 5 711673583 0 RID 1:24336:10 X GRANT
57 5 711673583 0 RID 1:24336:10 U WAIT
Я был немного удивлен, увидев, что вторая транзакция запрашивает блокировку обновления для того же RID, поскольку я думал, что это указывает на одну запись, и оба оператора обновления обрабатывают разные данные. Вместо этого я ожидал конфликта на уровне страницы.
Когда второе обновление транзакции 1 пинает в транзакции 2, будет рассматриваться как жертва тупика, что приведет к откату транзакции 2 и завершению транзакции 1.
Может кто-нибудь объяснить мне, почему вторая транзакция потребует блокировки обновления для того же RID, хотя обновляет другую запись?
Я знаю, как это исправить (например, с помощью индекса). Я не ищу исправления, я на самом деле ищу объяснение того, почему 2 Updates, обрабатывающие разные записи в куче, захотят заблокировать один и тот же RID. Я использую прочитанную преданную изоляцию. В таблице нет некластеризованных индексов.
источник