SQL 服务器在同一个 objid 上死锁

SQL Server deadlock on the same objid

我们的应用程序有时会在某个特定 table 上发生死锁。数据库是 16 个处理器 SQL Server 2012(Build 7601:Service Pack 1),SQLs 由休眠生成。从死锁图中,我看到一个事务中有一个删除 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 文档,但它们都解释了拥有资源和请求资源不同的情况。抱歉,这是我第一次在 Whosebug 上 posting,所以如果我的 post 没有提供足够的信息,请告诉我。

    <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>

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

在这种情况下,两个进程中的每一个都在 dms_priority_queue 内的单个范围内拥有独占锁 (mode=X),但正在等待同一 table.