Reputation: 4339
I'm trying to sort out a deadlock by looking at the t-sql trace but I'm struggling to understand the information. I have a summary of the info here and then the full deadlock trace at the end of the post:
The first lock is on a table called dbo.RetailVoucher
The second lock is on a table called ooc.PlannedUniversalVoucher
The 1st stored procedure reads the following tables:
dbo.RetailVoucher, ooc.PlannedOrderItem and ooc.PlannedOrder.
The 2nd stored procedure reads the following tables:
ooc.PlannedBatch & ooc.PlannedUniversalVoucher
Now, for the procedures to be waiting for each other, I thought they would both have to be reading the same table at some point. I obviously don't understand how to interpret the trace. Do I need to hunt down the source of the locks on dbo.RetailerVoucher and ooc.PlannedUniversalVoucher in other procedures?
Thanks.
Here's the full trace:
<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>
Upvotes: 1
Views: 950
Reputation: 10098
Let me try.
You have tho processes, processd0db8088 and process894748. From the execution stack you can see that the process894748 was executing PlannedPacketPreserveEVouchers, and processd0db8088 is executing OfflineOrdersImportPacket. You can see the queries in question for both processes there as well.
From resource list you can find out the resorces on which these two processes were deadlocked. First one is a particular index row in PK_RetailVoucher index on RetailVoucher table: processd0db8088 locked it exclusively and the process process894748 is waiting to gain shared lock on it. The other resource is a data page 778990 which belongs to PlannedUniversalVoucher table, held by process process894748 while processd0db8088 is waiting to gain read access to it.
The locks could have been taken anywhere from start of transaction. The queries shown here in the execution stack are the queries that were waiting on the resources, not the ones that taken the locks. Inspect the whole execution trace to find out where the locks were actually taken.
The standard advices apply: shorten transactions, access the tables in order, index appropriatelly.
Upvotes: 5