2016-05-26 15 views
0

Ich schreibe Code, um Fehler in Zahlungssystemen automatisch zu korrigieren - bevor sie eine Zahlung anfordern, aktualisieren sie [Tabelle], um alle Daten zu haben, die zur Verarbeitung der Zahlung benötigt werden. Wenn es funktioniert, ist der Status = 1, wenn es fehlschlägt, Status = 0.Notwendigkeit zum Aktualisieren und Auswählen in einer atomaren Operation

Später, wenn eine Anfrage erfolgreich ist, werden alle Zeilen mit dem Status = 0 erneut verarbeitet. (Nur 1 wird pro erfolgreicher Anfrage erneut verarbeitet, um das Zahlungssystem nicht zu überlasten, sobald es wieder online ist, aber mehrere Anfragen könnten gleichzeitig in den SQL Server für fehlerhafte Datensätze gelangen)

Ich habe eine Tabelle, die mir gesagt wurde so etwas wie:

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; 

Aber wenn Anfragen zur gleichen Zeit laufen, können sie den gleichen Wert für @id bekommen, und beide von ihnen die Zahlung erneut zu verarbeiten - Erstellen von Duplikaten.

Ich denke, dies zu tun:

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 

Meine Frage: Gibt es einen besseren Weg? Dies scheint zu funktionieren und gibt entweder eine Zeile zurück, die erneut verarbeitet werden muss, oder keine Ergebnismenge.

Antwort

1

Wenn die Reihenfolge, in der Operationen verarbeitet werden, keine Rolle spielt, warum nicht einfach?

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

Und dann wählen Sie * aus [Tabelle], wo ID = @ ID - Ich mag es - Ich war mir ziemlich sicher, dass es einen besseren Weg hätte geben sollen! –

+0

Als ich das zum ersten Mal kopiert habe, habe ich das Top verpasst (1) Es ist seltsam, dass Top 1 nicht funktioniert - es braucht das() darum herum. Ich nehme an, deshalb habe ich das vorher noch nie gemacht. –

Verwandte Themen