Powoduje to zakleszczenie, ponieważ UPDATE
zapytanie blokuje wszystkie wiersze w tabeli i w zależności od użytych indeksów (lub ich braku) dwie różne sesje potencjalnie zablokują je w nieco innej kolejności. Pamiętaj, że UPDATE
, DELETE
i SELECT ... FOR UPDATE
zablokuje wszystkie napotkane wiersze, niezależnie od tego, czy pasują one do wszystkich WHERE
warunki, czy nie. Dlatego używając ich, powinieneś starać się, aby napotkały jak najmniej wierszy, używając indeksów (najlepiej klucza podstawowego) i unikając niejasnych lub szeroko zaznaczonych warunków.
Moja sugestia dotycząca kolejek roboczych jest dość uniwersalna:blokuj tak mało, jak to możliwe, tak rzadko, jak to możliwe i zawsze w deterministycznej kolejności. Tak więc ogólnie:
- Używaj odczytów bez blokowania (zwykłe
SELECT
), aby znaleźć pracę do zrobienia, szukając rzeczy, które Twój pracownik wie, jak robić i obecnie nie odebrano jej (lease_owner IS NULL AND lease_expiry IS NULL
-- lub podobne). - Wybierz jeden element pracy (lub kilka, jeśli się odważysz, ale jeden jest znacznie prostszy i zwykle pozwala na doskonale akceptowalną wydajność).
- Zaktualizuj swój element pracy (aby go odebrać, ale w każdym przypadku wymaga on również aktualizacji):
- Otwórz transakcję.
- Zablokuj wybrany element pracy za pomocą
SELECT ... FOR UPDATE
-- Jeśli nie jest już nieodebrany, przerwij i wybierz inny. - Zaktualizuj wybrany element pracy o swój identyfikator pracownika i czas wygaśnięcia dzierżawy.
- Zatwierdź transakcję natychmiast.
- Rozpocznij pracę nad wydzierżawionymi przedmiotami pracy.
- W innym procesie inny ankieter szuka porzuconej pracy i cofa ją (poprzez ten sam proces aktualizacji powyżej).
Dzięki temu projektowi można łatwo uzyskać bardzo wysoką przepustowość (tysiące zadań na sekundę) i zasadniczo bez rywalizacji i problemów z kolejnością. Optymalizacje w celu wybrania pracy, która jest mniej podatna na konflikty z innymi ankieterami, są proste i skuteczne (np. moduł na ID stanowiska lub podobny, wybrany, aby uniknąć głodu w pracy). Najważniejsze jest, aby pamiętać, że konflikt przy wyborze pracy jest w porządku -- po prostu przerwij i spróbuj ponownie, a wszystko potoczy się bardzo szybko.
Wszystkie blokujące zapisy dla pozycji/zadań kolejki pracy powinny być wykonywane tylko w pojedynczych wierszach i kluczem podstawowym tylko .