I uppsatsen från 1995, En kritik av ANSI SQL-isoleringsnivåer , Jim Gray och co, beskrev Phantom Read som:
Därför betyder en Phantom Read inte att du helt enkelt kan returnera en ögonblicksbild från början av den pågående transaktionen och låtsas som att genom att ge samma resultat för en fråga kommer du att skydda dig mot den faktiska Phantom Read-avvikelsen.
I den ursprungliga SQL Server 2PL-implementeringen (Two-Phase Locking), returnerar samma resultat för en fråga implicerade Predicate Locks.
MVCC (Multi-Version Concurrency Control) Snapshot Isolation (felaktigt namngiven Serializable i Oracle) hindrar faktiskt inte andra transaktioner från att infoga/ta bort rader som matchar samma filtreringskriterier med en fråga som redan körts och returnerade ett resultatuppsättning i vår nuvarande körning transaktion.
Av denna anledning kan vi föreställa oss följande scenario där vi vill tillämpa en löneförhöjning för alla anställda:
- 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 det här scenariot kör VD den första transaktionen (Tx1), så:
- Hon kontrollerar först summan av alla löner i sitt företag.
- Under tiden kör HR-avdelningen den andra transaktionen (Tx2) eftersom de precis har lyckats anställa John Doe och gett honom en lön på 100 000 $.
- VD:n beslutar att en höjning på 10 % är möjlig med hänsyn till den totala lönesumman, utan att veta om att lönesumman har höjts med 100k.
- Under tiden har HR-transaktionen Tx2 genomförts.
- Tx1 är engagerad.
bom! VD:n har tagit ett beslut på en gammal ögonblicksbild, vilket ger en höjning som kanske inte kan hållas av den nuvarande uppdaterade lönebudgeten.
Du kan se en detaljerad förklaring av detta användningsfall (med många diagram) i följande inlägg .
Är detta en Phantom Read eller en Skriv skevt ?
Enligt Jim Gray och co , detta är en fantomläsning eftersom Write Skew definieras som:
I Oracle kanske transaktionshanteraren upptäcker avvikelsen ovan eftersom den inte använder predikatlås eller indexintervalllås (nästa-nyckellås) , som MySQL.
PostgreSQL lyckas fånga denna anomali endast om Bob utfärdar en läsning mot medarbetartabellen, annars förhindras inte fenomenet.
UPPDATERA
Till en början antog jag att serialiseringsbarhet också skulle innebära en tidsbeställning. Men som mycket väl förklarat av Peter Bailis , ordning på väggklockor eller linjärisering antas endast för strikt serialisering.
Därför gjordes mina antaganden för ett strikt serialiserbart system. Men det är inte vad Serializable ska erbjuda. Modellen Serialiserbar isolering ger inga garantier om tid, och operationer tillåts omordnas så länge de är likvärdiga med några seriell exekvering.
Därför, enligt den serialiserbara definitionen, kan en sådan Phantom Read inträffa om den andra transaktionen inte ger någon läsning. Men i en strikt serialiserbar modell, den som erbjuds av 2PL, skulle Phantom Read förhindras även om den andra transaktionen inte utfärdar en läsning mot samma poster som vi försöker skydda mot fantomläsningar.