我一直在研究死锁,它是不同的原因。我找到了一个关于这个问题的例子,但我无法完全理解死锁的原因,因为涉及两个不同的表,到目前为止我读到的是只涉及一个表!
首先,我在连接 1 中运行此查询:
Begin Tran
Update Purchasing.PurchaseOrderHeader
Set Freight = Freight * 0.9
Where PurchaseOrderID = 1255;
Run Code Online (Sandbox Code Playgroud)
我再次在连接 2 中运行此查询:
update Purchasing.PurchaseOrderDetail
Set OrderQty = 4
Where ProductID = 448 and
PurchaseOrderID = 1255
Run Code Online (Sandbox Code Playgroud)
回到连接 1 我运行这个查询(这会导致死锁):
Begin Transaction
Update Purchasing.PurchaseOrderDetail
Set OrderQty = 2
where ProductID = 448 and
PurchaseOrderID = 1255
Run Code Online (Sandbox Code Playgroud)
可以看到,事务中涉及到两张表,那么到底是什么导致了死锁呢??提前致谢
我无法完全理解死锁的原因,因为涉及两个不同的表,而我目前所读的是只涉及一个表!
当 2 个或更多会话相互等待时会发生死锁。死锁资源是同一个表、不同表、整个对象等中的行都没有关系。
我运行了您的脚本来重现死锁,xml_deadlock_report
从system_health
XE 跟踪中提取列,并将死锁报告 XML 保存到带有.xdl
扩展名的文件中。下面是来自 SSMS 的图形视图。
如您所见,SPID 58 受害者正在等待Purchasing.PurchaseOrderDetail
更新键锁,但被同一键上的 SPID 53 独占键锁阻止。SPID 53 正在等待更新Purchasing.PurchaseOrderHeader
密钥锁,被保存在同一密钥上的排他锁 SPID 58 阻止。
下面是原始的 xml_deadlock_report XML。
<deadlock>
<victim-list>
<victimProcess id="process1a668c9eca8"/>
</victim-list>
<process-list>
<process id="process1a668c9eca8" taskpriority="0" logused="400" waitresource="KEY: 6:72057594048348160 (4ab5f0d47ad5)" waittime="1316" ownerId="2500187" transactionname="user_transaction" lasttranstarted="2018-07-24T06:02:13.303" XDES="0x1a85b00c490" lockMode="U" schedulerid="3" kpid="2932" status="suspended" spid="58" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2018-07-24T06:02:31.437" lastbatchcompleted="2018-07-24T06:02:31.433" lastattention="2018-07-24T06:00:22.400" clientapp="Microsoft SQL Server Management Studio - Query" hostname="SQLSERVER" hostpid="15904" loginname="DOMAINNAME\USERNAME" isolationlevel="read committed (2)" xactid="2500187" currentdb="6" lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="64" stmtend="278" sqlhandle="0x02000000d0c7f31a30fb1ad425c34357fe8ef6326793e7aa0000000000000000000000000000000000000000"> unknown </frame>
<frame procname="adhoc" line="1" stmtstart="26" stmtend="326" sqlhandle="0x02000000b66e4532b6686980baf466a9597258f2464dd4f50000000000000000000000000000000000000000"> unknown </frame>
</executionStack>
<inputbuf> Update Purchasing.PurchaseOrderDetail Set OrderQty = 2 where ProductID = 448 and PurchaseOrderID = 1255 </inputbuf>
</process>
<process id="process1a66883d848" taskpriority="0" logused="9484" waitresource="KEY: 6:72057594048413696 (4bc08edebc6b)" waittime="16176" ownerId="2500193" transactionname="user_transaction" lasttranstarted="2018-07-24T06:02:16.577" XDES="0x1a85e004490" lockMode="U" schedulerid="5" kpid="20416" status="suspended" spid="53" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2018-07-24T06:02:16.577" lastbatchcompleted="2018-07-24T06:02:16.570" lastattention="2018-07-24T06:01:28.820" clientapp="Microsoft SQL Server Management Studio - Query" hostname="SQLSERVER" hostpid="15904" loginname="DOMAINNAME\USERNAME" isolationlevel="read committed (2)" xactid="2500193" currentdb="6" lockTimeout="4294967295" clientoption1="673319008" clientoption2="390200">
<executionStack>
<frame procname="AdventureWorks2014.Purchasing.uPurchaseOrderDetail" line="39" stmtstart="2732" stmtend="3830" sqlhandle="0x0300060004cc856a0ee00a016ba3000000000000000000000000000000000000000000000000000000000000"> UPDATE [Purchasing].[PurchaseOrderHeader] SET [Purchasing].[PurchaseOrderHeader].[SubTotal] = (SELECT SUM([Purchasing].[PurchaseOrderDetail].[LineTotal]) FROM [Purchasing].[PurchaseOrderDetail] WHERE [Purchasing].[PurchaseOrderHeader].[PurchaseOrderID] = [Purchasing].[PurchaseOrderDetail].[PurchaseOrderID]) WHERE [Purchasing].[PurchaseOrderHeader].[PurchaseOrderID] IN (SELECT inserted.[PurchaseOrderID] FROM inserted </frame>
<frame procname="adhoc" line="3" stmtstart="64" stmtend="278" sqlhandle="0x02000000d0c7f31a30fb1ad425c34357fe8ef6326793e7aa0000000000000000000000000000000000000000"> unknown </frame>
<frame procname="adhoc" line="3" stmtstart="28" stmtend="250" sqlhandle="0x02000000cac3a70ebbbc20e8360adb397f4986f2ced020140000000000000000000000000000000000000000"> unknown </frame>
</executionStack>
<inputbuf> Begin Tran update Purchasing.PurchaseOrderDetail Set OrderQty = 4 Where ProductID = 448 and PurchaseOrderID = 1255 </inputbuf>
</process>
</process-list>
<resource-list>
<keylock hobtid="72057594048348160" dbid="6" objectname="AdventureWorks2014.Purchasing.PurchaseOrderDetail" indexname="PK_PurchaseOrderDetail_PurchaseOrderID_PurchaseOrderDetailID" id="lock1a7fea46a00" mode="X" associatedObjectId="72057594048348160">
<owner-list>
<owner id="process1a66883d848" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process1a668c9eca8" mode="U" requestType="wait"/>
</waiter-list>
</keylock>
<keylock hobtid="72057594048413696" dbid="6" objectname="AdventureWorks2014.Purchasing.PurchaseOrderHeader" indexname="PK_PurchaseOrderHeader_PurchaseOrderID" id="lock1a815dda900" mode="X" associatedObjectId="72057594048413696">
<owner-list>
<owner id="process1a668c9eca8" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process1a66883d848" mode="U" requestType="wait"/>
</waiter-list>
</keylock>
</resource-list>
</deadlock>
Run Code Online (Sandbox Code Playgroud)
示例AdventureWorks
数据库包括导致此死锁的表UPDATE
触发器Purchasing.PurchaseOrderDetail
。触发插入到Production.TransactionHistory
也同时更新Purchasing.PurchaseOrderHeader
和Purchasing.PurchaseOrderDetail
时ProductID
,OrderQty
或UnitPrice
列被更新。
总之,导致这个僵局的顺序是:
1) 连接 1 更新了一个Purchasing.PurchaseOrderHeader
但没有提交
2) 连接 2 更新了Purchasing.PurchaseDetail
表,尝试更新时触发的触发器被阻止Purchasing.PurchaseOrderHeader
3) connection 1 tried to update Purchasing.PurchaseDetail
but was blocked by connection
4) SQL Server chose connection 1 as the deadlock victim, allowing connection 2 to autocommit
归档时间: |
|
查看次数: |
990 次 |
最近记录: |