2016-05-26 4 views
0

支払いシステムで障害を自動修正するコードを作成しています。支払いを要求する前に[テーブル]を更新して支払い処理に必要なすべてのデータを保持します。動作している場合、Status = 1、失敗した場合はStatus = 0となります。1つのアトミック操作で更新して選択する必要があります

要求が成功すると、ステータス= 0の行はすべて再処理されます。 (オンラインに戻った後、支払システムに過負荷がかかるのを避けるために、成功した要求ごとに再処理されるのは1回だけですが、同時に複数の要求がSQL Serverに届く可能性があります)

私は、ような何か:

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 [email protected] 
    select * from [table] where id = @id; 
    END 

END 

私の質問:より良い方法はあり

は、私がこれをやって考えていますか?これは、再処理が必要な行、または結果セットがない行のいずれかを返すように動作しているようです。

答えて

1

操作が処理される順序が問題でない場合は、どうしてこのようにする必要はありませんか?

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

ここからid * @ idのところから*を選択してください - 私はそれが好きです - 私はもっと良い方法があるはずでした! –

+0

私が最初にこれをコピーしたとき、私はトップを見逃しました(1)トップ1が動作しないのは奇妙です。私はそれが前にそのようにしたことはないと思う。 –

関連する問題