PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Ниво на изолация SERIALIZABLE в Spring-JDBC

TL;DR:Откриването на конфликти за сериализиране се подобри драстично в Pg 9.1, така че надстройте.

Трудно е да разберете от вашето описание какъв е действителният SQL и защо очаквате да получите връщане назад. Изглежда, че сте разбрали сериозно погрешно сериализируемата изолация, може би смятайки, че тества перфектно всички предикати, което не е така, особено не в Pg 8.4.

SERIALIZABLE не гарантира напълно, че транзакциите се изпълняват така, сякаш се изпълняват последователно - тъй като това би било прекалено скъпо от гледна точка на производителността, ако изобщо беше възможно. Предоставя само ограничена проверка. Какво точно се проверява и как варира от база данни до база данни и версия до версия, така че трябва да прочетете документите за вашата версия на вашата база данни.

Възможни са аномалии, когато две транзакции се изпълняват в SERIALIZABLE режим дава различен резултат от този, ако тези транзакции наистина са изпълнени в серия.

Прочетете документацията за изолиране на транзакции в Pg, за да научите повече. Обърнете внимание, че SERIALIZABLE промени драматично поведението в Pg 9.1, така че не забравяйте да прочетете версията на ръководството, подходяща за вашата версия на Pg. Ето версията 8.4 . По-специално прочетете 13.2.2.1. Сериализираща се изолация срещу истинска сериализируемост . Сега сравнете това със значително подобрената поддръжка за сериализация, базирана на заключване на предикат, описана в Страница 9.1 документи .

Изглежда, че се опитвате да изпълните логически нещо подобно на този псевдокод:

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

Ако е така, това няма да работи в Pg 8.4, когато се изпълнява едновременно - това е почти същото като примера за аномалия, използван в документацията, свързана по-горе. Удивително, той действително работи на Pg 9.1; Не очаквах дори предикатното заключване на 9.1 да хване използването на агрегати.

Вие пишете, че:

но 8.4 няма да открие, че двете транзакции са взаимозависими, нещо, което можете тривиално да докажете, като използвате два psql сесии, за да го тествате. Само с нещата за истинска сериализация, въведени в 9.1, това ще работи - и честно казано, бях изненадан, че работи в 9.1.

Ако искате да направите нещо като налагане на максимален брой редове в Pg 8.4, трябва да LOCK таблицата за предотвратяване на едновременно INSERT s, извършвайки заключването ръчно или чрез функция за задействане . Правенето му в тригер по своята същност ще изисква промоция на заключване и по този начин често ще блокира, но ще свърши успешно работата. По-добре е да го направите в приложението, където можете да издадете LOCK TABLE my_table IN EXCLUSIVE MODE преди да получите дори SELECT от масата, така че вече има най-високия режим на заключване, от който ще се нуждае на масата, и по този начин не трябва да се нуждае от насърчаване на заключване, склонно към блокиране. EXCLUSIVE режимът на заключване е подходящ, защото позволява SELECT но нищо друго.

Ето как да го тествате в две 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;

Когато се изпълнява на Pg 9.1, st commits succeeds then the second COMMIT` се проваля с:

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.

но когато се изпълнява на 8.4, и двата ангажимента са успешни, тъй като 8.4 няма целия код за заключване на предикат за възможност за сериализиране, добавен в 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. SQL тригерна функция за АКТУАЛИЗИРАНЕ на дневна подвижна средна стойност при INSERT

  2. Postgresql:ФАТАЛНО:ролята не съществува

  3. Съхранявайте резултата от заявката на PostgreSQL в Shell или променлива на PostgreSQL

  4. pgadmin4 инструментът за заявки винаги се връща без връзка

  5. Неуспешно удостоверяване на паролата за postgres контейнера на Docker