Col*_*nee 3 sql-server deadlock sql-server-2008-r2 locking update
我正在调查由两个并发 UPDATE 语句引起的死锁:
UPDATE [table]
SET [column] = 0
WHERE [unindexed_column] = @id
Run Code Online (Sandbox Code Playgroud)
我的理解是,因为WHERE
预测的列是未索引的,所以执行了全表扫描。对于每一行,获取一个更新锁。如果它与WHERE
子句匹配,则它升级到排他锁并保持它直到语句完成。
当会话 A 拥有第 2 行的排他锁并试图获取第 1 行的更新锁,而会话 B 拥有第 1 行的排他锁并试图获取第 2 行的更新锁时,就会发生死锁。
死锁的原因是有道理的,但我不完全理解如何执行表扫描使这种情况成为可能。如果两个查询以相同的顺序执行扫描,最坏的情况似乎是其中一个查询在获取更新锁时被阻塞,直到另一个查询完成并释放它的锁。
表扫描是如何执行的?表格行的扫描顺序是否不一致?如果更新语句未能获得更新锁,它是否会转到下一行并稍后再次尝试上一行?究竟是什么让这种僵局成为可能?
表扫描的顺序永远无法保证。行被锁定的顺序也不能保证。另外,SQL Server 有锁升级,所以你真的不能说引擎决定锁什么,行,页,还是表本身。
因此,即使并发会话中@id 的值不同,也可能发生死锁,但感兴趣的行恰好位于相同的页面上。在 SQL Server 2008 及更高版本中,您可以添加提示ROWLOCK
以减少锁升级的机会(但同样不能保证)。如果UPDATE
无法获取锁,则等待(LOCK_TIMEOUT
指定等待多长时间)。
归档时间: |
|
查看次数: |
1008 次 |
最近记录: |