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

Błąd zakleszczenia w instrukcji INSERT

Jednym ze sposobów radzenia sobie z zakleszczeniami jest posiadanie mechanizmu ponawiania prób, który czeka na losowy interwał i próbuje ponownie uruchomić transakcję. Losowy interwał jest niezbędny, aby kolidujące transakcje nie ciągle wpadały na siebie, powodując tak zwaną blokadę na żywo - coś jeszcze bardziej nieprzyjemnego do debugowania. W rzeczywistości większość złożonych aplikacji prędzej czy później będzie potrzebować takiego mechanizmu ponawiania prób, gdy będą musiały obsłużyć błędy serializacji transakcji.

Oczywiście, jeśli jesteś w stanie określić przyczynę zakleszczenia, zwykle lepiej jest ją wyeliminować, bo będzie wróć, żeby cię ugryźć. W prawie wszystkich przypadkach, nawet gdy stan zakleszczenia jest rzadki, warto odrobina przepustowości i narzutu na kodowanie, aby uzyskać blokady w deterministycznej kolejności lub uzyskać bardziej gruboziarniste blokady, aby uniknąć sporadycznych dużych opóźnień i nagłego urwiska wydajności podczas skalowania współbieżności.

Gdy konsekwentnie otrzymujesz zakleszczenie dwóch instrukcji INSERT, jest to najprawdopodobniej problem z unikatową kolejnością wstawiania indeksu. Wypróbuj na przykład następujące polecenie w dwóch oknach poleceń psql:

Thread A           | Thread B
BEGIN;             | BEGIN;
                   | INSERT uniq=1;
INSERT uniq=2;     | 
                   | INSERT uniq=2; 
                   |   block waiting for thread A to commit or rollback, to
                   |   see if this is an unique key error.
INSERT uniq=1;     |
   blocks waiting  |
   for thread B,   |
     DEADLOCK      | 
                   V    

Zwykle najlepszym sposobem rozwiązania tego problemu jest ustalenie obiektów nadrzędnych, które strzegą wszystkich takich transakcji. Większość aplikacji ma jedną lub dwie podstawowe jednostki, takie jak użytkownicy lub konta, które są do tego dobrymi kandydatami. Wtedy wszystko, czego potrzebujesz, to dla każdej transakcji uzyskanie blokad na podstawową jednostkę, której dotyka, za pomocą opcji WYBIERZ ... DO AKTUALIZACJI. Lub jeśli dotknie kilku, załóż blokady na wszystkie, ale za każdym razem w tej samej kolejności (kolejność według klucza podstawowego to dobry wybór).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak uzyskać dostęp do wewnętrznego indeksu tablicy za pomocą postgreSQL?

  2. Zarządzanie kolejnym Commitfestem PostgreSQL

  3. ON DELETE SET NULL w postgresie

  4. Generowanie danych i jakość sprzętu

  5. jak przenieść tabele z publicznych do innych schematów w Postgres