【问题标题】:How is it I am getting deadlocks when inserting into two different tables?插入两个不同的表时,我怎么会遇到死锁?
【发布时间】:2016-07-21 13:56:27
【问题描述】:

这是一个 DynamicsAX 应用程序,我现在经常看到以下死锁。如果我正确理解输出,则插入表 CUSTTRANS 被插入表 CUSTSETTLEMENT 阻止。我检查了两个表,都没有触发器,所以我不清楚一个是如何导致另一个死锁的? CUSTTRANS 表确实启用了更改跟踪,但没有启用 CUSTSETTLEMENT。

<event name="xml_deadlock_report" package="sqlserver" timestamp="2016-07-19T23:43:24.567Z">
  <data name="xml_report">
    <value>
      <deadlock>
        <victim-list>
          <victimProcess id="processb7c273c38" />
        </victim-list>
        <process-list>
          <process id="processb7c273c38" taskpriority="0" logused="9000" waitresource="KEY: 5:72057881131876352 (9006753b740b)" waittime="37640" ownerId="221473485" transactionname="user_transaction" lasttranstarted="2016-07-19T16:42:46.317" XDES="0xb7caa3078" lockMode="RangeS-S" schedulerid="6" kpid="1940" status="suspended" spid="122" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2016-07-19T16:42:46.760" lastbatchcompleted="2016-07-19T16:42:46.737" lastattention="2016-07-19T13:12:49.450" clientapp="Microsoft Dynamics AX" hostname="DW22" hostpid="3076" loginname="xxx" isolationlevel="read committed (2)" xactid="221473485" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
            <executionStack>
              <frame procname="adhoc" line="1" stmtstart="2872" sqlhandle="0x020000005b952a20985c14b98773bd4fb5fd593a90918fd00000000000000000000000000000000000000000">
INSERT INTO CUSTTRANS (ACCOUNTNUM,TRANSDATE,VOUCHER,...,REPORTINGEXCHADJUSTMENTRE    </frame>
              <frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">
unknown    </frame>
            </executionStack>
            <inputbuf>(@P1 nvarchar(21),@P2 datetime2...@P67 numeric(32,4)</inputbuf>
          </process>
          <process id="process1d15b0cf8" taskpriority="0" logused="3009456" waitresource="KEY: 5:72057881131876352 (e7873f5a29fe)" waittime="3566" ownerId="221391316" transactionname="user_transaction" lasttranstarted="2016-07-19T16:38:55.940" XDES="0x21b5e31d8" lockMode="RangeI-N" schedulerid="3" kpid="6320" status="suspended" spid="62" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2016-07-19T16:43:20.997" lastbatchcompleted="2016-07-19T16:43:20.993" lastattention="2016-07-19T15:31:56.060" clientapp="Microsoft Dynamics AX" hostname="DW22" hostpid="3076" loginname="xxxxx" isolationlevel="read committed (2)" xactid="221391316" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
            <executionStack>
              <frame procname="adhoc" line="1" stmtstart="1262" sqlhandle="0x020000000af3f41be10a624051e59a5f47e43bd38431bc5f0000000000000000000000000000000000000000">
INSERT INTO CUSTSETTLEMENT (TRANSRECID,TRANSDATE,OFFSETTRANSVOUCHER,...,RECID) VALUES (@P1,@P2,@P3...,@P40)    </frame>
            </executionStack>
            <inputbuf>
(@P1 bigint,@P2 datetime2,@P3 nvarchar(21)...,@P40 bigint)INSERT INTO CUSTSETTLEMENT (TRANSRECID,TRANSDATE,OFFSETTRANSVOUCHER,...</inputbuf>
          </process>
        </process-list>
        <resource-list>
          <keylock hobtid="72057881131876352" dbid="5" objectname="MicrosoftDynamicsAX.dbo.CUSTSETTLEMENT" indexname="I_075TRANSINDEX" id="lock6d97d4380" mode="RangeX-X" associatedObjectId="72057881131876352">
            <owner-list>
              <owner id="process1d15b0cf8" mode="RangeX-X" />
            </owner-list>
            <waiter-list>
              <waiter id="processb7c273c38" mode="RangeS-S" requestType="wait" />
            </waiter-list>
          </keylock>
          <keylock hobtid="72057881131876352" dbid="5" objectname="MicrosoftDynamicsAX.dbo.CUSTSETTLEMENT" indexname="I_075TRANSINDEX" id="lock7102fa100" mode="RangeS-S" associatedObjectId="72057881131876352">
            <owner-list>
              <owner id="processb7c273c38" mode="RangeS-S" />
            </owner-list>
            <waiter-list>
              <waiter id="process1d15b0cf8" mode="RangeI-N" requestType="wait" />
            </waiter-list>
          </keylock>
        </resource-list>
      </deadlock>
    </value>
  </data>
  <action name="collect_system_time" package="package0">
    <value>2016-07-19T23:43:24.567Z</value>
  </action>
  <action name="client_hostname" package="sqlserver">
    <value />
  </action>
  <action name="context_info" package="sqlserver">
    <value />
  </action>
  <action name="attach_activity_id_xfer" package="package0">
    <value>CE2E9A01-A31C-464F-9288-AC45C7927760-574</value>
  </action>
  <action name="attach_activity_id" package="package0">
    <value>634B86DC-58AB-4870-9170-5575B9C12D0A-1</value>
  </action>
</event>

【问题讨论】:

    标签: sql-server sql-server-2012 database-deadlocks


    【解决方案1】:

    第一个想法(不看图表)是 - 它们之间有一个 FK。我认为它确实存在。

    CUSTTRANS 可能是子表,CUSTSETTLEMENT 是父表。插入CUSTTRANS 时,服务器检查父表CUSTSETTLEMENT 中是否有适当的键(从CUSTTRANS 行引用)。并在该列的父表/索引中的键上放置共享锁。

    第二个事务是在父表CUSTSETTLEMENT 中插入值并更新I_075TRANSINDEX 索引。我假设您在一个事务中在该表中插入许多值,因此在某些时候您有一些范围已经被排他锁锁定并试图锁定更多。但是那里 - 在另一个范围内 - 已经从第一次插入到 CUSTTRANS 中放置了一个共享锁,它正在检查父表中是否存在相应的行以确保 FK 完整性。

    是的,FK 有一些与之相关的非常常见的死锁场景。另一种是:将许多(足以打开升级)插入子表并从父表中删除许多 - 两者都会尝试锁定整个相关表并且会失败。

    解决方案(一如既往):

    • 提高隔离级别,使这些查询按顺序执行
    • 禁用服务器的完整性控制机制并在需要时自行执行(删除或禁用 FK - 是的,这是困难情况下的常见解决方案)
    • 缩短事务和锁定范围 - 一次处理更少的行数
    • try-catch and retry处理死锁

    【讨论】:

    • 这是一个很好的观察结果(我不知道 FK 会导致这样的阻塞),但不幸的是这不是问题,这些表中的任何一个都有零个 FK。是否有任何其他信息可以收集来更清楚地说明这一点?
    • @Greg,有什么触发器吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-30
    • 2020-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-17
    相关资源
    最近更新 更多