SQL Server 2008R2 - ReadCommitted 隔离级别
我正在尝试准确计算 SQL 服务器何时将更新锁转换为独占锁。例如,我有表 dbo.TableA。dbo.TableA 有两列 PKCol1 和 NCCol2。PKCol1 是一个聚集索引,而 NCCol2 上有一个非聚集索引。如果我要执行
BEGIN TRAN
DELETE
FROM dbo.TableA
WHERE NCCol2 = 1
COMMIT TRANSACTION
并且优化器选择扫描 NCCol2 以查找所有候选记录,非聚集索引运算符是否会扫描索引中的所有记录。将更新锁添加到每个候选记录,直到它扫描了整个索引,然后聚集索引删除操作员将这些锁转换为排他锁并删除。
或者非聚集索引运算符是否会依次扫描每条记录,将更新锁添加到候选记录,评估该行是否匹配以及是否将更新锁转换为排他锁。
基本上哪个操作员将更新锁转换为排他锁,一旦扫描识别出记录是匹配的非聚集索引扫描,或者一旦候选行被识别并传递给它,就会删除聚集索引?
网上的书告诉我
更新(U)
用于可以更新的资源。防止在多个会话读取、锁定和稍后可能更新资源时发生的常见死锁形式
和
独家 (X)
用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不能同时对同一资源进行多次更新。
附加信息 1
在优化器选择以下计划后,我实际上正在调查以下非唯一非集群 INT Index2 上发生的死锁
死锁翻译为
- 受害者在 dbo.Table1 Index2 row1 上获取了更新锁
- 所有者对 dbo.Table1 Index2 row2 进行了排他锁
- 受害者等待 dbo.Table1 Index2 row2 上的更新锁
- 所有者等待 dbo.Table1 Index2 row1 上的更新锁
我的理解是,执行计划中的每个操作符都是按照从右到左从上到下的顺序完整执行的。而且我的理解是,更新锁仅在 UPDATE/INSERT 或 DELETE 期间转换为独占锁,即聚集索引删除操作符。因此,我不确定为什么步骤 2 中的所有者在 Index2 row2 上有一个排他锁,这表明它在聚集索引删除步骤,但仍在等待更新锁,这表明它也是非聚集索引扫描步骤。怎么可能同时在这两个步骤?
但是,如果您认为在索引扫描期间同时使用了更新锁和排他锁,那么这种死锁会更有意义。
重新编译后,优化器选择在聚集索引上寻找没有问题
@Bogdan Sahlean 和 @brian - 非常感谢您的帮助和建议。