我在SQL Server上有一个非常经典的多线程问题,通过数据值控制锁定行为,但我找不到正确的关键字来搜索解决方案。
假设我们的表 A 在读提交数据库上有 2 个主键列 GroupID 和 ItemID
CREATE TABLE A (
GroupID INT
, ItemID INT
, Attribute1 VARCHAR(50) PRIMARY KEY (GroupID, ItemID)
)
如何有效地阻止仅针对特定 GroupID 值的插入/更新/删除,并且该值一开始可能不是表?
比如所有 GroupID = 1 的事务都需要一一运行(忽略顺序),但新的 GroupID = 2 事务可以同时流畅处理。
我知道如果 GroupID 已经存在,UPDLOCK 可以完美运行,但当时它无法处理两个新的 GroupID 插入。其他找到的解决方案也有副作用:
TRUNCATE TABLE A
DECLARE @GroupID INT = 1 --Change to 2 in other thread
DECLARE @RowCount INT
BEGIN TRAN
SELECT @RowCount = COUNT(*) FROM A WITH(TABLOCKX) WHERE A.GroupID = @GroupID
WAITFOR DELAY '00:00:10' --Comment in other thread
INSERT INTO A SELECT @GroupID,@RowCount+1,'Value1'
COMMIT TRAN
--Thread 2 must wait Thread 1 complete
TRUNCATE TABLE A
DECLARE @GroupID INT = 1 --Change to 2 in other thread
DECLARE @RowCount INT
BEGIN TRAN
SELECT @RowCount = COUNT(*) FROM A WITH(UPDLOCK, HOLDLOCK) WHERE A.GroupID = @GroupID
WAITFOR DELAY '00:00:10' --Comment in other thread
INSERT INTO A SELECT @GroupID,@RowCount+1,'Value1'
COMMIT TRAN
--Thread 2 must wait Thread 1 complete
那么我是否知道还有其他方法可以处理这种情况,或者我可以使用一些关键词来搜索?谢谢!
我知道UPDLOCK可以在GroupID已经存在的情况下完美运行,但它无法处理当时两个新的GroupID插入。
添加 HOLDLOCK。这添加了 SERIALIZABLE 隔离级别的空范围锁定行为。