SQL问题 - 高容量转换和PK违规

Dio*_*ion 5 sql multithreading sql-server-2008

我正在写一个大批量的交易系统.我们以每秒300-500左右的速度接收消息,然后需要尽快将这些消息保存到数据库中.这些消息存放在消息队列中,然后从那里读取.

我实现了一个Competing Consumer模式,它从队列中读取并允许对消息进行多线程处理.但是,当应用程序运行时,我经常遇到主键违规.

我们正在运行SQL 2008.示例表结构将是:

TableA
{
    MessageSequence INT PRIMARY KEY,
    Data VARCHAR(50)
}
Run Code Online (Sandbox Code Playgroud)

调用存储过程以保留此消息并看起来像这样:

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
Run Code Online (Sandbox Code Playgroud)

所有这些都在TRY ... CATCH块中,所以如果出现错误,它会回滚事务.

我尝试过使用表格提示,比如ROWLOCK,但它并没有什么区别.由于Insert被评估为单个语句,因此我仍然得到"插入时的主键"问题似乎很荒谬.

有谁知道为什么会这样?您是否有任何想法可以指出我的解决方案?

Joe*_*Joe 0

这可能与事务隔离级别有关。你可能需要

设置事务隔离级别已提交读

在您开始交易之前。

另外,如果更新多于插入,则应首先尝试更新并检查行数,然后再执行插入。