I papiret fra 1995, En kritik af ANSI SQL-isolationsniveauer , Jim Gray og co, beskrev Phantom Read som:
Derfor betyder en Phantom Read ikke, at du blot kan returnere et øjebliksbillede fra starten af den aktuelt kørende transaktion og foregive, at det at give det samme resultat for en forespørgsel vil beskytte dig mod den faktiske Phantom Read-anomali.
I den originale SQL Server 2PL-implementering (Two-Phase Locking) returnerede det samme resultat for en forespørgsel, der implicerede prædikatlåse.
MVCC (Multi-Version Concurrency Control) Snapshot Isolation (forkert navngivet Serializable i Oracle) forhindrer faktisk ikke andre transaktioner i at indsætte/slette rækker, der matcher de samme filtreringskriterier med en forespørgsel, der allerede er udført og returneret et resultatsæt i vores nuværende kørsel transaktion.
Af denne grund kan vi forestille os følgende scenarie, hvor vi ønsker at anvende en lønforhøjelse til alle medarbejdere:
- Tx1:
SELECT SUM(salary) FROM employee where company_id = 1;
- Tx2:
INSERT INTO employee (id, name, company_id, salary) VALUES (100, 'John Doe', 1, 100000);
- Tx1:
UPDATE employee SET salary = salary * 1.1;
- Tx2:
COMMIT;
- Tx1:
COMMIT:
I dette scenarie kører den administrerende direktør den første transaktion (Tx1), så:
- Hun tjekker først summen af alle lønninger i sin virksomhed.
- I mellemtiden kører HR-afdelingen den anden transaktion (Tx2), da de lige har formået at ansætte John Doe og gav ham en løn på 100.000 $.
- Den administrerende direktør beslutter, at en forhøjelse på 10 % er mulig under hensyntagen til den samlede lønsum, idet han er uvidende om, at lønsummen er steget med 100.000.
- I mellemtiden er HR-transaktionen Tx2 forpligtet.
- Tx1 er forpligtet.
Bom! Den administrerende direktør har truffet en beslutning på et gammelt øjebliksbillede, hvilket giver en forhøjelse, der muligvis ikke kan holdes af det aktuelle opdaterede lønbudget.
Du kan se en detaljeret forklaring af denne anvendelse (med mange diagrammer) i følgende indlæg .
Er dette en Phantom Read eller en Skriv skævt ?
Ifølge Jim Gray og co , dette er en Phantom Read, da Write Skew er defineret som:
I Oracle vil Transaction Manager muligvis eller måske ikke opdage anomalien ovenfor, fordi den ikke bruger prædikatlåse eller indeksområdelåse (next-key-låse) , ligesom MySQL.
PostgreSQL formår kun at fange denne anomali, hvis Bob udsender en læsning mod medarbejdertabellen, ellers forhindres fænomenet ikke.
OPDATERING
I starten antog jeg, at serialisering også ville indebære en tidsbestilling. Men som meget godt forklaret af Peter Bailis , vægursbestilling eller lineariserbarhed antages kun for Strict Serializability.
Derfor blev mine antagelser lavet for et strengt serialiserbart system. Men det er ikke, hvad Serializable skal tilbyde. Den serialiserede isolationsmodel giver ingen garantier for tid, og operationer må omarrangeres, så længe de svarer til nogle seriel udførelse.
Derfor kan en sådan Phantom Read ifølge Serializable-definitionen forekomme, hvis den anden transaktion ikke udsteder nogen read. Men i en Strict Serializable-model, den, der tilbydes af 2PL, ville Phantom Read blive forhindret, selvom den anden transaktion ikke udsender en læsning mod de samme poster, som vi forsøger at beskytte mod phantom reads.