Jen*_*ens 8 sql-server deadlock
我正在设置一个测试用例来证明某个死锁场景,并需要对正在发生的事情有一些了解。我有一个堆表,方便地称为 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
Run Code Online (Sandbox Code Playgroud)
交易2:
BEGIN TRAN
UPDATE HeapTable
SET FirstName = 'Pierre'
WHERE FirstName = 'Michael';
ROLLBACK TRAN
Run Code Online (Sandbox Code Playgroud)
我首先触发事务 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
Run Code Online (Sandbox Code Playgroud)
看到第二个事务请求在同一个 RID 上更新锁,我有点惊讶,因为我认为这指向一个记录,并且两个更新语句处理不同的数据。我以某种方式期待页面级别的冲突。
当事务 1 的第二次更新启动事务 2 时,将被视为死锁受害者,导致事务 2 回滚并完成事务 1。
有人能解释一下为什么第二个事务虽然更新了不同的记录,但需要对同一个 RID 进行更新锁定吗?
我知道如何解决这个问题(例如使用索引)。我不是在寻找修复程序,我实际上是在寻找解释为什么处理堆中不同记录的 2 个更新要锁定相同的 RID。我正在使用读提交隔离。表上没有非聚集索引。
Pau*_*ite 18
如果没有索引FirstName
,SQL Server 必须检查每一行以查看它是否符合UPDATE
.
U
读取每一行时需要一个更新锁,以防止常见的死锁情况。它可能需要一个共享S
锁,但它仍然会被X
第一个事务持有的排它锁阻塞。
归档时间: |
|
查看次数: |
935 次 |
最近记录: |