我有一个非常简单的T-SQL查询
DELETE FROM my_table
WHERE [id] = @Id
INSERT INTO my_table
([id], [payload])
VALUES
(@Id, @Payload)
很多这样的查询都是在不同的线程中执行的。INSERT和DELETE位于
事务
with类型
已提交读取
..。每件事在99.9%的时间里都工作得很好,但当它失败的时候有一个边缘情况:
Violation of PRIMARY KEY constraint 'PK_my_table'. Cannot insert duplicate key in object 'dbo.my_table'. The duplicate key value is (9).
The statement has been terminated.
出现以下情况时会出现问题:
我们有2个交易具有相同的@Id
表my中没有@Id的记录
_
表格
因此,第一个和第二个事务以DELETE开始。两个事务都不会删除任何内容,因为表my中没有记录
_
表格。两个都开始插入,并且都违反了主键。
问题是如何避免这种情况
读取提交的事务类型
和
不使用MERGE语句
发布于 2021-02-20 02:32:58
我们有2个具有相同@Id的交易记录我们在表my中没有带有@Id的记录
_
表格
这就是范围锁定要解决的场景。在SERIALIZABLE或HOLDLOCK提示下,您将在空键范围上使用键范围锁。
例如
drop table if exists tt
go
create table tt(id int primary key, a int)
begin transaction
delete from tt
where id = 1
select resource_type, request_mode, request_status
from sys.dm_tran_locks
where request_session_id = @@spid
commit transaction
go
begin transaction
delete from tt with (holdlock)
where id = 1
select resource_type, request_mode, request_status
from sys.dm_tran_locks
where request_session_id = @@spid
commit transaction
输出
(0 rows affected)
resource_type request_mode request_status
------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------
OBJECT IX GRANT
(1 row affected)
(0 rows affected)
resource_type request_mode request_status
------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------
KEY RangeX-X GRANT
OBJECT IX GRANT
(2 rows affected)
https://stackoverflow.com/questions/66282479
复制相似问题