Odczyty brudne, niepowtarzalne i fantomowe
Trzy anomalie odczytu i poziom izolacji, który zapobiega każdej z nich.
Odczyty brudne, niepowtarzalne i fantomowe to bezpłatna lekcja SQL Interview Prep na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej SQL Interview Prep, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs SQL Interview Prep zawiera 4 lekcji w sumie.
Trzy anomalie odczytu
Poziomy izolacji mają zapobiegać określonym błędom współbieżności nazywanym anomaliami odczytu. Podczas rozmowy rekrutacyjnej oczekuje się precyzyjnego zdefiniowania wszystkich trzech anomalii i przypisania każdej z nich do poziomu, który jej zapobiega.
- Brudny odczyt - odczyt niezatwierdzonych danych
- Niepowtarzalny odczyt - wiersz zmienia się między dwoma odczytami
- Odczyt fantomowy - między dwoma odczytami pojawiają się nowe wiersze
Trudność polega na odróżnieniu odczytu niepowtarzalnego od fantomowego, ponieważ w obu przypadkach ponowne wykonanie zapytania zwraca inne wyniki.
Brudny odczyt: definicja
Brudny odczyt występuje, gdy transakcja T1 odczytuje wiersz zmodyfikowany przez transakcję T2, ale jeszcze przez nią niezatwierdzony. Jeśli T2 następnie wycofa zmiany, T1 podjęła decyzję na podstawie danych, które w rzeczywistości nigdy nie istniały.
Tylko READ UNCOMMITTED pozwala na brudne odczyty. Każdy wyższy poziom ich zabrania.
Rzeczywiste zagrożenie: zatwierdzenie pożyczki na podstawie wpłaty, która kilka sekund później zostaje wycofana.
Brudny odczyt: oś czasu
Proszę czytać obie kolumny jako oś czasu. T1 działa na poziomie READ UNCOMMITTED.
T1 widzi saldo 700, ale T2 nigdy nie zatwierdza transakcji. Wartość 700 była chwilową wartością wynikającą z niezatwierdzonej pracy T2. Po wycofaniu T2 rzeczywista wartość nadal wynosi 500. T1 podjęła decyzję na podstawie błędnych danych.
-- T2 (not committed) | -- T1 (READ UNCOMMITTED)
BEGIN; |
UPDATE accounts |
SET balance = 700 |
WHERE id = 1; |
| SELECT balance FROM accounts
| WHERE id = 1; -- reads 700 (dirty!)
ROLLBACK; |
| -- T1 acted on a value that never existedNiepowtarzalny odczyt: definicja
Niepowtarzalny odczyt występuje, gdy T1 odczytuje wiersz, T2 zatwierdza aktualizację lub usunięcie tego samego wiersza, a następnie T1 odczytuje go ponownie i widzi inną wartość.
Proszę zwrócić uwagę na kluczową różnicę względem brudnego odczytu: w tym przypadku T2 zatwierdziła transakcję. Dane są prawidłowe, ale w obrębie jednej transakcji zmieniły się w trakcie działania T1.
READ COMMITTED nadal dopuszcza taką sytuację. REPEATABLE READ i wyższe poziomy jej zapobiegają, odczytując dane ze stabilnej migawki.
Niepowtarzalny odczyt: oś czasu
T1 działa na poziomie READ COMMITTED i dwukrotnie odczytuje ten sam wiersz. Między odczytami T2 zatwierdza zmianę.
Ten sam klucz główny zwraca w obrębie jednej transakcji dwie różne wartości. Taka niespójność może zepsuć logikę wieloetapową, która zakłada, że wiersz pozostaje niezmienny.
-- T1 (READ COMMITTED) | -- T2
BEGIN; |
SELECT balance FROM accounts |
WHERE id = 1; -- 500 |
| BEGIN;
| UPDATE accounts SET balance = 900
| WHERE id = 1;
| COMMIT;
SELECT balance FROM accounts |
WHERE id = 1; -- 900 (changed!) |
COMMIT; |Odczyt fantomowy: definicja
Odczyt fantomowy występuje, gdy T1 wykonuje zapytanie z warunkiem wyszukiwania, T2 zatwierdza operację INSERT (lub DELETE) dotyczącą wierszy spełniających ten warunek, a T1 ponownie wykonuje zapytanie i otrzymuje inny zbiór wierszy.
Różnica względem odczytu niepowtarzalnego polega na tym, że odczyt niepowtarzalny dotyczy zmiany wartości istniejącego wiersza, a fantom dotyczy zmiany liczby wierszy spełniających predykat.
Według standardu tylko SERIALIZABLE gwarantuje zapobieganie odczytom fantomowym.
Odczyt fantomowy: oś czasu
T1 dwukrotnie zlicza konta o wysokiej wartości. Między tymi operacjami T2 wstawia nowy pasujący wiersz i zatwierdza transakcję.
Żaden istniejący wiersz się nie zmienił, a mimo to wynik COUNT jest inny. Nowy wiersz jest „fantomem”, który pojawił się w zbiorze wyników T1.
-- T1 (REPEATABLE READ, standard) | -- T2
BEGIN; |
SELECT COUNT(*) FROM accounts |
WHERE balance > 1000; -- 3 |
| INSERT INTO accounts(id, balance)
| VALUES (99, 5000);
| COMMIT;
SELECT COUNT(*) FROM accounts |
WHERE balance > 1000; -- 4 (phantom)|
COMMIT; |Przyporządkowanie anomalii do poziomów
To przyporządkowanie stanowi sedno tego tematu. Najniższy poziom, który zapobiega każdej anomalii:
- Brudny odczyt jest blokowany od poziomu
READ COMMITTEDwzwyż. - Niepowtarzalny odczyt jest blokowany od poziomu
REPEATABLE READwzwyż. - Odczyt fantomowy jest blokowany przez
SERIALIZABLE(zgodnie ze standardem).
Proszę zauważyć, że nazwy są trafne: REPEATABLE READ zapewnia powtarzalność odczytów, a poziomy nazwano od anomalii, którym zapobiegają.
Niepowtarzalny a fantomowy: wyraźne rozróżnienie
To najczęstsze nieporozumienie podczas rozmów rekrutacyjnych. Proszę zapamiętać jedno zdanie:
Niepowtarzalny odczyt = zmieniła się wartość istniejącego wiersza. Odczyt fantomowy = zmienił się zbiór pasujących wierszy (wiersze zostały dodane lub usunięte).
Proszę się sprawdzić: T2 wykonuje UPDATE ... WHERE id = 5, a następnie zatwierdza transakcję, po czym T1 ponownie odczytuje wiersz 5. To odczyt niepowtarzalny. T2 wykonuje INSERT nowego wiersza pasującego do klauzuli WHERE użytej przez T1, a T1 ponownie wykonuje zapytanie. To odczyt fantomowy.
Write skew: dodatkowa anomalia
Podczas rozmów rekrutacyjnych na stanowiska seniorskie można spotkać się także z wykraczającą poza trzy standardowe anomalie anomalią write skew: dwie transakcje odczytują częściowo wspólny zbiór danych, na podstawie odczytanych informacji wykonują rozłączne zapisy, a następnie obie zatwierdzają transakcję, pozostawiając stan, na który żadna z nich nie pozwoliłaby sobie samodzielnie.
Klasyczny przykład: dwóch lekarzy pełni dyżur; każdy sprawdza, że inny lekarz pełni dyżur, a następnie sam schodzi z dyżuru. Obie operacje kończą się powodzeniem, pozostawiając brak jakiejkolwiek obsady.
Izolacja migawkowa (Postgres REPEATABLE READ) dopuszcza anomalię write skew; powstrzymuje ją dopiero SERIALIZABLE. Wspomnienie o tym pokazuje szerokie zrozumienie tematu.
Utracona aktualizacja: czwarta pułapka
Podczas rozmów rekrutacyjnych czasami pojawia się utracona aktualizacja, która nie należy do standardowej listy anomalii, ale w praktyce występuje bardzo często. Dwie transakcje odczytują tę samą wartość, na jej podstawie obliczają nową wartość, a następnie obie ją zapisują. Drugi zapis po cichu nadpisuje pierwszy.
Przykład: dwa przelewy odczytują saldo 500, odejmują odpowiednie kwoty, a następnie zapisują obliczone wyniki. Jedno odejmowanie zostaje utracone.
Rozwiązaniem nie jest wyłącznie wyższy poziom izolacji, lecz także jawne blokowanie za pomocą SELECT ... FOR UPDATE albo atomowa aktualizacja, która wykonuje obliczenia w bazie, a nie w aplikacji.
-- Safe pattern: lock the row, or compute atomically
BEGIN;
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE; -- locks row
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;
-- Or simply: UPDATE accounts SET balance = balance - 100 WHERE id = 1;Szybki test
Proszę zidentyfikować anomalię na podstawie jej działania.
Podsumowanie: anomalie i sposoby ich eliminacji
Trzy anomalie odczytu, którym zapobiegają wyższe poziomy izolacji:
- Brudny odczyt (niezatwierdzone dane) - eliminowany na poziomie READ COMMITTED.
- Niepowtarzalny odczyt (zmiana wartości istniejącego wiersza) - eliminowany na poziomie REPEATABLE READ.
- Odczyt fantomowy (zmiana zbioru pasujących wierszy) - eliminowany na poziomie SERIALIZABLE.
Proszę zachować wyraźne rozróżnienie między odczytem niepowtarzalnym a fantomowym i wspomnieć o write skew, jeśli rozmówca oczekuje bardziej zaawansowanej odpowiedzi. Następnie przyjrzymy się temu, jak silniki baz danych faktycznie zapewniają izolację: blokadom, zakleszczeniom i MVCC.
Często zadawane pytania
Czy lekcja „Odczyty brudne, niepowtarzalne i fantomowe” jest bezpłatna?
Tak — pełny tekst „Odczyty brudne, niepowtarzalne i fantomowe” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu SQL Interview Prep, przejdź na CoddyKit PRO. Kurs SQL Interview Prep zawiera 4 lekcji w sumie.
Co nauczysz się w „Odczyty brudne, niepowtarzalne i fantomowe”?
Trzy anomalie odczytu i poziom izolacji, który zapobiega każdej z nich. Ćwiczysz SQL Interview Prep z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć SQL Interview Prep?
Nie wymagamy żadnego doświadczenia. SQL Interview Prep w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „Odczyty brudne, niepowtarzalne i fantomowe”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji SQL Interview Prep?
Tak. Każda lekcja SQL Interview Prep zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Wyjaśnienie właściwości ACID
- Cztery poziomy izolacji
- Odczyty brudne, niepowtarzalne i fantomowe
- Zakleszczenia, blokady i MVCC