0

我正在处理的 API 使用的数据库中发生了一些死锁。这仅在 API 进行负载测试时发生。在初步调查和研究中,一些进口指标似乎缺失,现已应用。这似乎解决了死锁问题。在应用索引之前,SQL 正在执行索引扫描。应用索引后,SQL 正在执行索引查找。

这个问题的原因是为了巩固我对死锁的理解。我仍然有点困惑,为什么没有索引选择语句会导致 MS SQL 中的排他(X)锁定?

我认为,这纯粹是因为我不了解死锁图。从我可以看到下图中的2个进程都在做选择..那怎么会导致排他(X)锁?图表上可能没有什么东西吗?

这是在没有额外索引的情况下发生的死锁图:

在此处输入图像描述

...这是XML(来自该图表:

<deadlock-list>
 <deadlock victim="process4c3708">
  <process-list>
   <process id="process4c3708" taskpriority="0" logused="1580" waitresource="KEY: 5:72057594038910976 (a94bedf44228)" waittime="99" ownerId="13602992" transactionname="user_transaction" lasttranstarted="2012-10-03T10:59:34.830" XDES="0x8cbf23b0" lockMode="S" schedulerid="3" kpid="7588" status="suspended" spid="67" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2012-10-03T10:59:35.027" lastbatchcompleted="2012-10-03T10:59:35.020" clientapp=".Net SqlClient Data Provider" hostname="DEVMACHINE" hostpid="8440" loginname="user" isolationlevel="read committed (2)" xactid="13602992" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="adhoc" line="1" stmtstart="170" stmtend="728" sqlhandle="0x02000000b3a88339052734f326b9dbb95deb1d46fe4d192d">
select basefolder1_.Identifier as col_0_0_ from TradeInfo tradepr0_ inner join BaseFolder basefolder1_ on tradepr0_.BaseFolderId=basefolder1_.Id where basefolder1_.BoxId=@p0 and tradepr0_.PersonId=@p1 and tradepr0_.CurrentTrade=1 and tradepr0_.IsActive=1;     </frame>
     <frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">
unknown     </frame>
    </executionStack>
    <inputbuf>
(@p0 uniqueidentifier,@p1 uniqueidentifier,@p2 uniqueidentifier,@p3 uniqueidentifier)select basefolder1_.Identifier as col_0_0_ from TradeInfo tradepr0_ inner join BaseFolder basefolder1_ on tradepr0_.BaseFolderId=basefolder1_.Id where basefolder1_.BoxId=@p0 and tradepr0_.PersonId=@p1 and tradepr0_.CurrentTrade=1 and tradepr0_.IsActive=1;
select basefolder1_.Identifier as col_0_0_ from TradeInfo tradepr0_ inner join BaseFolder basefolder1_ on tradepr0_.BaseFolderId=basefolder1_.Id where basefolder1_.BoxId=@p2 and tradepr0_.PersonId=@p3 and tradepr0_.SuspendedTrade=1 and tradepr0_.IsSuspended=1;
    </inputbuf>
   </process>
   <process id="process5dd4c8" taskpriority="0" logused="1580" waitresource="KEY: 5:72057594038910976 (b34811986aff)" waittime="301" ownerId="13602927" transactionname="user_transaction" lasttranstarted="2012-10-03T10:59:34.660" XDES="0xafb9f950" lockMode="S" schedulerid="4" kpid="2076" status="suspended" spid="61" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2012-10-03T10:59:35.020" lastbatchcompleted="2012-10-03T10:59:35.020" clientapp=".Net SqlClient Data Provider" hostname="DEVMACHINE" hostpid="8440" loginname="user" isolationlevel="read committed (2)" xactid="13602927" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="adhoc" line="1" stmtstart="170" stmtend="728" sqlhandle="0x02000000b3a88339052734f326b9dbb95deb1d46fe4d192d">
select basefolder1_.Identifier as col_0_0_ from TradeInfo tradepr0_ inner join BaseFolder basefolder1_ on tradepr0_.BaseFolderId=basefolder1_.Id where basefolder1_.BoxId=@p0 and tradepr0_.PersonId=@p1 and tradepr0_.CurrentTrade=1 and tradepr0_.IsActive=1;     </frame>
     <frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">
unknown     </frame>
    </executionStack>
    <inputbuf>
(@p0 uniqueidentifier,@p1 uniqueidentifier,@p2 uniqueidentifier,@p3 uniqueidentifier)select basefolder1_.Identifier as col_0_0_ from TradeInfo tradepr0_ inner join BaseFolder basefolder1_ on tradepr0_.BaseFolderId=basefolder1_.Id where basefolder1_.BoxId=@p0 and tradepr0_.PersonId=@p1 and tradepr0_.CurrentTrade=1 and tradepr0_.IsActive=1;
select basefolder1_.Identifier as col_0_0_ from TradeInfo tradepr0_ inner join BaseFolder basefolder1_ on tradepr0_.BaseFolderId=basefolder1_.Id where basefolder1_.BoxId=@p2 and tradepr0_.PersonId=@p3 and tradepr0_.SuspendedTrade=1 and tradepr0_.IsSuspended=1;
    </inputbuf>
   </process>
  </process-list>
  <resource-list>
   <keylock hobtid="72057594038910976" dbid="5" objectname="ccp.dbo.TradeInfo" indexname="PK__Activity__3214EC07060DEAE8" id="lock8011dd00" mode="X" associatedObjectId="72057594038910976">
    <owner-list>
     <owner id="process5dd4c8" mode="X"/>
    </owner-list>
    <waiter-list>
     <waiter id="process4c3708" mode="S" requestType="wait"/>
    </waiter-list>
   </keylock>
   <keylock hobtid="72057594038910976" dbid="5" objectname="ccp.dbo.TradeInfo" indexname="PK__Activity__3214EC07060DEAE8" id="lock8a864e00" mode="X" associatedObjectId="72057594038910976">
    <owner-list>
     <owner id="process4c3708" mode="X"/>
    </owner-list>
    <waiter-list>
     <waiter id="process5dd4c8" mode="S" requestType="wait"/>
    </waiter-list>
   </keylock>
  </resource-list>
 </deadlock>
</deadlock-list>
4

2 回答 2

3

它不会(没有锁定提示)

推测在同一个事务中存在前面的语句(死锁图中未显示)实际获得了X锁。

请注意,logused="1580"如果语句是独立的,这也不会发生SELECT

于 2012-10-03T11:16:27.837 回答
2

死锁 XML 中的任何 SELECT 都没有实际获得 X 锁。死锁涉及的两个资源目前在X模式下拥有,在S模式下请求。这意味着每个事务先前已锁定资源(在本例中为键),也许它运行了更新/插入该行的 DML 语句。SELECT 语句只想读取行,因此它们请求 S 模式。

于 2012-10-03T11:20:27.247 回答