标题过于宽泛但我无法找到更具体的标题,请随意更改。
我有一个使用序列而不是身份的表。我有三个生产者应用程序同时插入到表中,而消费者应用程序从未处理状态的表中进行选择,然后处理它们并最终更新已处理的行。
消费者应用程序有一条规则,它不处理其id(标识列值)小于最后自己处理的id的行
问题是,虽然我从未假设发生过,但我的消费者应用程序在运行时会陷入此规则。 (为其他目的而开发的规则)。想象;
每个应用程序都会向数据库发送新数据,在正常情况下,每个应用程序都应由消费者选择并进行处理(轮询),但有时(在工作期内)我的表中始终有未经处理的数据。
这是我的插入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。
我希望我对这个问题很清楚。可能是我解释的问题还是其他的问题?如果它是关于序列的,我可以为每个消费者锁定整个过程 - 获取序列和插入吗?
答案 0 :(得分:2)
这称为race condition
。在这种意义上,序列(以及在持久化之前检索值的任何其他方法)都是不安全的。
您希望将序列的下一个值作为ID列的默认约束:
[id] INT NOT NULL CONSTRAINT [DF_MyTable_ID] DEFAULT NEXT VALUE FOR [dbo].[MySequence]
这样,当记录被持久化时,将生成新的序列值。这与IDENTITY()
子句基本相同。