Sql 更新到独占锁转换
SQL Server 2008R2-ReadCommitted隔离级别 我正在尝试计算SQL server何时将更新锁转换为独占锁。例如,我有表dbo.TableA。dbo.TableA有两列PKCol1和NCCol2。PKCol1是聚集索引,NCCol2上有一个非聚集索引。如果我要执行Sql 更新到独占锁转换,sql,sql-server,sql-server-2008-r2,locking,Sql,Sql Server,Sql Server 2008 R2,Locking,SQL Server 2008R2-ReadCommitted隔离级别 我正在尝试计算SQL server何时将更新锁转换为独占锁。例如,我有表dbo.TableA。dbo.TableA有两列PKCol1和NCCol2。PKCol1是聚集索引,NCCol2上有一个非聚集索引。如果我要执行 BEGIN TRAN DELETE FROM dbo.TableA WHERE NCCol2 = 1 COMMIT TRANSACTION 优化者选择扫描NCCol2以查找所有候选记录,而非聚集索
BEGIN TRAN
DELETE
FROM dbo.TableA
WHERE NCCol2 = 1
COMMIT TRANSACTION
优化者选择扫描NCCol2以查找所有候选记录,而非聚集索引操作符则扫描索引中的所有记录。向每个候选记录添加更新锁,直到扫描完整个索引,然后聚集索引删除操作符将这些锁转换为独占锁并删除
或者,非聚集索引操作符会依次扫描每条记录,向候选记录添加更新锁,评估该行是否匹配,以及是否将更新锁转换为独占锁
基本上,哪一个操作符将更新锁转换为独占锁,即在扫描确定记录是匹配项后进行非聚集索引扫描,或者在确定候选行并将其传递给它后进行聚集索引删除
网上书籍告诉我
更新(U)
用于可更新的资源。防止在多个会话读取、锁定和稍后可能更新资源时发生常见形式的死锁
及
独家(X)
用于数据修改操作,如插入、更新或删除。确保不能同时对同一资源进行多个更新
附加信息1
我实际上是在调查一个死锁,它发生在下面的非唯一非聚集INT Index2上,在优化者选择了以下计划之后
僵局被解释为
IDA
-非聚集索引的键是NCCol2
-表A
内容:
-- Clustered index (C index)
NCCol2 IDA lockhash (these values are the "identifier" of locks)
------ --- --------------
1 11 (29cf3326f583)
2 22 (31178495a25a)
-- Non-Clustered index (NC index)
NCCol2 lockhash
------ --------------
1 (8194443284a0)
2 (61a06abd401c)
在这方面:
Index Seek
(在非聚集索引上,使用NCCol2
键)查找记录,并选择一个运算符删除记录:
Index Seek
(onNCCol2
)运算符使用此谓词(NNCol2=1
)查找记录U
锁(参见lockhash(8194443284a0)
),并对聚集索引中的相应记录取另一个U
锁(PK;参见lockhash(29cf3326f583)
)U
锁(lockhash(29cf3326f583)
)被转换为X
锁,非聚集索引记录上的U
锁(lockhash(8194443284a0)
)也被转换为X
锁X
锁被释放Lock:Aquired
和Lock:Released
):
TLTR:索引查找(查找记录)>NC索引记录U锁>C索引记录U锁>C索引记录U->X>NC索引记录U->X>删除记录>重复(查找另一行)
编辑1:
Scan
可能有很多原因:
1) 一些(正如brian指出的)由类型优先级生成的(1
将是TINYINT
,如果数据库配置为简单参数化
,或者1
将具有与列类型相同的类型,如果数据库配置为强制参数化
)
2) 可以禁用索引
3) 它是一个过滤索引(),或者是在计算列上定义的索引,设置()不合适
4) 这是一个经过过滤的索引,数据库已激活参数化强制设置
5) [低概率]这是一个小表,(出于某种原因)SQL Server为@Bogdan的内部结构选择了扫描
而不是搜索
+1。只要NCCol2与它所比较的相等值的类型相同,这一点就成立。例如,如果NCCol2是varchar(25),并且相等值是int,那么它将是一个nc扫描,因为数据类型优先级要求varchar端在比较之前获得到int的隐式转换。如果你没有考虑到这一点