ibu*_*ubi 5 sql-server sequence producer-consumer
标题太宽泛了,但我找不到更具体的,请随时更换更好的。
我有一个使用序列而不是身份的表。我有三个同时插入表的生产者应用程序,一个消费者应用程序从未处理状态的表中选择,然后处理它们,最后更新已处理的行。
消费者应用程序有一个规则,它不处理 id(标识列值)小于最后自己处理的 id 的行。
问题是,虽然我从未假设会发生,但我的消费者应用程序在运行时会落入此规则。(为其他目的制定的规则)。形象化;
每个应用程序都会向数据库发送新数据,在正常情况下,每个应用程序都应该由消费者选择并处理(轮询),但是有时(在工作期间内)我的表中总是有未处理的数据。
这里我的insert 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
Run Code Online (Sandbox Code Playgroud)
所以我在想,生产者2和生产者3调用存储过程的时候,他们首先拿到的是序列值。然后,当涉及到插入时,不知何故,生产者 3 的插入发生得比生产者 2 快。然后消费者在较小的 id 之前处理较大的 id,因此永远不会处理 id 26。
我希望我清楚这个问题。可能是我解释的问题还是其他问题?如果是关于序列,我可以为每个消费者锁定整个过程 - 获取序列并插入吗?
这就是所谓的race condition
。从这个意义上说,序列(以及在持久化之前检索该值的任何其他方法)是不安全的。
您希望将序列的下一个值作为 ID 列的默认约束:
[id] INT NOT NULL CONSTRAINT [DF_MyTable_ID] DEFAULT NEXT VALUE FOR [dbo].[MySequence]
Run Code Online (Sandbox Code Playgroud)
这样,当记录被持久化时,将生成新的序列值。这本质上与子句相同IDENTITY()
。