需要在一个原子操作中更新 select

Need to update and select in one atomic operation

我正在编写代码来自动更正支付系统中的错误 - 在他们请求付款之前,他们会更新 [Table] 以获取处理付款所需的所有数据。如果成功,Status=1,如果失败,Status=0。

稍后,如果请求成功,它将重新处理任何状态为 0 的行。 (每个成功的请求只重新处理 1 个,以避免支付系统恢复在线后超载,但多个请求可能同时进入 SQL 服务器以获得失败的记录)

我有一个 table,有人告诉我要做这样的事情:

DECLARE @id int;
SET @id = (select top(1) id from [table] where Status = 0 order by id );

select * from [table] where id = @id;
update [table] set Success = NULL where id = @id;

但如果同时查询 运行,它们可能会得到相同的 @id 值,并且它们都会重新处理付款 - 创建重复项。

我正在考虑这样做:

DECLARE @id int;
DECLARE @tmp int;

SET @id = (select top(1) id from [table] where Success = 0 and RetryAttempCount < 5 order by id);

-- Code to handle multiple people hitting this at once.  One will get -1, and the other -2
-- in the @tmp var.

update [table] set Success = Success -1, @tmp= Success -1 where id = @id;   

if (@tmp = -1)  -- then we got it
   BEGIN
   update [table] set RetryAttemptCount = RetryAttemptCount +1, RetryDate = GetDate(), Success = NULL
       Where id=@id
   select * from [table] where id = @id;
   END

END

我的问题:有没有更好的方法?这似乎有效,返回需要重新处理的行,或者没有结果集。

如果操作的处理顺序无关紧要,为什么不这样做呢?

DECLARE @id int;
UPDATE TOP(1) [table] SET @id=id, Success=NULL WHERE Success=0 AND RetryAttemptCount<5;