Różnica między „odczytem zatwierdzonym” a „powtarzalnym odczytem”

245

Myślę, że powyższe poziomy izolacji są takie same. Czy ktoś mógłby opisać kilkoma fajnymi przykładami, jaka jest główna różnica?

Dziobowy
źródło
3
Powinieneś rozwinąć pytanie i dodać tagi do jakiego „poziomu izolacji” masz na myśli (Java, itp.). „poziom izolacji” jest dość dwuznacznym terminem i oczywiście pytasz o odpowiedź dla konkretnego środowiska.
jesus

Odpowiedzi:

564

Przeczytaj zaangażowana jest poziom izolacji, który gwarantuje, że każdy odczyt danych zostało popełnione w tej chwili jest odczytywany. To po prostu ogranicza czytelnikowi dostęp do jakiegokolwiek pośredniego, niezaangażowanego, „brudnego” odczytu. Nie daje żadnej obietnicy, że jeśli transakcja ponownie wystawi odczyt, znajdzie te same dane, dane mogą ulec zmianie po odczytaniu.

Powtarzalny odczyt to wyższy poziom izolacji, który oprócz gwarancji poziomu zatwierdzonego odczytu, gwarantuje również, że każdy odczyt danych nie może się zmienić , jeśli transakcja ponownie odczyta te same dane, znajdzie wcześniej odczytane dane w niezmienionej formie i dostępne do czytania.

Kolejny poziom izolacji, możliwy do serializacji, daje jeszcze silniejszą gwarancję: oprócz wszystkiego powtarzalne gwarancje odczytu, gwarantuje również, że żadne nowe dane nie będą widoczne podczas kolejnego odczytu.

Załóżmy, że masz tabelę T z kolumną C z jednym wierszem, powiedz, że ma wartość „1”. I rozważ, że masz proste zadanie, takie jak:

BEGIN TRANSACTION;
SELECT * FROM T;
WAITFOR DELAY '00:01:00'
SELECT * FROM T;
COMMIT;

Jest to proste zadanie, które wydaje dwa odczyty z tabeli T, z opóźnieniem 1 minuty między nimi.

  • w sekcji CZYTAJ ZOBOWIĄZANO drugi WYBÓR może zwrócić dowolne dane. Współbieżna transakcja może aktualizować rekord, usuwać go, wstawiać nowe rekordy. Drugi wybór zawsze zobaczy nowe dane.
  • w obszarze REPEATABLE READ drugi WYBÓR gwarantuje wyświetlenie przynajmniej niezmienionych wierszy, które zostały zwrócone z pierwszego WYBORU . Nowe wiersze mogą być dodawane przez jednoczesną transakcję w ciągu jednej minuty, ale istniejących wierszy nie można usunąć ani zmienić.
  • pod odczytami SERIALIZABLE drugi wybór gwarantuje zobacz dokładnie te same wiersze, co pierwszy. Żaden wiersz nie może się zmienić, ani usunięty, ani nie można wstawić nowych wierszy w ramach transakcji równoległej.

Postępując zgodnie z powyższą logiką, możesz szybko zdać sobie sprawę, że transakcje SERIALIZABLE, chociaż mogą ułatwić ci życie, zawsze całkowicie blokują każdą możliwą jednoczesną operację, ponieważ wymagają, aby nikt nie mógł modyfikować, usuwać ani wstawiać żadnego wiersza. Domyślny poziom izolacji transakcji w System.Transactionszakresie .Net można przekształcić do postaci szeregowej, co zazwyczaj tłumaczy wynikającą z tego fatalną wydajność.

I wreszcie, istnieje również poziom izolacji SNAPSHOT. Poziom izolacji SNAPSHOT zapewnia te same gwarancje, co szeregowanie, ale nie wymaga, aby żadna z równoczesnych transakcji nie mogła modyfikować danych. Zamiast tego zmusza każdego czytelnika do zobaczenia własnej wersji świata (własnej „migawki”). To sprawia, że ​​programowanie jest bardzo łatwe, a także bardzo skalowalne, ponieważ nie blokuje równoczesnych aktualizacji. Jednak ta korzyść ma swoją cenę: dodatkowe zużycie zasobów serwera.

Uzupełnienie brzmi:

Remus Rusanu
źródło
24
Wydaje mi się, że powyżej jest błąd dotyczący POWTARZANEGO ODCZYTU: Mówisz, że istniejących wierszy nie można usunąć ani zmienić, ale myślę, że można je usunąć lub zmienić, ponieważ powtarzalny odczyt po prostu odczytuje „migawkę”, a nie rzeczywiste dane. Z dokumentacji dev.mysql.com/doc/refman/5.0/en/… : „Wszystkie spójne odczyty w ramach tej samej transakcji odczytują migawkę utworzoną przy pierwszym odczycie”.
Derek Litz,
2
@Derek Litz Czy mam rację, mówiąc: dane MOGĄ / MOŻE zostać zmienione od strony trzeciej, podczas gdy transakcja ma miejsce, ale odczyty nadal będą widzieć „stare” oryginalne dane, jakby zmiana nie nastąpiła miejsce (migawka).
Programster
5
@Cornstalks. Tak, odczyty fantomowe mogą wystąpić po usunięciu (lub wstawieniu). Tak, odczyty fantomowe mogą występować w powtarzalnej izolacji odczytu (tylko z wkładek). Nie, odczyty fantomów po usunięciu nie mogą wystąpić w powtarzalnej izolacji odczytu. Sprawdź to. To, co mówię, nie jest sprzeczne z cytowaną przez ciebie dokumentacją.
AndyBrown,
4
@Cornstalks NP. Wspomniałem o tym w ogóle, ponieważ sam nie byłem w 100% pewien i musiałem głęboko zanurkować, aby mieć pewność, kto ma rację! I nie chciałem, aby przyszli czytelnicy wprowadzali w błąd. Ponownie zachowaj komentarze, prawdopodobnie najlepiej zachować zgodnie z sugestią. Jestem pewien, że każda inna osoba zainteresowana tym poziomem drobnych szczegółów będzie wystarczająco szczegółowa, aby przeczytać wszystkie komentarze !!
AndyBrown,
12
Dziękujemy, że nie usunąłeś swoich komentarzy. Dyskusja pomaga połączyć więcej kropek.
Josh
68

Powtarzalne czytanie

Stan bazy danych jest utrzymywany od początku transakcji. Jeśli pobierzesz wartość w session1, następnie zaktualizuj tę wartość w session2, odzyskanie jej ponownie w session1 zwróci te same wyniki. Odczyty są powtarzalne.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Aaron

Czytaj Zaangażowane

W kontekście transakcji zawsze będziesz pobierać ostatnio zatwierdzoną wartość. Jeśli pobierzesz wartość w session1, zaktualizujesz ją w session2, a następnie odzyskasz w session1 ponownie, otrzymasz wartość zmodyfikowaną w session2. Odczytuje ostatni zatwierdzony wiersz.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Bob

Ma sens?

Hazel_arun
źródło
Próbowałem powtarzalnego odczytu w SQL Server 2008 z „ustawieniem powtarzalnego odczytu poziomu izolacji”. Utworzono dwa okna zapytań SQL. Ale nie działało. Czemu?
Aditya Bokade,
1
Dlaczego druga sesja 1 nadal czytałaby Aarona? Czy transakcja session2 nie jest zakończona i zatwierdzona? Znam to stare, ale może ktoś może rzucić trochę światła.
Sonny Childs,
9
Myślę, że powtarzalny odczyt zablokuje drugą sesję do czasu zatwierdzenia pierwszej sesji. Więc przykład jest zły.
Nighon
4
W przypadku odczytu powtarzalnego, gdy sesja 1 odczytuje wiersz, umieszcza blokadę współdzieloną, która nie zezwala na żadną blokadę wyłączności (do sesji 2) na aktualizację, dlatego danych nie można zaktualizować.
Taher,
Myślę, że SQL Server i MySQL zachowują się inaczej, jeśli chodzi o aktualizację współdzielonych wierszy między dwiema transakcjami
user2488286
23

Po prostu odpowiedź zgodnie z moim czytaniem i zrozumieniem tego wątku, a odpowiedź @ remus-rusanu opiera się na tym prostym scenariuszu:

Istnieją dwa procesy A i B. Proces B odczytuje tabelę X Proces A zapisuje w tabeli X Proces B ponownie odczytuje tabelę X.

  • Odczyt Niezatwierdzony : Proces B może odczytać niezaangażowane dane z procesu A i może zobaczyć różne wiersze na podstawie zapisu B. W ogóle nie ma blokady
  • ReadCommitted : Proces B może odczytywać TYLKO zatwierdzone dane z procesu A i może zobaczyć różne wiersze na podstawie zapisu ZALECANEGO tylko B. czy możemy to nazwać Simple Lock?
  • RepeatableRead : Proces B odczyta te same dane (wiersze) niezależnie od tego, co robi proces A. Ale proces A może zmieniać inne wiersze. Blok poziomu wierszy
  • Serializowalny : Proces B odczyta te same wiersze co poprzednio, a Proces A nie będzie mógł odczytać ani zapisać w tabeli. Blok na poziomie stołu
  • Migawka : każdy proces ma własną kopię i nad nią pracują. Każdy ma swój własny pogląd
Mo Zaatar
źródło
15

Stare pytanie, które ma już zaakceptowaną odpowiedź, ale lubię myśleć o tych dwóch poziomach izolacji w kategoriach zmiany sposobu blokowania w SQL Server. Może to być pomocne dla tych, którzy debugują impasy jak ja.

PRZECZYTAJ ZOBOWIĄZANE (domyślnie)

Blokady współdzielone są pobierane w SELECT, a następnie zwalniane po zakończeniu instrukcji SELECT . W ten sposób system może zagwarantować, że nie wystąpią nieczytelne odczyty nieprzypisanych danych. Inne transakcje mogą nadal zmieniać wiersze bazowe po zakończeniu SELECT i przed zakończeniem transakcji.

POWTARZANE CZYTANIE

Blokady współdzielone są pobierane w SELECT, a następnie zwalniane dopiero po zakończeniu transakcji . W ten sposób system może zagwarantować, że odczytywane wartości nie zmienią się podczas transakcji (ponieważ pozostają zablokowane do czasu zakończenia transakcji).

Chris Gillum
źródło
13

Próbuję wyjaśnić tę wątpliwość za pomocą prostych schematów.

Odczyt zatwierdzony : tutaj, na tym poziomie izolacji, transakcja T1 będzie czytać zaktualizowaną wartość X zatwierdzoną przez transakcję T2.

Czytaj Zaangażowane

Powtarzalne czytanie: Na tym poziomie izolacji transakcja T1 nie będzie uwzględniać zmian dokonanych przez transakcję T2.

wprowadź opis zdjęcia tutaj

vkrishna17
źródło
1

Myślę, że to zdjęcie może być również przydatne, pomaga mi jako odniesienie, gdy chcę szybko zapamiętać różnice między poziomami izolacji (dzięki kudvenkat na youtube)

wprowadź opis zdjęcia tutaj

Ivan Pavičić
źródło
0

Należy pamiętać, że powtarzalne w powtarzalnym czytaniu dotyczy krotki, ale nie całej tabeli. Na poziomach izolacji ANSC może wystąpić anomalia odczytu fantomowego , co oznacza odczyt tabeli z tym samym, w którym klauzula dwukrotnie może zwrócić różne zestawy wyników. Dosłownie nie jest to powtarzalne .

不辞 长 做 岭南 人
źródło
-1

Moja obserwacja początkowo zaakceptowanego rozwiązania.

Pod RR (domyślny mysql) - Jeśli tx jest otwarty, a SELECT został uruchomiony, inny tx NIE może usunąć żadnego wiersza należącego do poprzedniego zestawu wyników READ, dopóki poprzednia tx nie zostanie zatwierdzona (w rzeczywistości instrukcja usuwania w nowym tx po prostu się zawiesi) , jednak następny tx może bez problemu usunąć wszystkie wiersze z tabeli. Przy okazji, następne CZYTANIE w poprzednim tx nadal będzie widzieć stare dane, dopóki nie zostanie zatwierdzone.

Sanjeev Dhiman
źródło
2
Może być konieczne umieszczenie go w sekcji komentarzy, aby odpowiadający mógł otrzymać powiadomienie. W ten sposób będzie mógł zareagować na twoje obserwacje i w razie potrzeby wprowadzić poprawki.
RBT