为什么这个SQL Server查询死锁?(Why is this SQL Server query

2019-09-26 10:45发布

谁能告诉我,为什么下面的SQL Server查询被锁死,什么是解决修复它?

<deadlock-list>
  <deadlock victim="process88b5b8">
    <process-list>
      <process id="process88b5b8" taskpriority="0" logused="76132" waitresource="RID: 32:1:151867:174" waittime="5093" ownerId="65554098" transactionguid="0xedf3314c05f1124cbe8d480cd092e03e" transactionname="DTCXact" lasttranstarted="2011-09-02T19:00:29.690" XDES="0x1029e040" lockMode="S" schedulerid="1" kpid="5108" status="suspended" spid="118" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2011-09-02T19:00:31.317" lastbatchcompleted="2011-09-02T19:00:31.300" hostname="MELWFPL382S" hostpid="0" loginname="MM4" isolationlevel="repeatable read (3)" xactid="65554098" currentdb="32" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
        <executionStack>
          <frame procname="adhoc" line="1" stmtstart="78" sqlhandle="0x020000004b4b0a0d63e1040095143cbaa0174ffc3e076067"> delete from PARTIES where PARTYEXTERNALREF=@P0 and ISCOUNTERPARTY='N' and PARTYID in (select PARTYID from NAB_PARTY_EXTEND (nolock) where PARTYTYPE=@P1)     </frame>
          <frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">unknown     </frame>
        </executionStack>
        <inputbuf>(@P0 nvarchar(4000),@P1 nvarchar(4000))delete from PARTIES where PARTYEXTERNALREF=@P0 and ISCOUNTERPARTY='N' and PARTYID in (select PARTYID from NAB_PARTY_EXTEND (nolock) where PARTYTYPE=@P1)                    </inputbuf>
      </process>
      <process id="process9196a8" taskpriority="0" logused="132612" waitresource="RID: 32:1:140302:31" waittime="5046" ownerId="65554657" transactionguid="0x7313c78fecc8914dac3ed821cd7c21fe" transactionname="DTCXact" lasttranstarted="2011-09-02T19:00:34.100" XDES="0x12835778" lockMode="S" schedulerid="2" kpid="3692" status="suspended" spid="94" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2011-09-02T19:00:35.690" lastbatchcompleted="2011-09-02T19:00:35.687" hostname="MELWFPL382S" hostpid="0" loginname="MM4" isolationlevel="repeatable read (3)" xactid="65554657" currentdb="32" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
        <executionStack>
          <frame procname="adhoc" line="1" stmtstart="78" sqlhandle="0x020000004b4b0a0d63e1040095143cbaa0174ffc3e076067">delete from PARTIES where PARTYEXTERNALREF=@P0 and ISCOUNTERPARTY='N' and PARTYID in (select PARTYID from NAB_PARTY_EXTEND (nolock) where PARTYTYPE=@P1)     </frame>
          <frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">unknown     </frame>
        </executionStack>
        <inputbuf>(@P0 nvarchar(4000),@P1 nvarchar(4000))delete from PARTIES where PARTYEXTERNALREF=@P0 and ISCOUNTERPARTY='N' and PARTYID in (select PARTYID from NAB_PARTY_EXTEND (nolock) where PARTYTYPE=@P1)                    </inputbuf>
      </process>
    </process-list>
    <resource-list>
      <ridlock fileid="1" pageid="140302" dbid="32" objectname="mm4_melwfpl382s.dbo.COUNTERPARTYSSI" id="lock170fa500" mode="X" associatedObjectId="72057595803336704">
        <owner-list>
          <owner id="process88b5b8" mode="X" />
        </owner-list>
        <waiter-list>
          <waiter id="process9196a8" mode="S" requestType="wait" />
        </waiter-list>
      </ridlock>
      <ridlock fileid="1" pageid="151867" dbid="32" objectname="mm4_melwfpl382s.dbo.COUNTERPARTYSSI" id="lock20e65d80" mode="X" associatedObjectId="72057595803336704">
        <owner-list>
          <owner id="process9196a8" mode="X" />
        </owner-list>
        <waiter-list>
          <waiter id="process88b5b8" mode="S" requestType="wait" />
        </waiter-list>
      </ridlock>
    </resource-list>
  </deadlock>
</deadlock-list>

我不明白的是两种工艺都可以有相同的对象的排它锁。

还有,对当事人表的索引(IDX_NC_PARTIES_PARTYEXTERNALREF_ISCOUNTERPARTY_PARTYID)和数据库设置为读提交快照。

谢谢,

韦恩。

Answer 1:

  • 过程9196a8有151867页槽174在X模式,并希望页140302槽31在S模式
  • 过程88b5b8具有140302页槽31在X模式,并希望页151867槽174在S模式
  • 两个删除下运行isolationlevel="repeatable read (3)"

所以,僵局出现在桌子上的一堆基地(RID锁代替钥匙锁意味着堆而不是B树)。 高隔离级别(可能是由DTC引起的,从XACT名称判断)使得RCSI设定无关。

什么类型的列PARTYEXTERNALREF和PARTYTYPE? 传递的参数是NVARCHAR(即Unicode的),并且如果列是VARCHAR(即ASCII)然后由于规则的数据类型的优先级将不使用的NC索引。 由于涉及,在使用高隔离级别一起表扫描的,陷入僵局是几乎是不可避免的。

该解决方案将是使用VARCHAR类型参数@ P0和P1 @所以NC指数将被利用来避免表扫描。

如果参数VARCHAR类型的已经,您可以从一个NC上寻求执行计划确认被使用时,我的第一个问题是还有什么是做交易,比delete语句其他?

顺便说一句,你只给NC索引的名字,但我认为是(PARTYEXTERNALREF, ISCOUNTERPARTY, PARTYID)

更新

由于您的评论说, NVARCHAR那么表扫描的假设也许是错误的。 有三种更多的可能性,以使需要调查死锁:

  • 由事务运行的任何其他语句之前删除(这是最有可能的)
  • 在各行由死锁涉及两条DELETE语句选择任何重叠
  • 哈希冲突

对于前两种假设只有你现在就可以做任何事情(调查,如果他们是正确的)。 最后一个我可以告诉你如何进行验证,但不是小事。 这是不可能发生的,有点难以证实,但它是可能的。 既然你知道的死锁情况(附XML),使用它作为调查的基础:

  • 恢复点即时数据库的副本在2011-09-02T19与站:00:29.690
  • 运行DBCC TRACEON(3604,-1)
  • 使用DBCC PAGE (<restored db id>, 1, 151867, 3)在槽174检查值
  • 使用DBCC PAGE(i,1,140302,3)`在槽31检查值
  • 运行SELECT %%lockres%% FROM PARTIES WHERE PARTYEXTERNALREF = ... AND ISCOUNTERPARTY='N' and PARTYID=...和传递中的值读以上
  • compars所得到的锁哈希值,如果他们匹配,那么你有一个哈希冲突,这导致了僵局。


文章来源: Why is this SQL Server query deadlocking?