SQL Server序列是否安全?

时间:2017-11-29 06:52:44

标签: sql-server sequence producer-consumer

标题过于宽泛但我无法找到更具体的标题,请随意更改。

我有一个使用序列而不是身份的表。我有三个生产者应用程序同时插入到表中,而消费者应用程序从未处理状态的表中进行选择,然后处理它们并最终更新已处理的行。

消费者应用程序有一条规则,它不处理其id(标识列值)小于最后自己处理的id的行

问题是,虽然我从未假设发生过,但我的消费者应用程序在运行时会陷入此规则。 (为其他目的而开发的规则)。想象;

problem

每个应用程序都会向数据库发送新数据,在正常情况下,每个应用程序都应由消费者选择并进行处理(轮询),但有时(在工作期内)我的表中始终有未经处理的数据。

这是我的插入sp看起来像生产者常用的那些;

CREATE PROCEDURE spInsData
    @Data VARCHAR(MAX)
AS
BEGIN
    SET @Id = NEXT VALUE FOR dbo.sequenceId

    INSERT INTO dbo.MyTable(Id, Data, Status)
    VALUES (@Id, @Data, 0)
END

所以我想到的是,当Producer 2和Producer 3调用存储过程时,它们首先获取序列值。然后,当涉及插入时,生产者3的插入比生产者2更快地发生。然后消费者在较小的ID之前处理较大的id,因此永远不会处理id 26。

我希望我对这个问题很清楚。可能是我解释的问题还是其他的问题?如果它是关于序列的,我可以为每个消费者锁定整个过程 - 获取序列和插入吗?

1 个答案:

答案 0 :(得分:2)

这称为race condition。在这种意义上,序列(以及在持久化之前检索值的任何其他方法)都是不安全的。

您希望将序列的下一个值作为ID列的默认约束:

[id] INT NOT NULL CONSTRAINT [DF_MyTable_ID] DEFAULT NEXT VALUE FOR [dbo].[MySequence]

这样,当记录被持久化时,将生成新的序列值。这与IDENTITY()子句基本相同。