sql >> Database >  >> RDS >> PostgreSQL

org.postgresql.util.PSQLException:FOUT:kon toegang niet serialiseren vanwege lees-/schrijfafhankelijkheden tussen transacties

Wanneer u SERIALIZABLE aanvraagt isolatie de DB zal proberen om gelijktijdige reeksen query's te laten lijken alsof ze serieel zijn uitgevoerd in termen van de resultaten die ze opleveren. Dit is niet altijd mogelijk, b.v. wanneer twee transacties wederzijdse afhankelijkheden hebben. In dit geval zal PostgreSQL een van de transacties afbreken met een fout in de serialisatiefout, die u vertelt dat u het opnieuw moet proberen.

Code die gebruikmaakt van SERIALIZABLE moet altijd bereid zijn om transacties opnieuw te proberen. Het moet de SQLSTATE . controleren en herhaal de transactie voor serialisatiefouten.

Zie de documentatie over transactie-isolatie .

In dit geval denk ik dat je grootste misvatting is dat:

aangezien het niets van dien aard is, is het een INSERT ... SELECT dat raakt vo_business.repositoryoperation voor zowel lezen als schrijven. Dat is voldoende om een ​​potentiële afhankelijkheid te creëren met een andere transactie die hetzelfde doet, of een die op een andere manier naar de tabel leest en schrijft.

Bovendien kan de serialiseerbare isolatiecode onder bepaalde omstandigheden ontaarden in het vasthouden van afhankelijkheidsinformatie op blokniveau om efficiëntieredenen. Het hoeft dus niet per se een transactie te zijn die dezelfde rijen raakt, alleen hetzelfde opslagblok, vooral onder belasting.

PostgreSQL zal een serialiseerbare transactie liever afbreken als het niet zeker is of het veilig is. Het bewijssysteem heeft beperkingen. Het is dus ook mogelijk dat je zojuist een zaak hebt gevonden die hem voor de gek houdt.

Om het zeker te weten zou ik beide transacties naast elkaar moeten zien, maar hier is een bewijs met een insert ... select kan in conflict komen met zichzelf. Open drie psql sessies en lopen:

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 zal boete doen. session2 zal mislukken met:

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.

Het is niet dezelfde serialisatiefout als uw geval, en het bewijst niet dat uw uitspraken kunnen met elkaar conflicteren, maar het laat zien dat een insert ... select is niet zo atomair als je dacht.




  1. Een PL/SQL-rijtrigger maken die een kolom uit een andere tabel valideert?

  2. MySQL relationele databases gebruiken op Fedora 12

  3. SQL-query's versus voorwaarden in PHP

  4. Hoe kan public_dependency verwijzingen bevatten naar objecten die niet in all_objects staan?