To způsobuje zablokování, protože UPDATE
dotaz zamyká všechny řádky v tabulce a v závislosti na použitých indexech (nebo jejich nedostatku) je dvě různé relace potenciálně uzamknou v mírně odlišném pořadí. Pamatujte, že UPDATE
, DELETE
a SELECT ... FOR UPDATE
uzamkne všechny řádky, na které narazí, bez ohledu na to, zda tyto řádky odpovídají všem WHERE
podmínky nebo ne. Při jejich používání byste se tedy měli usilovně snažit zajistit, aby se setkaly s co nejmenším počtem řádků, pomocí indexů (ideálně primárního klíče) a vyhýbání se vágním podmínkám nebo podmínkám širokého výběru.
Můj návrh pro pracovní fronty je do značné míry univerzální:Zamykejte co nejméně, pokud možno zřídka a vždy v deterministickém pořadí. Takže obecně:
- Používejte nezamykatelné čtení (běžné
SELECT
), abyste si našli práci tím, že hledejte věci, které váš pracovník umí dělat a které momentálně nejsou nárokovány (lease_owner IS NULL AND lease_expiry IS NULL
-- nebo podobně). - Vyberte jednu pracovní položku (nebo několik, pokud si troufáte, ale jedna je mnohem jednodušší a obvykle umožňuje dokonale přijatelný výkon).
- Aktualizujte svou pracovní položku (chcete-li ji nárokovat, ale v každém případě je také potřeba ji aktualizovat):
- Otevřete transakci.
- Zamkněte vybranou pracovní položku pomocí
SELECT ... FOR UPDATE
-- Pokud již není nárokován, zrušte jej a vyberte jiný. - Aktualizujte vybranou pracovní položku o své ID pracovníka a dobu vypršení platnosti vašeho pronájmu.
- Okamžitě potvrďte svou transakci.
- Začněte pracovat na pronajatých pracovních položkách.
- V některém jiném procesu jiný dotazovatel hledá opuštěné dílo a zruší jeho nárok (prostřednictvím stejného procesu aktualizace výše).
S tímto designem můžete snadno získat velmi vysokou propustnost (tisíce úloh za sekundu) a v podstatě bez sporů a problémů s objednávkou. Optimalizace pro výběr práce, u které je méně pravděpodobné, že bude v konfliktu s jinými dotazovači, jsou jednoduché a účinné (např. modul na ID úlohy nebo podobné, zvolené tak, aby nedocházelo k hladovění pracovních míst). Klíčem je zapamatovat si, že konflikt při výběru práce je v pořádku -- prostě přerušte a zkuste to znovu a vše půjde velmi rychle.
Všechny zamykací zápisy pro položky/úlohy pracovní fronty by se měly provádět pouze na jednom řádku a podle primárního klíče pouze .