PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Blokady doradcze czy NOWAIT, aby uniknąć czekania na zablokowane wiersze?

FOR UPDATE NOWAIT 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):

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 .)

Na bok

Ś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.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. USUŃ KASKADOWE tylko raz

  2. PostgreSQL :rzuca ciąg do daty DD/MM/RRRR

  3. Jeśli liczba PostgreSQL(*) jest zawsze wolna, jak stronicować złożone zapytania?

  4. Zmień sortowanie bazy danych, Ctype w Postgresql

  5. Przywróć zrzut na zdalnym komputerze