我正在建立一个测试案例,以证明一定的僵局情况,并且需要对正在发生的事情有一些了解。我有一个堆表,方便地称为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更新处理堆中不同记录的原因会希望锁定相同的RID。我正在使用读取提交隔离。表上没有非聚集索引。