gpt4 book ai didi

sql - 同一个表上带有 X 和 U 锁的死锁

转载 作者:行者123 更新时间:2023-12-02 08:46:35 26 4
gpt4 key购买 nike

我有一个存储过程,在 Begin 和 Commit tran 下包含以下两个事务。

UPDATE  mytable
SET UserID = @ToUserID
WHERE UserID = @UserID

DELETE FROM mytable
WHERE UserID = @UserID

在多次执行运行该存储过程时,我遇到了死锁。这是死锁图:

<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>

有人可以解释一下死锁的原因和原因吗?

我现在很难理解这个 X 和 U 锁流程。

你能解释一下 X 和 U 之间发生死锁的流程吗?

最佳答案

您没有提供足够的查询详细信息,但您共享的死锁图清楚地表明,这是由于并行性而导致的“写入器-写入器”死锁,因为授予或请求的所有锁都是XU

<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>

关于写入器-写入器死锁的一个重要问题是,SQL Server 在事务提交之前一直持有独占锁,这与默认读取已提交的共享锁不同隔离级别。

如果没有查询详细信息,就无法找出错误的确切原因。通常,您需要重构查询以避免出现死锁,例如

  1. SELECT 查询移至事务之外,以便它仅返回提交的数据,而不是返回包含修改的数据这可能会回滚。
  2. 有时您需要调整查询,这样 SQL Server 就不需要尽可能并行化或完全并行化。
  3. 向查询添加 MAXDOP 提示以强制其串行运行将删除查询内并行死锁的任何变化。

死锁的其他常见原因是,当您读取数据并打算稍后通过放置共享锁来更新或删除它时,以下 UPDATE 语句无法获取必要的更新锁,因为该资源已被另一个进程阻塞,导致死锁。

要解决此问题,您可以使用 WITH (SERIALIZABLE) 来选择记录,如下所示

UPDATE  mytable WITH (SERIALIZABLE)
SET UserID = @ToUserID
WHERE UserID = @UserID

这将在记录上获取必要的更新锁,并阻止其他进程获取记录上的任何锁(共享/独占),并防止任何死锁。

您还需要注意查询的顺序,错误的顺序可能会导致循环死锁。在这种情况下,查询会等待不同事务中的另一个查询完成。

关于sql - 同一个表上带有 X 和 U 锁的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54597532/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com