我有一个处理传入消息的应用程序,但根据消息的类型,我希望以单例方法处理它们,这意味着不允许同时处理两个相同类型的消息.
所以在我的数据库中,我有一个包含消息的MessageInformation
表和一个ExecuteStatus
.其中,0=未处理,1=正在处理,6=打开.
现在,我想知道到达的新消息是应该标记为正在处理还是应该被搁置.
我使用下面的SQL语句很容易做到这一点:
IF EXISTS (SELECT 1 FROM [dbo].[MessageInformations] WHERE MessageType = @MessageType AND ExecuteStatus IN (1,6))
BEGIN
UPDATE [dbo].[MessageInformations]
SET ExecuteStatus = 6
OUTPUT Inserted.ExecuteStatus
WHERE [Identifier] = @MessageIdentifier
END
ELSE
BEGIN
UPDATE [dbo].[MessageInformations]
SET ExecuteStatus = 1
OUTPUT Inserted.ExecuteStatus
WHERE [Identifier] = @MessageIdentifier
END
这里的问题是它不是"线程安全的",这意味着如果两个消息同时到达,这两个消息可能都被标记为Processing
,而实际上应该只有1个.我可以将它放在一个事务中并锁定MessageInformation
表,但我不想在整个表上加锁,因为可能有其他类型的消息不想等待锁定完成,我只对该特定消息类型的消息运行此查询.其他消息类型将简单地设置为Processing
.
而且表中也有很多消息,它将稳定在4,000-5,000万条左右(清除旧消息).
因此,我需要一个单独的UPDATE
语句来为我完成这项工作,或者需要一种方法来仅锁定表中与MessageType
匹配的行(我可以在此基础上添加一个日期范围以减少要匹配的记录,因为如果一条消息在ON Hold上超过几个小时,则一定有问题).
说得更清楚一点.以下是包括的几个步骤.
-
首先,有一个步骤在数据库中创建消息,并将其标记为"未处理"
-
然后,有几个处理器会获得一个分配给它们的消息标识符来try 处理这些消息.因此,基本上处理器带有一个消息标识符并需要验证是否可以处理该消息,或者是否应该将其搁置.如果它被标记为‘正在处理’=1,则处理器可以继续处理该消息,但如果它被标记为‘OnHold’=6,则处理器必须停止并结束处理.这就是我希望我的SQL查询得出的结果.
-
当处理器处理完"Singleton"消息时,它会将其标记为"已处理"=2,并将告诉"Manager"可以获取第一个(基于创建时间)‘onhold’消息并处理它,因此它将继续,直到不再有‘onhold’消息.
-
当数据库中存在此消息类型的"保留"或"处理"消息时到达的任何新消息都应始终进入"保留"状态,因此保留消息将按其到达的顺序进行处理.
我可以创建一个单独的表并将等待消息放在其中,但如果我可以通过简单地更改MessageInformation表中的状态来解决它,就会容易得多,因为有许多其他逻辑依赖于该表.