Korzyści z USTAWIONEGO POZIOMU ​​IZOLACJI PRZECZYTAJ NIEPOKONANE

12

Używam SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDw większości moich ogólnych zapytań SQL, głównie dlatego, że zostały mi one wywiercone podczas oryginalnej nauki języka.

Z mojego zrozumienia ten poziom izolacji działa w ten sam sposób, z którego WITH (NO LOCK)jednak zawsze korzystam SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.

  • Czy kiedykolwiek czas, że należy przy użyciu WITH (NO LOCK)ponad SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
  • Czy SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDpowstrzymuje innych użytkowników przed blokowaniem się w tabelach, które czytam?
  • Jeśli SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDsłuży do zatrzymywania blokad, ale czytam tylko dane, jaki jest sens ich używania? Czy to tylko zapytania systemowe wymagające wygenerowania blokad? Czy warto go używać podczas uruchamiania zapytań, które zwrócą się powiedzmy za 5-10 sekund?
  • Powiedziano mi, aby nie używać SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDpodczas odczytu danych, które zostaną wykorzystane w aktualizacjach, prawdopodobnie w celu uniknięcia aktualizacji brudnych danych. Czy to byłby jedyny powód?
  • Z typem bazy danych, nad którą pracuję, istnieje środowisko produkcyjne i testowe. Bardzo rzadko wysyłamy zapytania do środowiska produkcyjnego, ale gdy zajdzie taka potrzeba, zwykle używam SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDw moim zapytaniu. Rozumiem, że przy tym możliwe są brudne odczyty. Oprócz otrzymywania danych z powrotem, które mogą nie zostać przypisane do bazy danych (a zatem wyrzucić moje wyniki), jakie inne rodzaje „brudnych odczytów” mogą być możliwe?

Przepraszam za masowe pytania.

dmoney
źródło
2
Możesz odczytać te same dane dwa razy, to kolejny upadek. Używanie RU lub NO LOCK w standardzie to zły pomysł.
James Anderson
9
Nie używałbym READ UNCOMMITTEDwszędzie, w dokładnie taki sam sposób, jak nie używałbym WITH (NOLOCK)wszędzie (to w zasadzie ta sama rzecz) blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere
Mark Sinkinson
1
Sprawdź modele izolacji SNAPSHOT. Są znacznie silniejsze niż RCU, a także nie blokują ani nie powodują blokowania. Brzmią jak dobry domyślny model dla ciebie (zamiast domyślnego RCU!).
usr

Odpowiedzi:

26

To okropne, że nauczyłeś się tego w ten sposób (przepraszam!).

READ UNCOMMITTEDprzeczytajmy każdy wiersz, tak. Nawet ci, którzy są obecnie stosowane w INSERT, UPDATE, DELETEoperacji. Jest to bardzo przydatne, jeśli chcesz SELECTrzucić okiem na niektóre dane lub w krytycznych misjach - informacje, w których blok byłby bardzo szkodliwy.

W rzeczywistości ryzykujesz uczciwość. Może się zdarzyć, że przeczytasz wiersz, który jest obecnie używany do usunięcia lub zmiany. Może się również wydawać, że odczytałeś niewłaściwą wartość. To może być naprawdę rzadkie, ale może się zdarzyć. Co mam na myśli? Pomyśl o rzędzie, który jest bardzo szeroki (ma wiele kolumn z wieloma długimi kolumnami nvarchar). Aktualizacja występuje w tym wierszu i ustawia nowe wartości. W rzadkich przypadkach może się zdarzyć, że przeczytasz tylko pół rzędu. Inna rzecz może się zdarzyć na przykład, jeśli użytkownik zmieni swoje wartości logowania. Zmienia swoją pocztę + hasło. Poczta jest już ustawiona, ale hasło nie jest. W ten sposób masz niespójny stan.

Sugerowałbym zapomnieć o READ UNCOMMITTED. Po prostu użyj go tam, gdzie jest naprawdę potrzebny.

Inną alternatywą dla ciebie może być włączenie READ_COMMITTED_SNAPSHOTopcji bazy danych - do tego możesz użyć READ COMMITTED SNAPSHOTze względu na włączone wersjonowanie wierszy w tempdb. W ten sposób po prostu czytasz inną (starszą) wersję wiersza. To nie zablokuje twoich zapytań. Ale może się zdarzyć, że odczytasz również starą wartość, ale spójną starą wartość.

WITH(READPAST)Zamiast tego może być inny pomysł WITH(NOLOCK). Przeczytasz stary stan tabeli (trochę jak w SNAPSHOT ISOLATION), ale zamiast tego pominiesz wszystkie aktualnie zablokowane wiersze.

joński
źródło
@Ionic, dziękuję bardzo za odpowiedź! Naprawdę doceniam pomoc w tym zakresie.
dmoney,
@HingeSight, to brzmi tak, ale jest bardzo duża szansa, że ​​to była moja interpretacja tego oświadczenia, dzięki tak czy inaczej.
dmoney,
1
SNAPSHOT ISOLATIONnie musi być włączony, aby się włączyć READ COMMITTED SNAPSHOT. READ COMMITTED SNAPSHOTNależy włączyć tylko opcję bazy danych, aby wersjonowanie wierszy zamiast blokować spójność odczytu, unikając konieczności niepoprawnych odczytów.
Dan Guzman,
Tak, miałem na myśli, że @ DanGuzman. Niestety, odpowiedź była nieco niejasna. Zredagowałem to. :-)
Ionic
Dzięki READPAST pominiesz zablokowane rekordy, nie dostaniesz starych wartości - więc jedynym miejscem, które wymyśliłem, że może być wykorzystane, jest obsługa kolejek
James Z
2

Jak stwierdzono w zaakceptowanej odpowiedzi, zapomnij o używaniu poziomu izolacji ODCZYTAJ NIEDOZWOLONY (z wyjątkiem gdy jest to naprawdę potrzebne), ponieważ ryzykujesz odczytaniem niewłaściwych danych. Ale aby odpowiedzieć na trzeci punkt w twoim pytaniu, przydatne są dwie sytuacje:

  1. Podczas pisania i testowania pakietów SSIS programu SQL Server kroki pakietu mogą być zawinięte w transakcję. Jeśli testujesz pakiet, uruchamiając go krok po kroku w debuggerze SSIS, możesz sprawdzić tabele, gdy są tam blokady. Użycie USTAW POZIOMU ​​IZOLACJI ODCZYTUJE NIEZGODNE Z NIMI pozwala używać SQL Server Manager Studio do sprawdzania tabel podczas debugowania pakietu.

  2. W SQL Server Manager Studio możesz przetestować kod T-SQL, zawijając go w transakcji, aby dać Ci możliwość wycofania zmian. Na przykład w testowej bazie danych możesz chcieć przywrócić dane do stanu początkowego w ramach testu. Jeśli testujesz kod zawarty w transakcji i chcesz sprawdzić zablokowane tabele podczas trwania transakcji, możesz użyć USTAW POZIOMU ​​IZOLACJI ODCZYTAJ NIEZGODNIE, aby sprawdzić wartości w innym oknie.

Przyjmuję do wiadomości, że są to dość niejasne zastosowania dla CZYTAJ NIEZGODNE, ale uważam je za przydatne w środowisku testowym.

Ubercoder
źródło
1

W większości baz danych zdecydowana większość działań, nawet wstawianie, usuwanie i aktualizacje, nie obejmuje jawnych transakcji.

Jasne, READ UNCOMMITTED(Brudne odczyty) mogą w takich przypadkach podawać nieprawidłowe informacje, ale te informacje BYŁY prawidłowe 5 sekund wcześniej.

Czasy, w których Dirty Reads przynoszą naprawdę złe wyniki, mają miejsce, gdy transakcja kończy się niepowodzeniem i musi zostać wycofana lub podczas uruchamiania zapytania w stosunku do dwóch tabel, które są zwykle aktualizowane razem przy użyciu jawnej transakcji.

Tymczasem w typowej dużej, zajętej bazie danych, która ma stosunek odczytów do zapisów od 100 (lub więcej) do 1, KAŻDE pojedyncze zapytanie (odczyt), które nie korzysta z Dirty Reads, spowalnia system, ponieważ musi uzyskać i sprawdzić dla blokad ORAZ sprawia, że ​​znacznie bardziej prawdopodobne jest, że transakcje zakończą się niepowodzeniem (zazwyczaj z powodu zakleszczeń), co może powodować poważniejsze problemy z integralnością bazy danych.

Zamiast tego użycie brudnych odczytów sprawia, że ​​system DUŻO jest szybszy i bardziej niezawodny (częściowo ze względu na lepszą wydajność, co zmniejsza prawdopodobieństwo wystąpienia niespójności).

Jasne, są chwile, kiedy nie należy ich używać. Nie podoba mi się ustawianie domyślnej bazy danych na używanie READ UNCOMMITTEDpoziomu izolacji, a nawet używanie jawnej SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDinstrukcji na początku skryptów SQL i SP - istnieje zbyt duża szansa, że ​​nastąpi Brudne Odczyt, gdy nie powinno. Zamiast tego (NOLOCK)podpowiedzi są znacznie lepszym podejściem, ponieważ wyraźnie wskazują, że programista pomyślał o tym, co robią i zdecydował, że dla tej konkretnej tabeli w tym zapytaniu Dirty Reads są bezpieczne.

Jeśli programujesz aplikację do przesyłania pieniędzy z jednego konta bankowego na inne, nie powinieneś używać Dirty Reads. Ale większość aplikacji nie potrzebuje takiego poziomu paranoi.

Simon Holzman
źródło