Art*_*dod 4 sql-server indexing deadlock sql-server-profiler
我试图使用SQL Server Profiler确定死锁的原因.这是死锁图:
这两个语句都是插入,后面跟着select scope_identity();
实际上有两个并发进程,它们在一个循环中重复执行insert-select_identity.
我期望插入对聚簇索引进行独占锁定,并且select获取非聚集索引的共享锁,然后它们等待彼此释放它们各自的indeces.
我看到的是两个进程都在等待释放相同的资源 - 聚集索引.怎么会这样?特定的追索权应属于一个过程或另一个过程.我在这里想念什么?感谢所有提前.
编辑:是的,隔离级别是Serializible.PS:可能,我对非聚集索引的共享锁的假设是错误的,只要我的select不包含where语句
Edit2:这是xml的一部分:
<resource-list>
<keylock hobtid="72057594148028416" dbid="29" objectname="<confidential>" indexname="PK_WP_Inbound_StockTransactionLine" id="lock9641700" mode="RangeS-S" associatedObjectId="72057594148028416">
<owner-list>
<owner id="process8e09288" mode="RangeS-S"/>
</owner-list>
<waiter-list>
<waiter id="process991ce08" mode="RangeI-N" requestType="convert"/>
</waiter-list>
</keylock>
<keylock hobtid="72057594148028416" dbid="29" objectname="<confidential>" indexname="PK_WP_Inbound_StockTransactionLine" id="lock9641700" mode="RangeS-S" associatedObjectId="72057594148028416">
<owner-list>
<owner id="process991ce08" mode="RangeS-S"/>
</owner-list>
<waiter-list>
<waiter id="process8e09288" mode="RangeI-N" requestType="convert"/>
</waiter-list>
</keylock>
</resource-list>
Run Code Online (Sandbox Code Playgroud)
根据这个,我认为它是由SERIALIZABLE隔离引起的范围扫描(谷歌搜索).但是,我仍然不明白这是怎么发生的,建议的补救措施是什么.
考虑从访问相同记录的两个并行事务(T1和T2)调用以下代码.
Read LastRow
Insert AtLastRow
Run Code Online (Sandbox Code Playgroud)
让我们说上下文切换发生在Read.所以操作顺序是
T1 Read LastRow
T2 Read LastRow
T2 Insert AtLastRow // This will wait for T1 to finish.
T1 Insert AtLastRow // This will wait for T2 to finish. Hence deadlock!
Run Code Online (Sandbox Code Playgroud)
以上阅读将Range S-S锁定.最后插入也需要Range I-N与Range S-S其他事务持有的现有锁不兼容.因此它等待.
可以有多种方法来解决此问题.
如果您有任何疑问,请告诉我.