【发布时间】:2009-07-02 18:07:35
【问题描述】:
我正在编写一个大容量交易系统。我们每秒收到大约 300-500 条消息,然后这些消息需要尽快保存到数据库中。这些消息存放在消息队列中,然后从那里读取。
我已经实现了一个竞争消费者模式,它从队列中读取数据并允许对消息进行多线程处理。但是,当应用程序运行时,我经常遇到主键违规问题。
我们正在运行 SQL 2008。示例表结构为:
TableA
{
MessageSequence INT PRIMARY KEY,
Data VARCHAR(50)
}
一个存储过程被调用来持久化这条消息,看起来像这样:
BEGIN TRANSACTION
INSERT TableA(MessageSequence, Data )
SELECT @MessageSequence, @Data
WHERE NOT EXISTS
(
SELECT TOP 1 MessageSequence FROM TableA WHERE MessageSequence = @MessageSequence
)
IF (@@ROWCOUNT = 0)
BEGIN
UPDATE TableA
SET Data = @Data
WHERE MessageSequence = @MessageSequence
END
COMMIT TRANSACTION
所有这些都在一个 TRY...CATCH 块中,所以如果出现错误,它会回滚事务。
我尝试过使用表格提示,例如 ROWLOCK,但并没有什么不同。由于插入被评估为单个语句,因此我仍然遇到“插入时的主键”问题似乎很可笑。
有人知道为什么会这样吗?您有什么想法可以为我指明解决方案的方向吗?
【问题讨论】:
-
什么版本的sql server?如果是 2008 年,你可以试试 MERGE 语句
-
我不知道它是否会提高性能,但试试新的 MERGE 语句。对于最近的一个项目,我决定忽略它,因为学习时间太长。不对。使用 BOL 示例的 15 分钟让我的 SP 正常工作。
-
有趣的是,随着事务加载,可能会发生奇怪的事情。我首先想到的是为什么不使用 IDENTITY 作为密钥,但更好地阅读我知道 ID 在消息中。
-
我确实尝试了新的 MERGE 语句,但它导致了同样的错误 - 主键违规。去图吧。
标签: sql multithreading sql-server-2008