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

org.postgresql.util.PSQLException:ГРЕШКА:не можа да сериализира достъпа поради зависимости за четене/запис между транзакциите

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

Код, който използва SERIALIZABLE трябва винаги да са готови да опитат отново транзакции. Трябва да провери SQLSTATE и при неуспешна сериализация повторете транзакцията.

Вижте документацията за изолиране на транзакция .

В този случай мисля, че основното ви погрешно разбиране може да е следното:

тъй като не е нищо подобно, това е INSERT ... SELECT който докосва vo_business.repositoryoperation както за четене, така и за писане. Това е напълно достатъчно, за да създадете потенциална зависимост с друга транзакция, която прави същото, или такава, която чете и записва в таблицата по друг начин.

Освен това сериализуемият изолационен код може при определени обстоятелства да се дегенерира в съхраняване на информация за зависимост на ниво блок от съображения за ефективност. Така че може да не е непременно транзакция, засягаща същите редове, само същия блок за съхранение, особено при натоварване.

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

За да знам със сигурност, ще трябва да видя двете транзакции една до друга, но ето доказателство, показващо insert ... select може да влезе в конфликт със себе си. Отворете три psql сесии и стартирайте:

session0: CREATE TABLE serialdemo(x integer, y integer);

session0: BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

session0: LOCK TABLE serialdemo IN ACCESS EXCLUSIVE MODE;

session1: BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

session2: BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

session1: INSERT INTO serialdemo (x, y)
          SELECT 1, 2
          WHERE NOT EXISTS (SELECT 1 FROM serialdemo WHERE x = 1);

session2: INSERT INTO serialdemo (x, y)
          SELECT 1, 2
          WHERE NOT EXISTS (SELECT 1 FROM serialdemo WHERE x = 1);

session0: ROLLBACK;

session1: COMMIT;

session2: COMMIT;

session1 ще се ангажира добре. session2 ще се провали с:

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.

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




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Драйверът JDBC postgresql не е намерен в проекта на Android

  2. План за изпълнение на функции в PostgreSQL

  3. Psycopg2 форматиране на низове с имена на променливи за създаване на тип

  4. Postgres:Преобразуване на varchar в текст

  5. Експортиране на таблица от база данни на Postgres (на сървър) в csv файл (на локален) в java