sql >> Databasteknik >  >> RDS >> PostgreSQL

Isolationsnivå SERIALISERBAR i Spring-JDBC

TL;DR:Detektering av serialiseringskonflikter förbättrades dramatiskt i Pg 9.1, så uppgradera.

Det är svårt att utifrån din beskrivning ta reda på vad den faktiska SQL är och varför du förväntar dig att få en återställning. Det verkar som att du allvarligt har missförstått serialiserbar isolering, kanske tror att den testar alla predikat perfekt, vilket den inte gör, särskilt inte i sidan 8.4.

SERIALIZABLE garanterar inte perfekt att transaktionerna utförs som om de kördes i serie - eftersom det skulle vara oöverkomligt dyrt ur prestationssynpunkt om det alls var möjligt. Det ger bara begränsad kontroll. Exakt vad som kontrolleras och hur varierar från databas till databas och version till version, så du måste läsa dokumenten för din version av din databas.

Avvikelser är möjliga, där två transaktioner utförs i SERIALIZABLE läge ger ett annat resultat än om dessa transaktioner verkligen utförs i serie.

Läs dokumentationen om transaktionsisolering på sidan för att lära dig mer. Observera att SERIALIZABLE ändrat beteende dramatiskt i Pg 9.1, så se till att läsa den version av manualen som är lämplig för din Pg-version. Här är 8.4-versionen . Läs särskilt 13.2.2.1. Serialiserbar isolering kontra sann serialiseringsbarhet . Jämför nu det med det kraftigt förbättrade predikatlåsningsbaserade serialiseringsstödet som beskrivs i Sida 9.1 dokument .

Det ser ut som att du försöker utföra logik ungefär som denna pseudokod:

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

Om så är fallet, kommer det inte att fungera i sidan 8.4 när det körs samtidigt - det är i stort sett detsamma som anomaliexemplet som används i dokumentationen länkad ovan. Otroligt nog fungerar det faktiskt på sidan 9.1; Jag förväntade mig inte ens 9.1:s predikatlåsning för att fånga användningen av aggregat.

Du skriver att:

men 8.4 kommer inte att upptäcka att de två transaktionerna är beroende av varandra, något som du trivialt kan bevisa genom att använda två psql sessioner för att testa det. Det är bara med grejer som är sanna serialiserbara som introducerades i 9.1 som detta kommer att fungera - och ärligt talat, jag blev förvånad över att det fungerar i 9.1.

Om du vill göra något som att genomdriva ett maximalt antal rader i sidan 8.4, måste du LOCK bordet för att förhindra samtidig INSERT s, gör låsningen antingen manuellt eller via en triggerfunktion . Att göra det i en trigger kommer i sig att kräva en låskampanj och kommer därför ofta att låsa sig, men kommer att lyckas med jobbet. Det är bättre gjort i programmet där du kan utfärda LOCK TABLE my_table IN EXCLUSIVE MODE innan du får ens SELECT från bordet, så den har redan det högsta låsläget den behöver på bordet och borde därför inte behöva främja låsning som är utsatt för dödläge. EXCLUSIVE låsläget är lämpligt eftersom det tillåter SELECT s men inget annat.

Så här testar du det i två 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örs på sidan 9.1, lyckas st commits succeeds then the second COMMIT` misslyckas 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örs på 8.4 lyckas båda commits commits, eftersom 8.4 inte hade alla predikatlåskoder för serialiserbarhet tillagda i 9.1.




  1. Upptar kolumnerna char / varchar / text / longtext i MySQL full storlek i filsystemet även för delvis fyllda celler?

  2. Kan jag köra vilket program som helst utanför mysql genom mysql-utlösare?

  3. Hur vet jag om en databas är av hög kvalitet?

  4. Spårar höga CLR_MANUAL_EVENT-väntningar