sql-server - SQL Server - 实现序列

标签 sql-server tsql sequence

我有一个系统,要求我在数据进入数据库之前拥有数据的 ID。我正在使用 GUID,但发现它们太大而无法证明其便利性。

我现在正在尝试实现一个序列生成器,它基本上为给定的上下文保留一系列唯一的 ID 值。代码如下;

ALTER PROCEDURE [dbo].[Sequence.ReserveSequence]
@Name varchar(100),
@Count int,
@FirstValue bigint OUTPUT
AS
BEGIN
SET NOCOUNT ON;

-- Ensure the parameters are valid
IF (@Name IS NULL OR @Count IS NULL OR @Count < 0)
    RETURN -1;

-- Reserve the sequence
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION

    -- Get the sequence ID, and the last reserved value of the sequence
    DECLARE @SequenceID int;
    DECLARE @LastValue bigint;

    SELECT TOP 1 @SequenceID = [ID], @LastValue = [LastValue]
    FROM [dbo].[Sequences]
    WHERE [Name] = @Name;

    -- Ensure the sequence exists
    IF (@SequenceID IS NULL)
    BEGIN
        -- Create the new sequence
        INSERT INTO [dbo].[Sequences] ([Name], [LastValue])
        VALUES (@Name, @Count);

        -- The first reserved value of a sequence is 1
        SET @FirstValue = 1;
    END
    ELSE
    BEGIN
        -- Update the sequence
        UPDATE [dbo].[Sequences]
        SET [LastValue] = @LastValue + @Count
        WHERE [ID] = @SequenceID;

        -- The sequence start value will be the last previously reserved value + 1
        SET @FirstValue = @LastValue + 1;
    END

COMMIT TRANSACTION

END

“序列”表只是序列的 ID、名称(唯一)和最后分配的值。使用此过程,我可以请求命名序列中的 N 个值,并将它们用作我的标识符。

到目前为止,这效果很好 - 速度非常快,因为我不必不断地要求单独的值,我可以用完一系列值,然后要求更多。

问题在于,在极高频率下,并发调用该过程有时会导致死锁。我只在压力测试时发现这种情况,但我担心它会在生产中突然出现。此过程是否存在任何明显的缺陷,有人可以推荐任何改进方法吗?例如,如果没有事务就很好,但我确实需要它是“线程安全的”。

最佳答案

MS themselves offer a solution甚至他们说它会锁定/死锁。 如果您想添加一些锁定提示,那么您需要减少高负载的并发性

选项:

  • 您可以针对下一个版本的“Denali”CTP 进行开发
  • 像其他人一样使用 IDENTITY 和 OUTPUT 子句
  • 采用/修改上述解决方案

在 DBA.SE 上有 "Emulate a TSQL sequence via a stored procedure" :请参阅 dportas 的答案,我认为它扩展了 MS 解决方案。

关于sql-server - SQL Server - 实现序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6750614/

相关文章:

php - 通过 PHP INI 添加 MsSQL

sql-server - 检查约束不适用于超过 250 条记录的批量插入

sql-server - 事务隔离级别范围

java - LibGDX:序列不起作用

Swift 序列迭代器,它隐藏了数组中的一些底层值

SQL Server 2000 try catch

sql - View 和随机数

mysql - sql - 按计数更新列

sql-server-2008 - 创建存储过程以修改行(如果存在),如果不存在则将新行插入表中

c - C语言中使用二分查找查找交错序列