【发布时间】:2009-05-08 08:37:27
【问题描述】:
我有一个 Java 应用程序,它在数据库上执行多个并发 CRUD 操作。我正在添加对 SQLServer 的支持,但在并发删除期间遇到死锁问题。经过一些调查,问题似乎是由于特定表上的锁升级。
为了修复它,我决定使用 UPDLOCK 提示对有问题的表进行“更新”的所有读取,这样可以避免死锁。但是,我仍然看到了问题。我在 SQLServer 中启用了跟踪,并在 SQLServer 日志中发现了以下死锁跟踪:
遇到死锁 .... 打印死锁信息 等待图
节点:1 密钥:5:72057594042384384(54048e7b3828)CleanCnt:3 模式:X 标志:0x0 拨款清单 1: 所有者:0x03D08C40 模式:X Flg:0x0 参考:0 寿命:02000000 SPID:62 ECID:0 XactLockInfo:0x04834274 SPID:62 ECID:0 语句类型:DELETE 行号:1 输入 Buf:语言事件:(@P0 nvarchar(4000))delete from part_data where part_id = @P0 被要求: ResType:LockOwner Stype:'OR'Xdes:0x04B511C8 Mode:U SPID:60 BatchID:0 ECID:0 TaskProxy:(0x058BE378) Value:0x3d08500 Cost:(0/1296)
节点:2
KEY: 5:72057594042384384 (f903d6d6e0ac) CleanCnt:2 模式:X 标志: 0x0 赠款清单 0: 所有者:0x03D088A0 模式:X Flg:0x0 参考:0 寿命:02000000 SPID:60 ECID:0 XactLockInfo:0x04B511EC SPID:60 ECID:0 语句类型:DELETE 行号:1 输入 Buf:语言事件:(@P0 nvarchar(4000))delete from part_data where part_id = @P0 被要求: ResType:LockOwner Stype:'OR'Xdes:0x04834250 Mode:U SPID:62 BatchID:0 ECID:0 TaskProxy:(0x047BA378) Value:0x3d089e0 Cost:(0/4588)
受害者资源所有者: ResType:LockOwner Stype:'OR'Xdes:0x04B511C8 Mode:U SPID:60 BatchID:0 ECID:0 TaskProxy:(0x058BE378) Value:0x3d08500 Cost:(0/1296)
SQLServer 分析器将此显示为两个客户端持有更新 (U) 锁并尝试升级为独占 (X) 锁。我读过的 SQLServer 文档说,在给定时间,只有一个客户端可以在表上拥有 (U) 锁,所以我想知道为什么我会看到跟踪中显示的情况。
该跟踪中引用的数据库对象是外键上的索引。如果有解决此类问题经验的人可以提供建议,那将是一个很大的帮助。
谢谢, 布拉德。
EDIT 按要求添加了死锁图 xml:
<deadlock-list>
<deadlock victim="process989018">
<process-list>
<process id="process6aa7a8" taskpriority="0" logused="4844" waitresource="KEY: 5:72057594042384384 (5504bdfb7529)" waittime="9859" ownerId="613553" transactionname="implicit_transaction" lasttranstarted="2009-05-08T11:52:39.137" XDES="0x5fcbc30" lockMode="U" schedulerid="1" kpid="3516" status="suspended" spid="59" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2009-05-08T11:52:39.183" lastbatchcompleted="2009-05-08T11:52:39.183" clientapp="jTDS" hostname="LOIRE" hostpid="123" loginname="sa" isolationlevel="read committed (2)" xactid="613553" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128058">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="40" sqlhandle="0x0200000007c76c39efdd8317c6fa7b611b4fd958f05cfcf4">
delete from part_data where part_id = @P0 </frame>
</executionStack>
<inputbuf>(@P0 nvarchar(4000))delete from part_data where part_id = @P0</inputbuf>
</process>
<process id="process989018" taskpriority="0" logused="1528" waitresource="KEY: 5:72057594042384384 (5e0405cb0377)" waittime="1250" ownerId="613558" transactionname="implicit_transaction" lasttranstarted="2009-05-08T11:52:39.183" XDES="0x48318f0" lockMode="U" schedulerid="2" kpid="2692" status="suspended" spid="60" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2009-05-08T11:52:39.183" lastbatchcompleted="2009-05-08T11:52:39.183" clientapp="jTDS" hostname="LOIRE" hostpid="123" loginname="sa" isolationlevel="read committed (2)" xactid="613558" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128058">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="40" sqlhandle="0x0200000007c76c39efdd8317c6fa7b611b4fd958f05cfcf4">
delete from part_data where part_id = @P0 </frame>
</executionStack>
<inputbuf>(@P0 nvarchar(4000))delete from part_data where part_id = @P0</inputbuf>
</process>
</process-list>
<resource-list>
<keylock hobtid="72057594042384384" dbid="5" objectname="MESSAGESTOREDB61.dbo.part_data" indexname="idx_part_data_part_id" id="lock3cab740" mode="X" associatedObjectId="72057594042384384">
<owner-list>
<owner id="process6aa7a8" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process989018" mode="U" requestType="wait"/>
</waiter-list>
</keylock>
<keylock hobtid="72057594042384384" dbid="5" objectname="MESSAGESTOREDB61.dbo.part_data" indexname="idx_part_data_part_id" id="lock3cad340" mode="X" associatedObjectId="72057594042384384">
<owner-list>
<owner id="process989018" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process6aa7a8" mode="U" requestType="wait"/>
</waiter-list>
</keylock>
</resource-list>
</deadlock>
</deadlock-list>
【问题讨论】:
-
你在某处有级联删除吗?
-
嗨斯特凡。不,我没有任何级联删除约束。
-
的网页屏幕格式没关系,复制/粘贴到本地的.XML文件并打开它会很好看 -
您是否在使用围绕此删除的事务?如果是这样,交易中是否还有其他事情发生?
-
是的,声明了一个事务,以确保在出现错误时删除整个对象图或保持原样。事务中没有其他数据库操作,一些读取在事务启动之前完成,但内部没有。
标签: sql-server spring jdbc transactions deadlock