首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >SQLServer死锁

SQLServer死锁
EN

Stack Overflow用户
提问于 2009-05-08 08:37:28
回答 7查看 7.4K关注 0票数 6

我有一个java应用程序,它在数据库上执行多个并发CRUD操作。我正在添加对SQLServer的支持,但在并发删除期间遇到死锁问题。经过一些调查,这个问题可能是由于特定表上的锁升级造成的。

为了解决这个问题,我决定使用UPDLOCK提示将表上的所有读操作都设置为"for update“,这样就可以避免死锁。然而,我仍然看到了问题。我已经在SQLServer中启用了跟踪,并且在SQLServer日志中发现了以下死锁跟踪:

遇到死锁....打印死锁信息等待图

Node:1 KEY: 5:72057594042384384 (54048e7b3828) CleanCnt:3模式:x标志: 0x0授权列表1:所有者:0x03D08C40模式:x Flg:0x0引用:0生命周期:02000000 SPID:62 ECID:0 XactLockInfo: 0x04834274 SPID: 62 ECID:0语句类型:删除行号:1输入Buf:语言事件:(@P0 nvarchar(4000))delete from part_data where part_id = @P0请求者:资源类型:锁定所有者类型:‘OR’‘Xdes:0x04B511C8模式:u SPID:60 BatchID:0 ECID: 0TaskProxy:(0x058BE378)值:0x3d08500成本:(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语句类型:删除行号:1输入Buf:语言事件:(@P0 nvarchar(4000))从part_data中删除where part_id = @P0请求者:重类型:锁定所有者类型:‘OR’xx04834250模式:u SPID:62 BatchID:0 ECID: 0 TaskProxy:(0x047BA378)值:0x3d089e0成本:(0/4588)

受害者资源所有者:响应类型:锁定所有者类型:‘或’‘Xdes:0x04B511C8模式:U SPID:60批次60:0 ECID:0 TaskProxy:(0x058BE378)值:0x3d08500成本:(0/1296)

我读过的SQLServer文档说,在给定的时间内,只有一个客户端可以拥有表上的(U)锁,所以我想知道为什么我会看到跟踪中显示的情况。

该跟踪中引用的数据库对象是外键上的索引。如果任何有解决这类问题的经验的人都能提供建议,这将是一个很大的帮助。

谢谢,布拉德。

根据请求编辑添加的死锁图xml:

代码语言:javascript
运行
复制
<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>
EN

回答 7

Stack Overflow用户

发布于 2009-06-11 12:48:41

欢迎来到可怕的世界。

上一次我遇到这样的情况是因为update或delete无法找到一个好的索引来帮助它隔离它所影响的行。这导致了不稳定的锁升级,因为它使用非覆盖索引来修改定位记录。

因此,如果您可以隔离一些查询,请检查它们的sql,看看是否不能尝试提供一些覆盖索引。

票数 4
EN

Stack Overflow用户

发布于 2009-05-08 13:37:11

SQLServer上的死锁几乎总是源于这样一个事实:单个线程试图使用两个连接并因此使用两个事务进行写和读。如果你想让它工作,使用一个连接在一个线程中完成所有操作,并绝对确保你确实重用了这个连接。这可能是由于您的应用程序中的分层,您在事务期间意外地使用了不同的连接来读取,这使得读取等待其他代码(使用另一个连接)完成,这永远不会发生,因为读取永远不会完成。

示例(伪步骤)

开始交易

  • 将数据(例如INSERT、UPDATE)写入表Foo
  • 使用不同的连接死锁从Foo读取一些数据(这会触发表扫描),因为读取永远不会完成,因此事务永远不会提交
票数 2
EN

Stack Overflow用户

发布于 2009-11-06 07:44:13

首先不要使用提示,通常SQL Server最好还是让它自己来处理。

其次,确认你没有真正的死锁(但它发生的频率要低得多,因为死锁的出现可能会暗示这种情况)。

第三,按照一些人的建议,检查你是否有一些缓慢的查询,并调整它。

在我的经验中,每次客户报告死锁情况时,都会发生这种情况,因为有一个运行缓慢的查询升级,并且从来没有真正的死锁,调优查询或添加特定的索引解决了这个问题。

我不知道您说的是哪个版本的SQL Server,但是下面的每个版本都比前一个版本有更好的死锁管理,SQL Server2000在这个主题中尤其令人讨厌。

问候

马西莫

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/838824

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档