现在,我正在尝试使用用户提供的数字来增加SQL Server中的数字顺序。
当多个用户使用相同的号码同时插入一行时,我遇到了问题。
我尝试更新用户提供给临时表的数量,并且我希望当我以相同的条件更新同一个表时,SQL Server会将修改后的任何修改锁定到当前更新,但不会。 / p>
以下是我使用的更新声明:
UPDATE GlobalParam
SET ValueString = (CAST(ValueString as bigint) + 1)
WHERE Id = 'xxxx'
你能告诉我任何方法强制其他更新命令等到当前命令结束吗?
这完全是我的命令:
DECLARE @Result bigint;
UPDATE GlobalParam SET ValueString = (SELECT MAX(Code) FROM Item)
DECLARE @SelectTopStm nvarchar(MAX);
DECLARE @ExistRow int
SET @SelectTopStm = 'SELECT @ExistRow = 1 FROM (SELECT TOP 1 Code FROM Item WHERE Code = '999') temp'
EXEC sp_executesql @SelectTopStm, N'@ExistRow int output', @ExistRow output
IF (@ExistRow is not null)
BEGIN
DECLARE @MaxValue bigint
DECLARE @ReturnUpdateTbl table (ValueString nvarchar(max));
UPDATE GlobalParam SET ValueString = (CAST(ValueString as bigint) + 1)
OUTPUT inserted.ValueString INTO @ReturnUpdateTbl
WHERE [Id] = '333A8E1F-16DD-E411-8280-D4BED9D726B3'
SELECT TOP 1 @MaxValue = CAST(ValueString as bigint) FROM @ReturnUpdateTbl
SET @Result = @MaxValue
END
ELSE
BEGIN
SET @Output = 999
END
END
我将上面的代码写为存储过程。
这是插入一个项目时的真实代码:
DECLARE @IncrementResult BIGINT
EXEC IncrementNumberUnique
, (some parameters)..
,@Result = @IncrementResult OUTPUT
INSERT INTO ITEM (Id, Code) VALUES ('xxxx', @IncrementResult)
我创建3个线程并让它同时运行。
返回结果:
Id Code
1 999
2 1000
3 1000
由于
答案 0 :(得分:0)
如果我理解了您的要求,请尝试ROWLOCK
提示告诉优化器在更新需要时逐个锁定行。
UPDATE GlobalParam WITH(ROWLOCK)
SET ValueString = (CAST(ValueString as bigint) + 1)
WHERE Id = 'xxxx'
答案 1 :(得分:0)
默认情况下,SQL Server执行READ Committed
锁定,一旦提交读取操作,就会释放READ
锁。完成下面的Update
语句后,将从表Item
中释放所有读锁定。
UPDATE GlobalParam SET ValueString = (SELECT MAX(Code) FROM Item)
由于您的INSERT into Item
不在您的程序范围内。您可以在SERIALIZABLE
隔离级别运行该线程。这样的事情。
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
DECLARE @IncrementResult BIGINT
EXEC IncrementNumberUnique
, (some parameters)..
,@Result = @IncrementResult OUTPUT
INSERT INTO ITEM (Id, Code) VALUES ('xxxx', @IncrementResult)
将隔离级别更改为SERIALIZABLE
会增加item
表上的资源阻塞和争用。
要了解有关隔离级别的更多信息,请参阅this
您应该查看identity columns并尽可能删除增量列的手动计算。