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

Błąd w mechanizmie blokowania PostgreSQL lub niezrozumienie mechanizmu

Nie ma błędu i nie sądzę, że niczego nie rozumiesz; brakuje Ci tylko kilku elementów układanki.

Klucze obce są implementowane wewnętrznie przy użyciu blokowania na poziomie wiersza; począwszy od Postgres 8.1 do 9.2, za każdym razem, gdy aktualizujesz tabelę referencyjną (apples w tym przypadku), uruchamiane jest zapytanie, które wykonuje SELECT FOR SHARE w tabeli odniesienia (trees ). Aby SELECT FOR UPDATE w pierwszej transakcji blokuje SELECT FOR SHARE integralności referencyjnej dla drugiej transakcji. To właśnie powoduje blokadę w drugim poleceniu.

Teraz słyszę, jak krzyczysz:„Czekaj! Jak to się dzieje, że blokuje się przy drugim poleceniu, a nie przy pierwszym? Wyjaśnienie jest naprawdę proste -- to tylko dlatego, że istnieje prosta optymalizacja, która pomija wewnętrzne SELECT FOR SHARE gdy klucz nie jest modyfikowany. Jest to jednak uproszczone, ponieważ jeśli zaktualizujesz krotkę po raz drugi, ta optymalizacja nie zostanie uruchomiona, ponieważ trudniej jest wyśledzić oryginalne wartości. Stąd blokada.

Możesz się również zastanawiać, dlaczego powiedziałem, że to jest do wersji 9.2 --- co jest z wersją 9.3? Główna różnica polega na tym, że w wersji 9.3 używa SELECT FOR KEY SHARE , czyli nowy, lżejszy poziom blokady; pozwala na lepszą współbieżność. Jeśli wypróbujesz swój przykład w wersji 9.3, a także zmienisz SELECT FOR UPDATE do SELECT FOR NO KEY UPDATE (który jest lżejszym trybem niż SELECT FOR UPDATE oznacza to, że być może zamierzasz zaktualizować krotkę, ale obiecujesz nie modyfikować klucza podstawowego i obiecujesz go nie usuwać), powinieneś zobaczyć, że nie blokuje się. (Możesz też spróbować UPDATE w wierszu, do którego istnieje odwołanie, a jeśli nie zmodyfikujesz klucza podstawowego, również nie zostanie on zablokowany.)

Te rzeczy w wersji 9.3 zostały wprowadzone przez twoją łatkę jako http://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=0ac5ad5134f2769ccbaefec73844f8504c4d6182 i myślę, że to był całkiem fajny hack (wiadomość o zatwierdzeniu zawiera więcej szczegółów, jeśli zależy ci na tego typu rzeczach). Ale uważaj, nie używaj wersji wcześniejszych niż 9.3.4, ponieważ ta poprawka była tak bardzo złożona, że ​​kilka poważnych błędów pozostało niezauważonych, a naprawiliśmy je dopiero niedawno.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Nazwa tabeli jako parametr funkcji PostgreSQL

  2. Wypełnij tablicę wielowymiarową

  3. Rekurencyjne wyzwanie zapytania - prosty przykład nadrzędny/podrzędny

  4. Amazon RDS dla alternatyw dla PostgreSQL — ClusterControl dla PostgreSQL

  5. Jak pobrać kolumnę Postgres bytea jako plik?