我需要创建一个模拟 TSQL 序列的存储过程。也就是说,它总是在每次调用时给出一个递增的不同整数值。此外,如果传入一个整数,如果从未有更大的结果或下一个可用的最高整数,它应该返回该值。不用说可以有多个客户端同时调用这个 SP。
给定一个包含 MetaKey varchar(max) 和 MetaValueLong bigInt 列的 MetaInfo 表。预计 MetaKey 为“Internal-ID-Last”的行将包含最后分配的最高值。我创建了以下存储过程:
CREATE PROCEDURE [dbo].[uspGetNextID]
(
@inID bigInt
)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION
UPDATE MetaInfo WITH (ROWLOCK)
SET MetaValueLong = CASE
WHEN ISNULL(MetaValueLong,0) > @inID THEN MetaValueLong+1
ELSE @inID+1
END
WHERE MetaKey = 'Internal-ID-Last'
SELECT MetaValueLong
FROM MetaInfo
WHERE MetaKey = 'Internal-ID-Last'
COMMIT TRANSACTION
END
我的问题很简单,这个存储过程是否按预期工作(所有调用者都将被分配一个唯一的结果)?
我看过了,微软自己提供了一个没有锁的解决方案:
SQL Server 序列号
这是一个没有锁定提示的简单更新,但他们说它会锁定/死锁。
关于这点也没什么。
我倾向于添加
UPDLOCK
到您的ROWLOCK
(根据“作为队列的表”(SO)但没有READPAST
)。如果第二个进程开始读取,这将增加隔离。然而,你所有的进程都想读/写同一行的事实让我自己第二次猜测。
READPAST
允许安全并发,但在这种情况下它是无用的。注意:您可以使用该
OUTPUT
子句而不是第二个选择,那么您不需要该事务。下面的东西不见了
是的,应该符合你的条件。一旦这种情况出现在事务中,它会创建多个实例,随后,所有调用者都将被分配一个唯一的结果
不需要序列化的更具可扩展性的解决方案是: