Frage

Ich habe eine Bestellung Warteschlange für den Zugriff durch mehrere um-Prozessoren über eine gespeicherte Prozedur.Jeder Prozessor geht in eine einzigartige ID, die ist verwendet zu sperren die nächsten 20 Bestellungen für den eigenen Gebrauch.Die gespeicherte Prozedur gibt dann diese Datensätze in der Reihenfolge Prozessor eingewirkt werden.

Es gibt Fälle, in denen mehrere Prozessoren in der Lage, abrufen gleichen 'OrderTable' record an welcher Stelle Sie versuchen, gleichzeitig zu arbeiten auf es.Dies resultiert letztlich in Fehler ausgelöst wird, die später in die Prozess.

Meine nächste Kurs der Aktion ist es, jeden Prozessor greifen Sie alle verfügbaren Aufträge und nur round-robin-Prozessoren, aber ich hatte gehofft, einfach nur diesen code-Abschnitt, der thread-sicher und ermöglichen die Prozessoren zu packen, Aufzeichnungen, Wann immer Sie möchten.

So Ausdrücklich - keine Ahnung warum erlebe ich diese race-Bedingung, und wie ich das problem lösen kann.

BEGIN TRAN
    UPDATE  OrderTable WITH ( ROWLOCK )
    SET     ProcessorID = @PROCID
    WHERE   OrderID IN ( SELECT TOP ( 20 )
                                        OrderID
                                FROM    OrderTable WITH ( ROWLOCK )
                                WHERE   ProcessorID = 0)
COMMIT TRAN


SELECT  OrderID, ProcessorID, etc...
FROM    OrderTable
WHERE   ProcessorID = @PROCID
War es hilfreich?

Lösung

Edit:

Ich habe gegoogelt, um zu überprüfen meine Antwort: "Verarbeitung von Daten, die Warteschlangen in SQL Server mit READPAST und UPDLOCK".Es ist Jahre her, seit ich darüber gelesen, und spielte mit dieser Lösung.

Original:

Wenn Sie die READPAST-Hinweis, dann gesperrte Zeilen übersprungen werden.Die Sie verwendet haben, ROWLOCK, so sollten Sie es vermeiden, die Sperrenausweitung.Sie müssen auch UPDLOCK, wie ich herausgefunden habe.

So Verfahren 1 die Schlösser 20 Zeilen, Prozess 2 wird in den nächsten 20, der Prozess dauert 3 Zeilen 41 bis 60, etc

Das update kann auch wie folgt geschrieben werden:

UPDATE TOP (20)
    foo
SET
    ProcessorID = @PROCID
FROM
    OrderTable foo WITH (ROWLOCK, READPAST, UPDLOCK)
WHERE
    ProcessorID = 0

Aktualisierung, Oktober 2011

Dies kann gemacht werden mehr elegant mit der OUTPUT-Klausel, wenn Sie brauchen, ein und WÄHLEN Sie ein UPDATE in one go.

Andere Tipps

Sie können die Verwendung von Service Broker.Sie können auch verwenden sp_getapplock zu serialisieren Zugriff auf Ihre Zeilen - beseitigen race-Bedingungen:

"Concurrency Unterstützung von erstellen Sie Ihre eigenen Schlösser (Mutexs in SQL) " http://sqlblogcasts.com/blogs/tonyrogerson/archive/2006/06/30/855.aspx

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top