В документа от 1995 г. Критика на нивата на изолация на ANSI SQL , Джим Грей и компания, описаха Phantom Read като:
Следователно Phantom Read не означава, че можете просто да върнете моментна снимка от началото на текущата изпълнявана транзакция и да се преструвате, че предоставянето на същия резултат за заявка ще ви предпази от действителната аномалия на Phantom Read.
В оригиналната реализация на SQL Server 2PL (двуфазно заключване) връщането на същия резултат за заявка предполага предикатни заключвания.
MVCC (Multi-Version Concurrency Control) Snapshot Isolation (погрешно наречен Serializable в Oracle) всъщност не пречи на други транзакции да вмъкват/изтриват редове, които отговарят на същите критерии за филтриране със заявка, която вече е изпълнена и е върнала набор от резултати в нашето текущо изпълнение транзакция.
Поради тази причина можем да си представим следния сценарий, при който искаме да приложим увеличение към всички служители:
- 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:
В този сценарий изпълнителният директор изпълнява първата транзакция (Tx1), така че:
- Първо проверява сбора на всички заплати в своята компания.
- Междувременно отделът по човешки ресурси извършва втората транзакция (Tx2), тъй като току-що успяха да наемат Джон Доу и му дадоха заплата от 100 000 $.
- Главният изпълнителен директор решава, че увеличението с 10% е възможно, като се вземе предвид общата сума на заплатите, без да знае, че сумата на заплатите е нараснала със 100k.
- Междувременно HR транзакцията Tx2 е ангажирана.
- Tx1 е ангажиран.
Бум! Главният изпълнителен директор е взел решение относно стара моментна снимка, давайки увеличение, което може да не се поддържа от текущия актуализиран бюджет за заплати.
Можете да видите подробно обяснение на този случай на използване (с много диаграми) в следната публикация .
Това фантомно четене ли е или Напишете наклонено ?
Според Джим Грей и ко , това е фантомно четене, тъй като изкривяването на запис се дефинира като:
В Oracle Transaction Manager може или може да не открие аномалията по-горе, защото не използва предикатни заключвания или заключвания на диапазона на индекса (заключвания на следващия ключ) , като MySQL.
PostgreSQL успява да улови тази аномалия само ако Боб издаде четене спрямо таблицата на служителите, в противен случай явлението не е предотвратено.
АКТУАЛИЗАЦИЯ
Първоначално предполагах, че сериализуемостта ще означава и времево подреждане. Въпреки това, както много добре обяснено от Peter Bailis , подреждането на стенния часовник или възможността за линеаризиране се приема само за стриктна възможност за сериализиране.
Следователно моите предположения бяха направени за система със строга сериализация. Но това не е това, което Serializable би трябвало да предлага. Сериализиращият се изолационен модел не дава гаранции относно времето и операциите могат да бъдат пренареждани, стига да са еквивалентни на някои серийно изпълнение.
Следователно, според дефиницията на Serializable, такова фантомно четене може да възникне, ако втората транзакция не издаде никакво четене. Но в модел Strict Serializable, този, предлаган от 2PL, фантомното четене ще бъде предотвратено дори ако втората транзакция не издаде четене срещу същите записи, които се опитваме да предпазим от фантомни четения.