SQL Server - 实现序列

2024-03-30

我有一个系统,要求我在数据进入数据库之前拥有数据的 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 他们自己提供了解决方案 http://blogs.msdn.com/b/sqlcat/archive/2006/04/10/sql-server-sequence-number.aspx甚至他们说它会锁定/死锁。 如果您想添加一些锁定提示,那么您需要减少高负载的并发性

Options:

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

在 DBA.SE 上有“通过存储过程模拟 TSQL 序列” https://dba.stackexchange.com/q/3307/630:请参阅 dportas 的答案,我认为它扩展了 MS 解决方案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SQL Server - 实现序列 的相关文章

随机推荐