Dies verursacht einen Deadlock, weil das UPDATE
query sperrt alle Zeilen in der Tabelle, und abhängig von den verwendeten Indizes (oder deren Fehlen) sperren zwei verschiedene Sitzungen sie möglicherweise in leicht unterschiedlicher Reihenfolge. Denken Sie daran, dass UPDATE
, DELETE
, und SELECT ... FOR UPDATE
sperrt alle Zeilen, auf die sie stoßen, unabhängig davon, ob diese Zeilen mit allen WHERE
übereinstimmen Bedingungen oder nicht. Wenn Sie sie also verwenden, sollten Sie sich bemühen, sicherzustellen, dass sie auf so wenige Zeilen wie möglich stoßen, indem Sie Indizes (idealerweise den Primärschlüssel) verwenden und vage oder weitreichende Bedingungen vermeiden.
Mein Vorschlag für Arbeitswarteschlangen ist ziemlich universell:Locken Sie so wenig wie möglich, so selten wie möglich und immer in einer deterministischen Reihenfolge. Also allgemein:
- Verwenden Sie Lesevorgänge ohne Sperre (reguläres
SELECT
), um Arbeit zu finden, indem Sie nach Dingen suchen, die Ihr Mitarbeiter kann und auf die derzeit kein Anspruch erhoben wird (lease_owner IS NULL AND lease_expiry IS NULL
). -- oder ähnlich). - Wählen Sie ein Arbeitselement (oder mehrere, wenn Sie sich trauen, aber eines ist viel einfacher und ermöglicht normalerweise eine vollkommen akzeptable Leistung).
- Aktualisieren Sie Ihr Arbeitselement (um es zu beanspruchen, aber in jedem Fall muss es auch aktualisiert werden):
- Öffnen Sie eine Transaktion.
- Sperren Sie Ihr gewähltes Workitem mit
SELECT ... FOR UPDATE
-- Wenn es nicht mehr beansprucht wird, brechen Sie ab und wählen Sie ein anderes. - Aktualisieren Sie Ihr ausgewähltes Arbeitselement mit Ihrer Arbeiter-ID und einer Ablaufzeit für Ihre Lease.
- Verpflichten Sie Ihre Transaktion sofort.
- Beginnen Sie mit der Arbeit an Ihren geleasten Arbeitselementen.
- In einem anderen Prozess sucht ein anderer Poller nach aufgegebener Arbeit und hebt die Beanspruchung auf (über denselben Aktualisierungsprozess oben).
Mit diesem Design können Sie problemlos einen sehr hohen Durchsatz (Tausende von Jobs pro Sekunde) erzielen, und das im Wesentlichen ohne Konflikte und Ordnungsprobleme. Optimierungen zur Auswahl von Arbeiten, die weniger wahrscheinlich mit anderen Meinungsforschern in Konflikt geraten, sind einfach und effektiv (z. B. Modulus auf Job-ID oder ähnliches, gewählt, um ein Aushungern von Jobs zu vermeiden). Der Schlüssel ist, sich daran zu erinnern, dass Konflikte bei der Jobauswahl okay sind -- brechen Sie einfach ab und versuchen Sie es erneut, und alles geht sehr schnell voran.
Alle sperrenden Schreibvorgänge für Elemente/Jobs der Arbeitswarteschlange sollten nur für einzelne Zeilen ausgeführt werden und nach Primärschlüssel nur .