to dobry pomysł tylko wtedy, gdy nalegasz na zablokowanie określonego wiersza, co nie czego potrzebujesz. Po prostu chcesz dowolnego kwalifikacja, dostępny (odblokowany) rząd. Ważna różnica jest taka (cytując podręcznik do Postgresa 9.4):FOR UPDATE NOWAIT
Z NOWAIT
, instrukcja zgłasza błąd, zamiast czekać, jeśli wybranego wiersza nie można natychmiast zablokować.
Zapytania identyczne najprawdopodobniej będą próbowały zablokować ten sam arbitralny wybór. FOR UPDATE NOWAIT
po prostu wycofa się z wyjątkiem (który cofnie całą transakcję, chyba że złapiesz błąd) i będziesz musiał spróbować ponownie.
Rozwiązanie w mojej przywołanej odpowiedzi na dba.SE wykorzystuje kombinację zwykłego FOR UPDATE
w połączeniu z pg_try_advisory_lock()
:
pg_try_advisory_lock
jest podobny do pg_advisory_lock
, z wyjątkiem tego, że funkcja nie będzie czekać na udostępnienie blokady. Albo uzyska blokadę natychmiast i zwróci prawdę, albo zwróci fałsz, jeśli blokady nie można uzyskać natychmiast.
Więc twoja najlepsza opcja to ... trzecia alternatywa:nowy FOR UPDATE SKIP LOCKED
w Postgresie 9.5, który implementuje to samo zachowanie bez dodatkowego wywołania funkcji.
Instrukcja dla Postgresa 9.5 porównuje te dwie opcje, wyjaśniając różnicę nieco bardziej:
Aby operacja nie czekała na zatwierdzenie innych transakcji, użyj NOWAIT
lub SKIP LOCKED
opcja. Z NOWAIT
, instrukcja zgłasza błąd, zamiast czekać, jeśli wybranego wiersza nie można natychmiast zablokować. Z SKIP LOCKED
, wszystkie wybrane wiersze, których nie można natychmiast zablokować, są pomijane.
W Postgresie 9.4 lub starszym Twoja następna najlepsza opcja jest użycie pg_try_advisory_xact_lock(id)
w połączeniu z FOR UPDATE
jak pokazano w przywołanej odpowiedzi:
- AKTUALIZACJA Postgresa… LIMIT 1
(Również z implementacją z FOR UPDATE SKIP LOCKED
.)
Ściśle mówiąc, otrzymujesz arbitralne, nie do końca losowe typy. To może być ważna różnica.
Skontrolowana wersja Twojego zapytania znajduje się w mojej odpowiedzi na Twoje inne pytanie.