sql-server - 如何解释 t-sql 死锁跟踪

标签 sql-server database tsql deadlock ssms

我试图通过查看 t-sql 跟踪来解决死锁问题,但我很难理解这些信息。我在这里总结了信息,然后在帖子末尾提供了完整的死锁跟踪:

第一个锁在名为 dbo.RetailVoucher 的表上
第二个锁在名为 ooc.PlannedUniversalVoucher 的表上

第一个存储过程读取下表:
dbo.RetailVoucher、ooc.PlannedOrderItem 和 ooc.PlannedOrder。

第二个存储过程读取下表:
ooc.PlannedBatch & ooc.PlannedUniversalVoucher

现在,对于相互等待的过程,我认为它们必须在某个时候都读取同一张表。我显然不明白如何解释痕迹。我是否需要在其他过程中追查 dbo.RetailerVoucher 和 ooc.PlannedUniversalVoucher 上的锁源?

谢谢。

这是完整的轨迹:

<deadlock-list>
 <deadlock victim="process894748">
  <process-list>
   <process id="process894748" taskpriority="0" logused="3064" waitresource="KEY: 8:72057594084655104 (845afc30a382)" waittime="944" ownerId="12987790066" transactionname="user_transaction" lasttranstarted="2014-04-10T19:07:02.250" XDES="0x803d53c0" lockMode="S" schedulerid="3" kpid="14356" status="suspended" spid="67" sbid="0" ecid="0" priority="0" trancount="3" lastbatchstarted="2014-04-10T19:07:02.287" lastbatchcompleted="2014-04-10T19:07:02.287" clientapp=".Net SqlClient Data Provider" hostname="ID13115" hostpid="4872" loginname="UVUser" isolationlevel="read committed (2)" xactid="12987790066" currentdb="8" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056">
    <executionStack>
     <frame procname="UVSystem.ooc.PlannedPacketPreserveEVouchers" line="144" stmtstart="12286" stmtend="13618" sqlhandle="0x0300080039a18c7fa2ed9800dda200000100000000000000">
update dbo.RetailVoucher
            set QuantityInStock -= rvsum.QuantitySum
            from dbo.RetailVoucher urv
            join (
                select oib.id, SUM(oib.Quantity) as QuantitySum
                from (
                    select coalesce(rv.RelatedVoucherId, rv.Id) id, oi.Quantity
                    from 
                        ooc.PlannedOrderItem oi 
                        join ooc.PlannedOrder po on oi.PlannedOrderId = po.Id
                        join RetailVoucher rv on oi.RetailVoucherId = rv.Id
                    where po.PlannedPacketId = @PlannedPacketId
                        and oi.PartnerId is null
                        and oi.OnDmenadServiceId is null
                        and rv.VoucherTypeId = 1
                ) oib
                group by oib.Id
            ) rvsum
            on urv.Id = rvsum.id;

         </frame>
    </executionStack>
    <inputbuf>
Proc [Database Id = 8 Object Id = 2139922745]    </inputbuf>
   </process>
   <process id="processd0db8088" taskpriority="0" logused="10716" waitresource="PAGE: 8:1:778990" waittime="1078" ownerId="12987783115" transactionname="user_transaction" lasttranstarted="2014-04-10T19:07:01.473" XDES="0x144975950" lockMode="S" schedulerid="7" kpid="11172" status="suspended" spid="61" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2014-04-10T19:07:01.473" lastbatchcompleted="2014-04-10T19:07:01.473" clientapp=".Net SqlClient Data Provider" hostname="ID13115" hostpid="12168" loginname="UVUser" isolationlevel="read committed (2)" xactid="12987783115" currentdb="8" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056">
    <executionStack>
     <frame procname="UVSystem.ooc.OfflineOrdersImportPacket" line="294" stmtstart="23548" stmtend="24026" sqlhandle="0x030008006d6796551b829700dda200000100000000000000">
update ooc.PlannedBatch 
    set 
        IsCompleted = @True
    from ooc.PlannedBatch pb
        join ooc.PlannedUniversalVoucher puv on puv.PlannedBatchId = pb.Id
        left outer join @DuplicatedVouchers dv on dv.Id = puv.Id
    where dv.Id is null;     </frame>
    </executionStack>
    <inputbuf>
Proc [Database Id = 8 Object Id = 1435920237]    </inputbuf>
   </process>
  </process-list>
  <resource-list>
   <keylock hobtid="72057594084655104" dbid="8" objectname="UVSystem.dbo.RetailVoucher" indexname="PK_RetailVoucher" id="lock10ccbd180" mode="X" associatedObjectId="72057594084655104">
    <owner-list>
     <owner id="processd0db8088" mode="X"/>
    </owner-list>
    <waiter-list>
     <waiter id="process894748" mode="S" requestType="wait"/>
    </waiter-list>
   </keylock>
   <pagelock fileid="1" pageid="778990" dbid="8" objectname="UVSystem.ooc.PlannedUniversalVoucher" id="lock15ba81480" mode="IX" associatedObjectId="72057594113425408">
    <owner-list>
     <owner id="process894748" mode="IX"/>
    </owner-list>
    <waiter-list>
     <waiter id="processd0db8088" mode="S" requestType="wait"/>
    </waiter-list>
   </pagelock>
  </resource-list>
 </deadlock>
</deadlock-list>

最佳答案

让我试试。

您有两个进程,processd0db8088 和 process894748。从执行堆栈中可以看到 process894748 正在执行 PlannedPacketPreserveEVouchers,processd0db8088 正在执行 OfflineOrdersImportPacket。您也可以在此处查看两个进程的相关查询。

从资源列表中可以找到这两个进程死锁的资源。第一个是 RetailVoucher 表上 PK_RetailVoucher 索引中的特定索引行:processd0db8088 独占锁定它,进程 process894748 正在等待获得共享锁。另一个资源是属于 PlannedUniversalVoucher 表的数据页 778990,由进程 process894748 持有,而 processd0db8088 正在等待获得对其的读取访问权限。

锁可以从交易开始的任何地方被拿走。此处显示在执行堆栈中的查询是等待资源的查询,而不是获取锁的查询。检查整个执行跟踪以找出实际获取锁的位置。

适用标准建议:缩短事务、按顺序访问表、适本地建立索引。

关于sql-server - 如何解释 t-sql 死锁跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23053560/

相关文章:

database - Prolog 数据库查询

sql - 如何查找超过1个大写字符

sql-server - 在两个结果集中查找 'missing' 行

sql-在执行中超出变量大小?

c# - 将运算符传递给存储过程

android - 如何在android中创建数据库?

tsql - 清除数据库表的 SQL 脚本

sql-server - SQL Cascade 树可视化工具

c# - SQL Server 2012 FileTable 创建文件时性能下降(集成 Lucene.NET)

c# - 需要找到数据库列的类型