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

Poziom izolacji SERIALIZABLE w Spring-JDBC

TL;DR:Wykrywanie konfliktów związanych z serializacją znacznie się poprawiło w Pg 9.1, więc uaktualnij.

Trudno jest odgadnąć na podstawie opisu, czym jest rzeczywisty kod SQL i dlaczego oczekujesz wycofania. Wygląda na to, że poważnie źle zrozumiałeś serializowalną izolację, być może myśląc, że doskonale testuje wszystkie predykaty, czego nie robi, zwłaszcza nie na stronie 8.4.

SERIALIZABLE nie gwarantuje w pełni, że transakcje są wykonywane tak, jakby były uruchamiane w serii — ponieważ byłoby to zbyt kosztowne z punktu widzenia wydajności, gdyby było to w ogóle możliwe. Zapewnia jedynie ograniczoną kontrolę. Dokładnie to, co jest sprawdzane i jak różni się w zależności od bazy danych i od wersji do wersji, więc musisz przeczytać dokumentację dla swojej wersji bazy danych.

Możliwe są anomalie, gdy dwie transakcje wykonywane w SERIALIZABLE tryb daje inny wynik niż w przypadku, gdy te transakcje są rzeczywiście wykonywane w seriach.

Przeczytaj dokumentację dotyczącą izolacji transakcji w Pg, aby dowiedzieć się więcej. Zauważ, że SERIALIZABLE drastycznie zmieniło się zachowanie w Pg 9.1, więc upewnij się, że przeczytałeś wersję podręcznika odpowiednią dla twojej wersji Pg. Oto wersja 8.4 . W szczególności przeczytaj 13.2.2.1. Serializowalna izolacja a prawdziwa serializowalność . Teraz porównaj to ze znacznie ulepszoną obsługą serializacji opartej na blokowaniu predykatów opisaną w Strona 9.1 dokumenty .

Wygląda na to, że próbujesz wykonać logikę podobną do tego pseudokodu:

count = query("SELECT count(*) FROM the_table");
if (count < threshold):
    query("INSERT INTO the_table (...) VALUES (...)");

Jeśli tak, to nie zadziała to w Pg 8.4, gdy zostanie uruchomione jednocześnie - jest to prawie to samo, co przykład anomalii użyty w dokumentacji połączonej powyżej. Zadziwiające, że faktycznie działa na stronie 9.1; Nie spodziewałem się, że nawet blokowanie predykatów w wersji 9.1 przechwyci użycie agregatów.

Piszesz, że:

ale 8.4 nie wykryje, że te dwie transakcje są współzależne, co można łatwo udowodnić, używając dwóch psql sesje, aby to przetestować. To zadziała tylko z rzeczywistą możliwością serializacji w wersji 9.1 – i szczerze mówiąc, byłem zaskoczony, że działa w wersji 9.1.

Jeśli chcesz zrobić coś takiego jak wymuszenie maksymalnej liczby wierszy na stronie 8.4, musisz LOCK stół aby zapobiec równoczesnemu INSERT s, wykonując blokowanie ręcznie lub za pomocą funkcji wyzwalacza . Wykonanie tego w wyzwalaczu będzie z natury wymagało promocji blokady, a zatem często spowoduje zakleszczenie, ale z powodzeniem wykona zadanie. Lepiej to zrobić w aplikacji, w której można wydać LOCK TABLE my_table IN EXCLUSIVE MODE przed uzyskaniem nawet SELECT z tabeli, więc ma już najwyższy tryb blokady, jakiego będzie potrzebował na stole, a zatem nie powinien potrzebować promocji blokady podatnej na zakleszczenia. EXCLUSIVE tryb blokady jest odpowiedni, ponieważ pozwala na SELECT s, ale nic więcej.

Oto jak przetestować go w dwóch sesjach psql:

SESSION 1                               SESSION 2

create table ser_test( x text );

BEGIN TRANSACTION 
ISOLATION LEVEL SERIALIZABLE;


                                        BEGIN TRANSACTION 
                                        ISOLATION LEVEL SERIALIZABLE;

SELECT count(*) FROM ser_test ;

                                        SELECT count(*) FROM ser_test ;

INSERT INTO ser_test(x) VALUES ('bob');


                                        INSERT INTO ser_test(x) VALUES ('bob');

 COMMIT;

                                        COMMIT;

Po uruchomieniu na stronie 9.1, st commits succeeds then the second COMMIT` kończy się niepowodzeniem z:

regress=# COMMIT;
ERROR:  could not serialize access due to read/write dependencies among transactions
DETAIL:  Reason code: Canceled on identification as a pivot, during commit attempt.
HINT:  The transaction might succeed if retried.

ale po uruchomieniu w wersji 8.4 oba zatwierdzenia powiodły się, ponieważ w wersji 8.4 nie dodano całego kodu blokującego predykat dla serializacji w wersji 9.1.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. jaka jest użyteczność typu tablica?

  2. Znajdowanie kombinacji określonych wartości

  3. Utwórz listę wszystkich dni w miesiącu i podziel wartość równo na każdy dzień

  4. wartość jest za długa, aby zmienić znak typu (N)

  5. Kto ma jakieś dokumenty dotyczące procesów w tle PostgreSQL?