通过存储过程模拟 TSQL 序列

Hog*_*gan 17 sql-server-2008

我需要创建一个模拟 TSQL 序列的存储过程。也就是说,它总是在每次调用时给出一个递增的不同整数值。此外,如果传入一个整数,如果从来没有更大的结果或可用的下一个最高整数,则它应该返回该值。不用说,可以有多个客户端同时调用此 SP。

给定一个包含 MetaKey varchar(max) 和 MeatValueLong 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
Run Code Online (Sandbox Code Playgroud)

我的问题很简单,这个存储过程是否按预期工作(所有调用者都将被分配一个唯一的结果)?

gbn*_*gbn 8

我看过了,MS 自己提供了一个没有锁的解决方案

http://blogs.msdn.com/b/sqlcat/archive/2006/04/10/sql-server-sequence-number.aspx

这是一个没有锁定提示的简单更新,但他们说它锁定/死锁。

关于这一点也没什么。

我倾向于将 UPDLOCK 添加到您的 ROWLOCK(根据“表作为队列”(SO)但没有 READPAST)。如果第二个进程开始读取,这将增加隔离。

然而,你所有的进程都想读/写同一行的事实让我自己第二次猜测。READPAST 允许安全并发,但在这种情况下它是无用的。

注意:您可以使用 OUTPUT 子句而不是第二次选择,那么您就不需要事务了。

哈...