【问题标题】:SQL Server deadlock on the same objid同一 objid 上的 SQL Server 死锁
【发布时间】:2015-09-14 14:19:42
【问题描述】:

有时我们的应用程序会在一个特定的表上看到死锁。数据库是 16 处理器 SQL Server 2012(内部版本 7601:Service Pack 1),SQL 由休眠生成。从死锁图中,我看到一个事务中有一个删除 SQL,另一个事务中有一个更新 SQL。我从图中不明白的是,所有者资源和请求资源的 objid 是相同的。如果它已经拥有该记录上的锁,为什么事务会请求同一对象上的锁?我阅读了 Brad McGehee 的文章 https://www.simple-talk.com/sql/learn-sql-server/how-to-track-down-deadlocks-using-sql-server-2005-profiler/ 和其他 msdn 文档,但它们都解释了拥有资源和请求资源不同的情况。抱歉,这是我第一次在 stackoverflow 上发帖,如果我的帖子没有提供足够的信息,请告诉我。

    <deadlock-list>
     <deadlock victim="process8fc64dc38">
     <process-list>
       <process id="process8fc64dc38" taskpriority="0" logused="348" waitresource="KEY: 5:72057594042843136 (83d75ea09649)" waittime="3635" ownerId="64693878583" transactionname="implicit_transaction" lasttranstarted="2015-09-11T12:49:54.470" XDES="0x8e917f838" lockMode="U" schedulerid="16" kpid="1920" status="suspended" spid="98" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2015-09-11T12:49:54.480" lastbatchcompleted="2015-09-11T12:49:54.480" lastattention="1900-01-01T00:00:00.480" clientapp="Microsoft SQL Server JDBC Driver" hostname="TSC-APP" hostpid="0" loginname="atms" isolationlevel="read committed (2)" xactid="64693878583" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128058">
       <executionStack>
     <frame procname="adhoc" line="1" stmtstart="568" sqlhandle="0x020000000336ba1ffcbedac90f190fce2fde4a3bac3cc5e80000000000000000000000000000000000000000">
    update dms_priority_queue set priority=@P0, owner=@P1, active=@P2, start_date=@P3, position=@P4, end_date=@P5, action_type=@P6, audit_date=@P7, message=@P8, beacon=@P9, delay=@P10, submit_time=@P11, audit_user=@P12, priority_key=@P13, associated_type=@P14, associated=@P15, dow_repeat=@P16 where device_id=@P17 and entry_id=@P18     </frame>
    </executionStack>
    <inputbuf>
    (@P0 int,@P1 nvarchar(4000),@P2 bit,@P3 datetime2,@P4 int,@P5 datetime2,@P6 nvarchar(4000),@P7 datetime2,@P8 nvarchar(4000),@P9 bit,@P10 int,@P11 datetime2,@P12 nvarchar(4000),@P13 nvarchar(4000),@P14 nvarchar(4000),@P15 varchar(8000),@P16 nvarchar(4000),@P17 int,@P18 nvarchar(4000))update dms_priority_queue set priority=@P0, owner=@P1, active=@P2, start_date=@P3, position=@P4, end_date=@P5, action_type=@P6, audit_date=@P7, message=@P8, beacon=@P9, delay=@P10, submit_time=@P11, audit_user=@P12, priority_key=@P13, associated_type=@P14, associated=@P15, dow_repeat=@P16 where device_id=@P17 and entry_id=@P18                                                                                                                                                       </inputbuf>
       </process>
       <process id="process8fc04d498" taskpriority="0" logused="948" waitresource="KEY: 5:72057594042843136 (0c15a51ae59f)" waittime="3631" ownerId="64693878466" transactionname="implicit_transaction" lasttranstarted="2015-09-11T12:49:54.467" XDES="0x7ac1e03a8" lockMode="X" schedulerid="8" kpid="10364" status="suspended" spid="144" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2015-09-11T12:49:54.487" lastbatchcompleted="2015-09-11T12:49:54.487" lastattention="1900-01-01T00:00:00.487" clientapp="Microsoft SQL Server JDBC Driver" hostname="TSC-APP" hostpid="0" loginname="atms" isolationlevel="read committed (2)" xactid="64693878466" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128058">
        <executionStack>
     <frame procname="adhoc" line="1" stmtstart="56" sqlhandle="0x02000000bd9f3034c4569fe476061660252530233735d0640000000000000000000000000000000000000000">
delete from dms_priority_queue where device_id=@P0 and entry_id=@P1     </frame>
     <frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown     </frame>
    </executionStack>
    <inputbuf>
        (@P0 int,@P1 nvarchar(4000))delete from dms_priority_queue where device_id=@P0 and entry_id=@P1                    </inputbuf>
   </process>
  </process-list>
  <resource-list>
   <keylock hobtid="72057594042843136" dbid="5" objectname="nwatms2.dbo.dms_priority_queue" indexname="pk_dms_priority_queue" id="lock7b664d300" mode="X" associatedObjectId="72057594042843136">
    <owner-list>
     <owner id="process8fc04d498" mode="X"/>
    </owner-list>
    <waiter-list>
     <waiter id="process8fc64dc38" mode="U" requestType="wait"/>
    </waiter-list>
   </keylock>
   <keylock hobtid="72057594042843136" dbid="5" objectname="nwatms2.dbo.dms_priority_queue" indexname="pk_dms_priority_queue" id="lock3533d6280" mode="X" associatedObjectId="72057594042843136">
    <owner-list>
     <owner id="process8fc64dc38" mode="X"/>
    </owner-list>
    <waiter-list>
     <waiter id="process8fc04d498" mode="X" requestType="wait"/>
    </waiter-list>
   </keylock>
  </resource-list>
 </deadlock>

【问题讨论】:

    标签: sql-server hibernate database-deadlocks


    【解决方案1】:

    有问题的锁(键锁)会影响表内的范围,而不是整个表。 See MSDN on Lock Granularity and Hierarchies.

    在这种情况下,两个进程中的每一个都在 dms_priority_queue 内的单个范围上拥有一个排他锁 (mode=X),但正在等待同一个表内另一个范围上的锁。

    【讨论】:

    • 谢谢。我认为objid是recordid。我重新阅读了文档并意识到 objid 引用了该表。我阅读了您提到的链接,并意识到键锁可能是基于 where 条件的一系列值。现在需要弄清楚如何防止这种死锁。
    • 我刚刚看了一下表,上面两个 SQL 中的 where 条件都是表的主键。那么当一个delete sql根据主键删除一条记录时,为什么会锁定一个范围的值呢?
    • 注意事务计数。 deleteupdate 正在尝试获取它们需要执行的锁,但我相信在与 deleteupdate 相同的事务中执行的其他东西持有冲突的锁。跨度>
    • 非常感谢!我想我将打开详细的 SQL 日志记录并查看正在执行的其他 SQL 作为事务的一部分。我现在对死锁跟踪有了更好的理解!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多