为什么选择/读取会导致独占(X)锁定?

时间:2012-10-03 11:01:34

标签: sql sql-server sql-server-2008 deadlock

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

这个问题的原因是为了巩固我对僵局的理解。我仍然有点困惑,为什么没有索引,select语句导致MS SQL中的独占(X)锁?

我认为,这纯粹是因为我不了解死锁图。从我可以看到,下图中的2个进程都在做选择..那么怎么能导致独占(X)锁?图表上是否还有某些内容?

这是没有额外索引的死锁图:

enter image description here

...这里是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>

2 个答案:

答案 0 :(得分:3)

它不会(没有锁定提示)

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

请注意logused="1580"如果语句是独立的SELECT

,也不会发生

答案 1 :(得分:2)

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