Jaka jest różnica między odczytem niepowtarzalnym a odczytem fantomowym?

154

Jaka jest różnica między niepowtarzalnym odczytem a odczytem fantomowym?

Przeczytałem artykuł Isolation (systemy bazodanowe) z Wikipedii , ale mam kilka wątpliwości. W poniższym przykładzie, co się stanie: niepowtarzalny odczyt i odczyt fantomowy ?

Transakcja A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1
WYNIK:
1----MIKE------29019892---------5000
Transakcja B
UPDATE USERS SET amount=amount+5000 where ID=1 AND accountno=29019892;
COMMIT;
Transakcja A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1

Kolejną wątpliwością jest w powyższym przykładzie, który poziom izolacji należy zastosować? I dlaczego?

user1357722
źródło

Odpowiedzi:

165

Z Wikipedii (która ma świetne i szczegółowe przykłady):

Niepowtarzalny odczyt występuje, gdy w trakcie transakcji wiersz jest pobierany dwukrotnie, a wartości w wierszu różnią się między odczytami.

i

Odczyt fantomowy występuje, gdy w trakcie transakcji wykonywane są dwa identyczne zapytania, a zbiór wierszy zwracanych przez drugie zapytanie różni się od pierwszego.

Proste przykłady:

  • Użytkownik A uruchamia to samo zapytanie dwukrotnie.
  • W międzyczasie Użytkownik B przeprowadza transakcję i zatwierdza.
  • Niepowtarzalny odczyt: wiersz A, o który zapytał użytkownik A, ma inną wartość za drugim razem.
  • Odczyt fantomowy: wszystkie wiersze w zapytaniu mają tę samą wartość przed i po, ale wybierane są różne wiersze (ponieważ B usunął lub wstawił niektóre). Przykład: select sum(x) from table;zwróci inny wynik, nawet jeśli żaden z tych wierszy nie został zaktualizowany, jeśli wiersze zostały dodane lub usunięte.

W powyższym przykładzie, który poziom izolacji ma zostać użyty?

Wymagany poziom izolacji zależy od aplikacji. „Lepszy” poziom izolacji wiąże się z wysokimi kosztami (np. Zmniejszona współbieżność).

W twoim przykładzie nie będziesz miał odczytu fantomu, ponieważ wybierasz tylko z jednego wiersza (identyfikowanego przez klucz podstawowy). Możesz mieć niepowtarzalne odczyty, więc jeśli jest to problem, możesz chcieć mieć poziom izolacji, który temu zapobiega. W Oracle transakcja A może również wydać SELECT FOR UPDATE, wtedy transakcja B nie może zmienić wiersza, dopóki A nie zostanie zakończona.

Thilo
źródło
6
Naprawdę nie rozumiem logiki takiej składni ... Niepowtarzalny odczyt pojawia się, gdy odczyt jest powtórzony (i uzyskano inną wartość) ??! ...
serhio
14
@serhio „niepowtarzalny” odnosi się do faktu, że możesz odczytać wartość raz i otrzymać x jako wynik, a następnie przeczytać ponownie i otrzymać y jako wynik, więc nie możesz powtórzyć (niepowtarzalnego) tych samych wyników z dwóch oddzielne zapytania w tym samym wierszu, ponieważ ta wartość wiersza była aktualizowana między odczytami.
BateTech
@Thilo Każdy prawdziwy przykład użycia, w którym powtarzalny odczyt może powodować problemy i gdzie jest to konieczne?
user104309
Co się stanie, jeśli PK zostanie zmodyfikowany w innej transakcji? Czy mogłoby to spowodować odczytanie widma? (Dziwna rzecz do zrobienia w większości przypadków, ale nie niemożliwa.)
jpmc26
1
Oba brzmi dla mnie tak samo
sn.anurag
125

Prosty sposób, w jaki lubię o tym myśleć, to:

Zarówno odczyty niepowtarzalne, jak i fantomowe mają do czynienia z operacjami modyfikacji danych z innej transakcji, które zostały zatwierdzone po rozpoczęciu transakcji, a następnie odczytane przez transakcję.

Niepowtarzalne odczyty mają miejsce, gdy transakcja odczytuje zatwierdzone AKTUALIZACJE z innej transakcji. Ten sam wiersz ma teraz inne wartości niż na początku transakcji.

Phantom czyta są podobne, ale podczas czytania z zaangażowanych INSERTÓW i / lub usuwa z innej transakcji. Pojawiły się nowe wiersze lub wiersze, które zniknęły od czasu rozpoczęcia transakcji.

Brudne odczyty są podobne do odczytów niepowtarzalnych i fantomowych, ale odnoszą się do odczytywania danych NIEZGODNYCH i występują, gdy odczytywana jest AKTUALIZACJA, WSTAWIANIE lub USUWANIE z innej transakcji, a inna transakcja NIE zatwierdziła jeszcze danych. Odczytuje dane „w toku”, które mogą nie być kompletne i mogą nigdy nie zostać zatwierdzone.

BateTech
źródło
4
Ma to związek z poziomami izolacji transakcji i współbieżnością. Korzystając z domyślnego poziomu izolacji, nie uzyskasz brudnych odczytów, aw większości przypadków chcesz uniknąć brudnych odczytów. Istnieją poziomy izolacji lub wskazówki dotyczące zapytań, które pozwalają na nieczytelne odczyty, co w niektórych przypadkach jest akceptowalnym kompromisem w celu osiągnięcia wyższej współbieżności lub jest konieczne ze względu na przypadek brzegowy, taki jak rozwiązywanie problemów z trwającą transakcją z innego połączenia. Dobrze, że pomysł brudnego czytania nie przechodzi dla ciebie „testu zapachu”, bc z reguły należy ich unikać, ale mają cel.
BateTech
1
@PHPAvenger to przypadek użycia dla poziomu izolacji READ UNCOMMITTED: zawsze istnieje możliwość wystąpienia impasu między kwerendą wybierającą a kwerendą aktualizującą (wyjaśnione tutaj ). Jeśli zapytanie wybierające jest zbyt złożone, aby utworzyć indeks pokrywający, aby uniknąć zakleszczeń, będziesz chciał użyć poziomu izolacji READ UNCOMMITED z ryzykiem napotkania brudnych odczytów, ale jak często wycofujesz transakcje, aby martwić się o te brudne odczyty, nie być stałym ?!
petrica.martinescu
1
@ petrica.martinescu problemy spowodowane przez brudne odczyty NIE dotyczą tylko tego, czy transakcja jest wycofywana, czy nie. Brudne odczyty mogą zwracać bardzo niedokładne wyniki, w zależności od sposobu modyfikacji danych w transakcjach oczekujących. Wyobraź sobie transakcję, która wykonuje serię kilku operacji usuwania, aktualizacji i / lub wstawiania. Jeśli odczytujesz dane w trakcie tej transakcji za pomocą polecenia „odczyt niezatwierdzone”, jest to niekompletne. Poziom izolacji migawki (w SQL Server) jest znacznie lepszą alternatywą dla odczytu niezatwierdzonych. Prawidłowym przypadkiem użycia niezatwierdzonego poziomu izolacji odczytu w systemie produkcyjnym jest rzadka IMO.
BateTech
2
@DiponRoy świetne pytanie. Blokowanie zaimplementowane w przypadku korzystania z izolacji powtarzalnego odczytu (RR) powinno zapobiegać usuwaniu wybranych wierszy. Widziałem różne definicje 2 poziomów iso na przestrzeni lat, głównie mówiąc, że fantom to zmiana w kolekcji / # wierszy zwróconych, a RR to ten sam zmieniany wiersz. Właśnie sprawdziłem zaktualizowaną dokumentację MS SQL, która mówi, że usuwanie może powodować inne niż RR ( docs.microsoft.com/en-us/sql/odbc/reference/develop-app/ ... ), więc myślę, że byłoby bezpieczne grupowe usuwanie w kategoria RR również
BateTech
2
@anir yes wstawia i usuwa elementy w brudnych odczytach. Przykład: rozpocznij transakcję, wstaw 2 ze 100 wierszy faktury na połączeniu a, teraz połączenie b odczytuje te 2 wiersze przed zatwierdzeniem trx i przed dodaniem pozostałych 98 wierszy, więc nie zawiera wszystkich informacji dotyczących faktury. Byłby to brudny odczyt z wkładką.
BateTech
28

Jak wyjaśniono w tym artykule , anomalia Niepowtarzalnego odczytu wygląda następująco:

wprowadź opis obrazu tutaj

  1. Alicja i Bob rozpoczynają dwie transakcje w bazie danych.
  2. Robert czyta rekord wiadomości, a wartość kolumny tytułu to Transakcje.
  3. Alicja modyfikuje tytuł danego wpisu na wartość ACID.
  4. Alice zatwierdza transakcję w bazie danych.
  5. Jeśli Bob ponownie przeczyta rekord postu, zauważy inną wersję tego wiersza tabeli.

W tym artykule o Phantom Read możesz zobaczyć, że ta anomalia może się zdarzyć w następujący sposób:

wprowadź opis obrazu tutaj

  1. Alicja i Bob rozpoczynają dwie transakcje w bazie danych.
  2. Robert czyta wszystkie rekordy post_comment powiązane z wierszem postu o wartości identyfikatora 1.
  3. Alicja dodaje nowy rekord post_comment, który jest powiązany z wierszem postu o wartości identyfikatora 1.
  4. Alice zatwierdza transakcję w bazie danych.
  5. Jeśli Bob ponownie odczyta rekordy post_comment mające wartość kolumny post_id równą 1, zaobserwuje inną wersję tego zestawu wyników.

Tak więc, podczas gdy Niepowtarzalny odczyt dotyczy pojedynczego wiersza, Phantom Read dotyczy zakresu rekordów, które spełniają podane kryteria filtrowania zapytań.

Vlad Mihalcea
źródło
3
znakomita wizualizacja @Vlad
dextermini
23

Przeczytaj zjawiska

  • Brudne odczyty : przeczytaj NIEZGODNE dane z innej transakcji
  • Odczyty niepowtarzalne : odczytaj dane ZATWIERDZONE zUPDATEzapytania z innej transakcji
  • Odczyty fantomowe : odczyt ZATWIERDZONYCH danychz innej transakcjiINSERTlubDELETEzapytania z innej transakcji

Uwaga : instrukcje DELETE z innej transakcji również mają bardzo małe prawdopodobieństwo spowodowania Niepowtarzalnych odczytów w niektórych przypadkach. Dzieje się tak, gdy instrukcja DELETE powoduje niestety usunięcie tego samego wiersza, którego dotyczyła bieżąca transakcja. Jest to jednak rzadki przypadek i znacznie mniej prawdopodobne w przypadku bazy danych, która ma miliony wierszy w każdej tabeli. Tabele zawierające dane transakcyjne zwykle zawierają dużą ilość danych w dowolnym środowisku produkcyjnym.

Możemy również zauważyć, że AKTUALIZACJE mogą być częstszym zadaniem w większości przypadków użycia, a nie faktyczne WSTAWIANIE lub USUWANIE (w takich przypadkach istnieje tylko niebezpieczeństwo niepowtarzalnych odczytów - w takich przypadkach odczyty fantomowe nie są możliwe). Dlatego AKTUALIZACJE są traktowane inaczej niż INSERT-DELETE, a wynikająca z nich anomalia jest również inaczej nazywana.

Istnieje również dodatkowy koszt przetwarzania związany z obsługą operacji INSERT-DELETE, a nie tylko obsługi aktualizacji.


Korzyści z różnych poziomów izolacji

  • READ_UNCOMMITTED niczego nie zapobiega. To zerowy poziom izolacji
  • READ_COMMITTED zapobiega tylko jednemu, tj. Brudnym odczytom
  • REPEATABLE_READ zapobiega dwóm anomaliom: Brudnym odczytom i Niepowtarzalnym odczytom
  • SERIALIZABLE zapobiega wszystkim trzem anomaliom: Brudne odczyty, Niepowtarzalne odczyty i Odczyty fantomowe

Dlaczego więc nie ustawić transakcji w dowolnym momencie jako SERIALIZOWALNA? Cóż, odpowiedź na powyższe pytanie brzmi: ustawienie SERIALIZABLE powoduje, że transakcje są bardzo wolne , czego znowu nie chcemy.

W rzeczywistości zużycie czasu transakcji kształtuje się następująco:

SERIALIZABLE > REPEATABLE_READ > READ_COMMITTED > READ_UNCOMMITTED

Zatem ustawienie READ_UNCOMMITTED jest najszybsze .


Podsumowanie

Właściwie musimy przeanalizować przypadek użycia i zdecydować o poziomie izolacji, aby zoptymalizować czas transakcji, a także zapobiec większości anomalii.

Zauważ, że bazy danych domyślnie mają ustawienie REPEATABLE_READ.

Subhadeep Ray
źródło
1
AKTUALIZUJ lub USUŃ oba mogą mieć miejsce w przypadku odczytów niepowtarzalnych, czy jest to tylko AKTUALIZACJA?
Dipon Roy
1
UPDATE lub DELETE oba mogą mieć miejsce w przypadku
niepowtarzalnych
Właściwie możemy podsumować, że średnio losowa instrukcja DELETE wykonana przez inną transakcję w tej samej bazie danych ma bardzo małe prawdopodobieństwo spowodowania niepowtarzalnych odczytów dla bieżącej transakcji. Ale ta sama instrukcja usuwania ma 100% szans na spowodowanie odczytu fantomu dla bieżącej transakcji. Patrząc na to w ten sposób, moje pisanie jest trochę błędne, jeśli wziąć to słowo w słowo. Ale hej, celowo napisałem to w ten sposób, aby czytelnik był bardziej zrozumiały.
Subhadeep Ray
+1 za proste i łatwe do zrozumienia wyjaśnienie. Jednak myślę, że większość baz danych (oracle, mysql) ma domyślny poziom izolacji Read Committed i prawdopodobnie postgress używa domyślnego repetytorium
akila
7

Istnieje różnica w implementacji między tymi dwoma rodzajami poziomów izolacji.
W przypadku „niepowtarzalnego odczytu” potrzebne jest blokowanie wierszy.
Do „odczytu fantomowego” , potrzebne jest blokowanie zakresu, nawet blokowanie tabeli.
Możemy zaimplementować te dwa poziomy za pomocą protokołu blokowania dwufazowego .

egraldlo
źródło
Aby zaimplementować powtarzalny odczyt lub możliwość serializacji, nie ma potrzeby używania blokowania wierszy.
a_horse_with_no_name
5

W systemie z niepowtarzalnymi odczytami wynik drugiego zapytania Transakcji A będzie odzwierciedlał aktualizację w Transakcji B - zobaczy nową kwotę.

W systemie, który umożliwia odczyty fantomowe, jeśli Transakcja B miałaby wstawić nowy wiersz o identyfikatorze = 1, Transakcja A zobaczy nowy wiersz po wykonaniu drugiego zapytania; tj. odczyty fantomowe są szczególnym przypadkiem odczytu niepowtarzalnego.

Jeffrey Kemp
źródło
Nie sądzę, aby wyjaśnienie czytania fantomu było prawidłowe. Możesz uzyskać odczyty fantomowe, nawet jeśli dane niezatwierdzone nigdy nie są widoczne. Zobacz przykład na Wikipedii (link w komentarzach powyżej).
Thilo
1

Przyjęta odpowiedź wskazuje przede wszystkim na to, że tak zwane rozróżnienie między nimi w rzeczywistości nie jest wcale istotne.

Jeśli „wiersz jest pobierany dwukrotnie, a wartości w wierszu różnią się między odczytami”, to nie są one tym samym wierszem (nie jest to ta sama krotka w prawidłowym języku RDB) i rzeczywiście z definicji jest tak, że „zbiór wiersze zwrócone przez drugie zapytanie różnią się od pierwszego ".

Jeśli chodzi o pytanie „jaki poziom izolacji powinien być użyty”, im bardziej Twoje dane są gdzieś dla kogoś istotne, tym bardziej będzie tak, że Serializable jest jedyną rozsądną opcją.

Erwin Smout
źródło
0

Myślę, że istnieje pewna różnica między odczytem niepowtarzalnym i odczytem fantomowym.

Niepowtarzalność oznacza, że ​​istnieją transakcje holowania A i B., jeśli B może zauważyć modyfikację A, więc może się zdarzyć brudny odczyt, więc pozwalamy B zauważyć modyfikację A po zatwierdzeniu A.

Jest nowy problem: pozwalamy B zauważyć modyfikację A po zatwierdzeniu A, oznacza to, że A modyfikuje wartość wiersza, który trzyma B, kiedyś B ponownie przeczyta wiersz, więc B otrzyma nową wartość inną za pierwszym razem get, nazywamy to Niepowtarzalnym, aby poradzić sobie z problemem, pozwalamy B zapamiętać coś (bo nie wiem, co zostanie jeszcze zapamiętane), gdy B zacznie.

Pomyślmy o nowym rozwiązaniu, możemy zauważyć, że jest też nowy problem, ponieważ pozwalamy B coś zapamiętać, więc cokolwiek wydarzyło się w A, nie można wpłynąć na B, ale jeśli B chce wstawić jakieś dane do tabeli, a B sprawdź tabelę, aby upewnić się, że nie ma rekordu, ale te dane zostały wstawione przez A, więc może wystąpić jakiś błąd. Nazywamy to Phantom-read.

Han R.
źródło
0

Niepowtarzalny odczyt jest poziomem izolacji, a odczyt fantomowy (odczyt wartości zatwierdzonej przez inne transakcje) jest pojęciem (typ odczytu, np. brudny odczyt lub odczyt migawki). Niepowtarzalny poziom izolacji odczytu umożliwia odczyt fantomowy, ale nie umożliwia odczytów brudnych lub migawkowych.

sn.anurag
źródło