Dit veroorzaakt een impasse omdat de UPDATE
query vergrendelt alle rijen in de tabel, en afhankelijk van de gebruikte indexen (of het ontbreken daarvan), zullen twee verschillende sessies ze mogelijk in een iets andere volgorde vergrendelen. Onthoud dat UPDATE
, DELETE
, en SELECT ... FOR UPDATE
vergrendelt alle rijen die ze tegenkomen, ongeacht of die rijen overeenkomen met alle WHERE
voorwaarden of niet. Dus als je ze gebruikt, moet je er alles aan doen om er zeker van te zijn dat ze zo min mogelijk rijen tegenkomen, door indexen te gebruiken (idealiter de primaire sleutel) en vage of brede selectievoorwaarden te vermijden.
Mijn suggestie voor werkwachtrijen is vrijwel universeel:sluit zo min mogelijk, zo zelden mogelijk en altijd in een deterministische volgorde. Dus over het algemeen:
- Gebruik niet-vergrendelende uitlezingen (normale
SELECT
) om werk te vinden door te zoeken naar dingen die uw werknemer weet en die momenteel niet zijn opgeëist (lease_owner IS NULL AND lease_expiry IS NULL
-- of vergelijkbaar). - Kies één werkitem (of een paar als je durft, maar één is veel eenvoudiger en zorgt normaal gesproken voor perfect acceptabele prestaties).
- Update je werkitem (om het te claimen, maar in ieder geval moet het ook worden bijgewerkt):
- Open een transactie.
- Vergrendel je gekozen werkitem met
SELECT ... FOR UPDATE
-- Als het niet langer niet-opgeëist is, stop dan en kies een ander. - Update uw gekozen werkitem met uw werknemer-ID en een vervaltijd voor uw lease erop.
- Voer uw transactie onmiddellijk uit.
- Beginnen met uw geleasede werkitems.
- In een ander proces zoekt een andere poller naar verlaten werk en maakt de claim ongedaan (via hetzelfde updateproces hierboven).
U kunt gemakkelijk een zeer hoge doorvoer krijgen met dit ontwerp (duizenden taken per seconde), en met in wezen geen geschillen en geen bestelproblemen. Optimalisaties om werk te kiezen dat minder snel conflicteert met andere opiniepeilers zijn eenvoudig en effectief (bijv. modulus op Job ID of iets dergelijks, gekozen om uithongering van banen te voorkomen). De sleutel is om te onthouden dat een conflict bij de selectie van een baan oké is -- gewoon afbreken en opnieuw proberen en alles gaat heel snel verder.
Alle vergrendelingsschrijfacties voor items/taken in de werkwachtrij mogen alleen op enkele rijen worden gedaan en met primaire sleutel alleen .