Detta orsakar ett dödläge eftersom UPDATE
frågan låser alla rader i tabellen, och beroende på vilka index som används (eller brist på sådana), kommer två olika sessioner potentiellt att låsa dem i lite olika ordning. Kom ihåg att UPDATE
, DELETE
, och SELECT ... FOR UPDATE
kommer att låsa alla rader de stöter på, oavsett om dessa rader matchar alla WHERE
villkor eller inte. Så när du använder dem bör du anstränga dig för att vara säker på att de stöter på så få rader som möjligt, genom att använda index (helst den primära nyckeln) och undvika vaga eller brett urval förhållanden.
Mitt förslag på arbetsköer är ganska universellt:Lås så lite som möjligt så sällan som möjligt och alltid i en deterministisk ordning. Så generellt:
- Använd icke-låsande läsningar (vanliga
SELECT
). ) för att hitta arbete att göra genom att leta efter saker som din arbetare vet hur man gör och för närvarande inte har gjorts anspråk på (lease_owner IS NULL AND lease_expiry IS NULL
-- eller liknande). - Välj ett arbetsobjekt (eller några om du vågar, men en är mycket enklare och tillåter normalt helt acceptabel prestanda).
- Uppdatera ditt arbetsobjekt (för att göra anspråk på det, men i alla fall behöver det också uppdateras):
- Öppna en transaktion.
- Lås ditt valda arbetsobjekt med
SELECT ... FOR UPDATE
-- Om det inte längre är outnyttjat, avbryt och välj ett annat. - Uppdatera ditt valda arbetsobjekt med ditt arbetar-id och en utgångstid för ditt hyresavtal.
- Gör din transaktion omedelbart.
- Börja arbeta med dina hyrda arbetsobjekt.
- I någon annan process letar en annan pollare efter övergivet arbete och gör anspråk på det (via samma uppdateringsprocess ovan).
Du kan enkelt få mycket hög genomströmning med den här designen (tusentals jobb per sekund), och i princip utan tvister och inga beställningsproblem. Optimering för att välja arbete som är mindre benäget att komma i konflikt med andra pollare är enkla och effektiva (t.ex. modul på jobb-ID eller liknande, vald för att undvika att svälta jobb). Nyckeln är att komma ihåg att konflikter vid val av jobb är okej -- Avbryt bara och försök igen och allt går framåt väldigt snabbt.
Alla låsskrivningar för arbetsköobjekt/jobb ska endast göras på enkla rader och med primärnyckel endast .