Rag*_*hav 12 sql sql-server database-administration database-deadlocks
我有一个存储过程,在Begin和Commit tran下有以下两个事务.
UPDATE mytable
SET UserID = @ToUserID
WHERE UserID = @UserID
DELETE FROM mytable
WHERE UserID = @UserID
Run Code Online (Sandbox Code Playgroud)
在运行具有多次执行的Store Procedure时,我会死锁.这是死锁图:
<deadlock-list>
<deadlock victim="process16409057468">
<process-list>
<process id="process16409057468" taskpriority="0" logused="912" waitresource="RID: 6:1:2392:152" waittime="3022" ownerId="6283339" transactionname="user_transaction" lasttranstarted="2019-02-08T21:08:24.663" XDES="0x16401b98490" lockMode="U" schedulerid="8" kpid="23924" status="suspended" spid="92" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2019-02-08T21:08:24.667" lastbatchcompleted="2019-02-08T21:08:24.667" lastattention="1900-01-01T00:00:00.667" clientapp=".Net SqlClient Data Provider" hostname="GYAAN" hostpid="5624" loginname="sa" isolationlevel="read uncommitted (1)" xactid="6283339" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="mytable" line="377" stmtstart="33320" stmtend="33540" sqlhandle="0x030006004f6bf63211085201eaa9000001000000000000000000000000000000000000000000000000000000">
UPDATE mytable
SET UserID = @ToUserID
WHERE UserID = @UserID
</frame>
</executionStack>
<inputbuf>
Proc [Database Id = 6 Object Id = 855010127]
</inputbuf>
</process>
<process id="process163feab3088" taskpriority="0" logused="912" waitresource="RID: 6:1:2392:149" waittime="99" ownerId="6282851" transactionname="user_transaction" lasttranstarted="2019-02-08T21:08:22.107" XDES="0x16401b20490" lockMode="U" schedulerid="3" kpid="33220" status="suspended" spid="81" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2019-02-08T21:08:22.103" lastbatchcompleted="2019-02-08T21:08:22.107" lastattention="1900-01-01T00:00:00.107" clientapp=".Net SqlClient Data Provider" hostname="GYAAN" hostpid="5624" loginname="sa" isolationlevel="read uncommitted (1)" xactid="6282851" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="mytable" line="382" stmtstart="33650" stmtend="33848" sqlhandle="0x030006004f6bf63211085201eaa9000001000000000000000000000000000000000000000000000000000000">
DELETE FROM mytable
WHERE UserID = @UserID
</frame>
</executionStack>
<inputbuf>
Proc [Database Id = 6 Object Id = 855010127]
</inputbuf>
</process>
</process-list>
<resource-list>
<ridlock fileid="1" pageid="2392" dbid="6" objectname="mytable" id="lock164096b7800" mode="X" associatedObjectId="72057594051493888">
<owner-list>
<owner id="process163feab3088" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process16409057468" mode="U" requestType="wait"/>
</waiter-list>
</ridlock>
<ridlock fileid="1" pageid="2392" dbid="6" objectname="mytable" id="lock163f7fb2c80" mode="X" associatedObjectId="72057594051493888">
<owner-list>
<owner id="process16409057468" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process163feab3088" mode="U" requestType="wait"/>
</waiter-list>
</ridlock>
</resource-list>
</deadlock>
</deadlock-list>
Run Code Online (Sandbox Code Playgroud)
有人可以解释如何以及可能导致死锁的原因吗?
此刻我很难理解这个X和U锁定流程.
你能解释一下X和U之间可能发生什么样的事情会卡在死锁之间吗?
您没有提供您的查询的足够的细节,但你已经清楚地共享僵局图表显示,这是一个"作家的作家" 的僵局,由于并行性,如授予或请求的所有锁要么是X或ü.
<resource-list>
<ridlock fileid="1" pageid="2392" dbid="6" objectname="xx" id="lock164096b7800" mode="X" associatedObjectId="72057594051493888">
<owner-list>
<owner id="process163feab3088" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process16409057468" mode="U" requestType="wait"/>
</waiter-list>
</ridlock>
<ridlock fileid="1" pageid="2392" dbid="6" objectname="mytable" id="lock163f7fb2c80" mode="X" associatedObjectId="72057594051493888">
<owner-list>
<owner id="process16409057468" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process163feab3088" mode="U" requestType="wait"/>
</waiter-list>
</ridlock>
</resource-list>
Run Code Online (Sandbox Code Playgroud)
关于编写器 - 编写器死锁的一个重要问题是SQL Server在事务提交之前保持独占锁,这与默认read committed隔离级别中的共享锁不同.
如果没有查询详细信息,则无法找出错误的确切原因.通常,您需要重新考虑查询以避免类似的死锁
SELECT在事务之外移动查询,以便它只返回已提交的数据,而不是返回包含可能回滚的修改的数据.MAXDOP查询添加提示以强制它以串行方式运行将删除查询内并行性死锁的任何更改.死锁的其他常见原因是当您通过仅放置共享锁来读取数据以便稍后更新或删除时,以下UPDATE语句无法获取必要的更新锁,因为该资源已被另一个进程阻止导致死锁.
要解决此问题,您可以使用WITH (SERIALIZABLE)以下内容选择记录
UPDATE mytable WITH (SERIALIZABLE)
SET UserID = @ToUserID
WHERE UserID = @UserID
Run Code Online (Sandbox Code Playgroud)
这将在记录上采取必要的Update锁定,并将停止其他进程获取记录上的任何锁定(共享/独占)并防止任何死锁.
您还需要查找查询的顺序,错误的订单可能导致循环死锁.在这种情况下,查询将等待不同事务中的另一个事务完成.
| 归档时间: |
|
| 查看次数: |
342 次 |
| 最近记录: |