关于在sql server中更新行时的锁定行为

时间:2015-04-08 04:11:14

标签: sql sql-server locking increment

现在,我正在尝试使用用户提供的数字来增加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

由于

2 个答案:

答案 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并尽可能删除增量列的手动计算。