添加提示以阻止特定值的插入/更新

问题描述 投票:0回答:1

我在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 插入。其他找到的解决方案也有副作用:

  1. 将GroupID与上层表分开,但是修改我的实际案例的现有代码成本非常高,并且新表仍然需要使用TABLOCK来处理INSERT情况
  2. 使用TABLOCK锁定全表,但性能损失巨大
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
  1. 使用HOLDLOCK或SERIALIZABLE强制所有事务按顺序运行,仍然有巨大的性能损失
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

那么我是否知道还有其他方法可以处理这种情况,或者我可以使用一些关键词来搜索?谢谢!

sql-server multithreading
1个回答
0
投票

我知道UPDLOCK可以在GroupID已经存在的情况下完美运行,但它无法处理当时两个新的GroupID插入。

添加 HOLDLOCK。这添加了 SERIALIZABLE 隔离级别的空范围锁定行为。

© www.soinside.com 2019 - 2024. All rights reserved.