sql >> Database teknologi >  >> RDS >> PostgreSQL

Isolationsniveau SERIALISERBAR i Spring-JDBC

TL;DR:Registrering af serialiseringskonflikter blev dramatisk forbedret i Pg 9.1, så opgrader.

Det er svært at finde ud af din beskrivelse, hvad den faktiske SQL er, og hvorfor du forventer at få en tilbagerulning. Det ser ud til, at du alvorligt har misforstået serialiserbar isolation, måske tænker du, at den tester alle prædikater perfekt, hvilket den ikke gør, især ikke i side 8.4.

SERIALIZABLE garanterer ikke perfekt, at transaktionerne udføres, som om de blev kørt i serie - da det ville være uoverkommeligt dyrt ud fra et præstationssynspunkt, hvis det overhovedet var muligt. Det giver kun begrænset kontrol. Præcis hvad der kontrolleres og hvordan varierer fra database til database og version til version, så du skal læse dokumenterne til din version af din database.

Anomalier er mulige, hvor to transaktioner udføres i SERIALIZABLE mode giver et andet resultat, end hvis disse transaktioner virkelig udføres i serier.

Læs dokumentationen om transaktionsisolering på side for at lære mere. Bemærk, at SERIALIZABLE ændret adfærd dramatisk i Pg 9.1, så sørg for at læse den version af manualen, der passer til din Pg-version. Her er 8.4-versionen . Læs især 13.2.2.1. Serialiserbar isolation versus ægte serialiserbarhed . Sammenlign nu det med den stærkt forbedrede prædikatlåsningsbaserede serialiseringsunderstøttelse beskrevet i Side 9.1 dokumenter .

Det ser ud til, at du forsøger at udføre logik noget som denne pseudokode:

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

Hvis det er tilfældet, vil det ikke fungere i Pg 8.4, når det udføres samtidigt - det er stort set det samme som det anomalieksempel, der er brugt i dokumentationen, der er linket til ovenfor. Utroligt nok virker det faktisk på side 9.1; Jeg forventede ikke, at selv 9.1's prædikatlåsning ville fange brugen af ​​aggregater.

Du skriver at:

men 8.4 vil ikke opdage, at de to transaktioner er indbyrdes afhængige, noget du trivielt kan bevise ved at bruge to psql sessioner for at teste det. Det er kun med de sand-serialiserbare ting, der blev introduceret i 9.1, at dette vil fungere - og ærligt talt var jeg overrasket over, at det virker i 9.1.

Hvis du vil gøre noget som at håndhæve et maksimalt antal rækker i side 8.4, skal du LOCK bordet for at forhindre samtidig INSERT s, udfører låsningen enten manuelt eller via en triggerfunktion . At gøre det i en udløser vil i sagens natur kræve en låseforfremmelse og vil derfor ofte gå i dødvande, men vil med succes gøre jobbet. Det er bedre gjort i applikationen, hvor du kan udstede LOCK TABLE my_table IN EXCLUSIVE MODE før du opnår endda SELECT ing fra bordet, så den har allerede den højeste låsetilstand, den har brug for på bordet, og burde derfor ikke have brug for dødvande-tilbøjelig låsefremme. Den EXCLUSIVE låsetilstand er passende, fordi den tillader SELECT s men intet andet.

Sådan tester du det i to psql-sessioner:

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;

Når den køres på side 9.1, lykkes st commits succeeds then the second COMMIT` mislykkes med:

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.

men når de køres på 8.4 lykkes begge commits commits, fordi 8.4 ikke havde al prædikatlåsekoden til serialiserbarhed tilføjet i 9.1.




  1. PostgreSQL hvordan man sammensætter intervalværdi '2 dage'

  2. Kald til udefineret funktion oci_connect()

  3. Gemmer tidsstempel i mysql-tabel ved hjælp af php

  4. Beregn Hash eller Checksum for en tabel i SQL Server