MSSQL Deadlock when update withc (updlock)(使用 c 更新时 MSSQL 死锁(updlock))
问题描述
我在更新时遇到了死锁.事务级别设置为Read Committed
.在这种情况下如何避免死锁?
I got deadlock while updating. The transaction level is set to Read Committed
. How to avoid deadlock in such situation?
在其他情况下,WITH (NOLOCK)
和 WITH (UPDLOCK)
有帮助.
我得到了以下 T-SQL
查询:
In other cases WITH (NOLOCK)
and WITH (UPDLOCK)
helped.
I got the following T-SQL
query:
IF EXISTS (SELECT 1 FROM DEBTORS_CUSTOMERS WITH (NOLOCK) WHERE DebtorId = @DebtorId AND ClientFCCustomerNumber = @CustomerNumber)
UPDATE DEBTORS_CUSTOMERS WITH (UPDLOCK) SET StatusId = @StatusId WHERE DebtorId = @DebtorId AND ClientFCCustomerNumber = @CustomerNumber
ELSE
INSERT INTO DEBTORS_CUSTOMERS (DebtorId, ClientFCCustomerNumber, StatusId, DocId) SELECT @DebtorId, @CustomerNumber, @StatusId, @DocId
这是我遇到的僵局:
<resource-list>
<keylock hobtid="72057594105692160" dbid="63" objectname="EOTestDataGenerator.dbo.DEBTORS_CUSTOMERS" indexname="PK_DEBTORS_CUSTOMERS" id="lockdf8abb00" mode="X" associatedObjectId="72057594105692160">
<owner-list>
<owner id="process3f59048" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="processbdbfa088" mode="U" requestType="wait"/>
</waiter-list>
</keylock>
<keylock hobtid="72057594105692160" dbid="63" objectname="EOTestDataGenerator.dbo.DEBTORS_CUSTOMERS" indexname="PK_DEBTORS_CUSTOMERS" id="lockdf5ab200" mode="X" associatedObjectId="72057594105692160">
<owner-list>
<owner id="processbdbfa088" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="process3f59048" mode="U" requestType="wait"/>
</waiter-list>
</keylock>
</resource-list>
推荐答案
每个事务处理多行,对吗?这不应该为一行死锁
You are processing multiple rows per transaction, right? This should not deadlock for one row
不过,您可能会得到双插入,这是一个错误.两个会话可能会得出没有行的结论,然后两个会话都会插入.
You might get double-inserts, though, which is a bug. Two sessions might conclude that there is no row and then both will insert.
有两种方法可以确保安全:
There are two ways to make this safe:
- 发出 select
WITH (ROWLOCK, UPDLOCK, HOLDLOCK)
这是一个众所周知的锁定提示序列.它需要一个锁来稳定您正在操作的数据.运行此语句后,您将拥有自己的数据.然后您可以插入或更新.您也可以将所有三个语句合并到一个MERGE
中,但您仍然需要锁定提示.此外,您必须有某种全局顺序来发出写入.现在,无论您如何锁定,如果一个会话写入 A、B,而另一个会话按 B、A 顺序写入,则总是会出现死锁.获得全局顺序的一种简单方法是在单个MERGE 中发出所有写入
语句.查询处理器通常会选择一个强制执行顺序的计划. - 使用
SERIALIZABLE
隔离并重试死锁.
- Issue the select
WITH (ROWLOCK, UPDLOCK, HOLDLOCK)
which is a well-known lock hint sequence. It takes a lock that stabilized the data you are operating on. After this statement has run you have the data for yourself. You can then insert or update. You can also collapse all three statements into oneMERGE
but you still need the lock hints. Also, you must have some kind of global order in which you issue the writes. Right now no matter how you lock there can always be a deadlock if one session writes A, B and the other writes in order B, A. An easy way to get a global order is to issue all writes in a singleMERGE
statement. The query processor usually picks a plan that enforces order. - Use
SERIALIZABLE
isolation with retry on deadlock.
这篇关于使用 c 更新时 MSSQL 死锁(updlock)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:使用 c 更新时 MSSQL 死锁(updlock)
- 在SQL中,如何为每个组选择前2行 2021-01-01
- 如何使用 pip 安装 Python MySQLdb 模块? 2021-01-01
- 远程 mySQL 连接抛出“无法使用旧的不安全身份验证连接到 MySQL 4.1+"来自 XAMPP 的错误 2022-01-01
- 如何将 SonarQube 6.7 从 MySQL 迁移到 postgresql 2022-01-01
- 如何将 Byte[] 插入 SQL Server VARBINARY 列 2021-01-01
- 使用 Oracle PL/SQL developer 生成测试数据 2021-01-01
- 以一个值为轴心,但将一行上的数据按另一行分组? 2022-01-01
- 导入具有可变标题的 Excel 文件 2021-01-01
- 更改自动增量起始编号? 2021-01-01
- SQL 临时表问题 2022-01-01