Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Verwenden einer Datenbanktabelle als Warteschlange

Ich würde ein IDENTITY-Feld als Primärschlüssel verwenden, um die eindeutig inkrementierende ID für jedes Element in der Warteschlange bereitzustellen, und einen gruppierten Index darauf kleben. Dies würde die Reihenfolge darstellen, in der die Elemente in die Warteschlange gestellt wurden.

Um die Elemente in der Warteschlangentabelle zu behalten, während Sie sie verarbeiten, benötigen Sie ein "Status"-Feld, um den aktuellen Status eines bestimmten Elements anzugeben (z. B. 0 =wartet, 1 =wird verarbeitet, 2 =verarbeitet). Dies ist erforderlich, um zu verhindern, dass ein Artikel zweimal verarbeitet wird.

Wenn Sie Elemente in der Warteschlange verarbeiten, müssen Sie das nächste Element in der Tabelle finden, das derzeit NICHT verarbeitet wird. Dies müsste so erfolgen, dass verhindert wird, dass mehrere Prozesse denselben Artikel gleichzeitig zur Verarbeitung aufnehmen, wie unten gezeigt. Beachten Sie die Tabellenhinweise UPDLOCK und READPAST, die Sie beim Implementieren von Warteschlangen beachten sollten.

z.B. innerhalb eines sproc etwa so:

DECLARE @NextID INTEGER

BEGIN TRANSACTION

-- Find the next queued item that is waiting to be processed
SELECT TOP 1 @NextID = ID
FROM MyQueueTable WITH (UPDLOCK, READPAST)
WHERE StateField = 0
ORDER BY ID ASC

-- if we've found one, mark it as being processed
IF @NextId IS NOT NULL
    UPDATE MyQueueTable SET Status = 1 WHERE ID = @NextId

COMMIT TRANSACTION

-- If we've got an item from the queue, return to whatever is going to process it
IF @NextId IS NOT NULL
    SELECT * FROM MyQueueTable WHERE ID = @NextID

Wenn die Verarbeitung eines Elements fehlschlägt, möchten Sie es später noch einmal versuchen? Wenn ja, müssen Sie den Status entweder auf 0 oder so zurücksetzen. Das erfordert mehr Nachdenken.

Verwenden Sie alternativ keine Datenbanktabelle als Warteschlange, sondern etwas wie MSMQ - dachte nur, ich werfe das in die Mischung!