Dlaczego warto korzystać z ODCZYTU NIEPOPRAWNEGO poziomu izolacji?

225

Mówiąc wprost, jakie są wady i zalety korzystania

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

w zapytaniu dotyczącym aplikacji .NET i aplikacji usług raportowania?

Kip Real
źródło

Odpowiedzi:

210

Ten poziom izolacji umożliwia brudne odczyty. Jedna transakcja może powodować niezatwierdzone zmiany wprowadzone przez inną transakcję.

Aby utrzymać najwyższy poziom izolacji, DBMS zwykle nabywa blokady danych, co może skutkować utratą współbieżności i wysokim kosztem blokowania. Ten poziom izolacji rozluźnia tę właściwość.

Możesz zajrzeć do artykułu w Wikipedii naREAD UNCOMMITTED kilka przykładów i dalsze czytanie.


Być może zainteresuje Cię również artykuł na blogu Jeffa Atwooda, w jaki sposób on i jego zespół rozwiązali problem impasu we wczesnych dniach przepełnienia stosu. Według Jeffa:

Ale czy jest nolockniebezpieczny? Czy możesz w końcu czytać nieprawidłowe dane z read uncommittedwłączonym? Tak, teoretycznie. Nie zabraknie astronautów architektury baz danych, którzy zaczynają zrzucać na ciebie wiedzę na temat ACID, a jedynie uruchamiają alarm przeciwpożarowy budynku, gdy mówisz im, że chcesz spróbować nolock. To prawda: teoria jest przerażająca. Ale oto, co myślę: „W teorii nie ma różnicy między teorią a praktyką. W praktyce jest”.

Nigdy nie zalecałbym używania nolock jako ogólnego rozwiązania problemów z zakleszczeniem bazy danych „dobra na jakie dolegliwości”. Najpierw spróbuj zdiagnozować źródło problemu.

Ale w praktyce dodawanie nolockzapytań, które absolutnie znasz, jest proste, proste sprawy tylko do odczytu nigdy nie prowadzą do problemów ... O ile wiesz, co robisz.

Jedną z alternatyw dla READ UNCOMMITTEDpoziomu, którą możesz rozważyć, jest READ COMMITTED SNAPSHOT. Cytując ponownie Jeffa:

Migawki opierają się na zupełnie nowej metodzie śledzenia zmian danych ... więcej niż tylko niewielkiej logicznej zmianie, wymaga to od serwera fizycznego przetwarzania danych. Po włączeniu tej nowej metody śledzenia zmiany danych tworzy kopię lub migawkę każdej zmiany danych. Dzięki odczytywaniu tych migawek zamiast bieżących danych w czasach rywalizacji, Udostępniane blokady nie są już potrzebne do odczytu, a ogólna wydajność bazy danych może wzrosnąć.

Daniel Vassallo
źródło
13
Autor zdaje się sugerować, że odczyt niezaangażowany / brak blokady zwróci dane, które zostały ostatnio popełnione. Moje zrozumienie jest przeczytane, że niezaangażowane zwróci wartość ostatnio ustawioną, nawet z niezaangażowanych transakcji. Jeśli tak, wynikiem nie będzie pobieranie danych „kilka sekund nieaktualnych”. Byłoby to (lub przynajmniej mogłoby, gdyby transakcja, która zapisała odczytane dane, została wycofana), pobierałaby dane, które nie istnieją lub nigdy nie zostały popełnione. Czy się mylę?
xr280xr
4
Świetna odpowiedź. BTW, Oracle ma domyślnie „migawkę”, ponieważ ją znam, prawdopodobnie kilkadziesiąt lat przed wprowadzeniem jej przez Sql Server. Byłem dość rozczarowany, kiedy zaczynałem od SQL Servera i odkryłem, że wszystkie problemy dotyczące współbieżności zostały rozwiązane przy użyciu „prymitywnych” mechanizmów blokujących. Nigdy nie widziałem „Przeczytaj niezaangażowane” w Oracle. A praktykujący są tak szczęśliwi jak astronauci.
Stefan Steinegger,
13
READ UNCOMMITTEDmoże również spowodować dwukrotne czytanie wierszy lub pominięcie całych wierszy . Jeśli podczas czytania nastąpi podział strony, możesz przeoczyć całe fragmenty danych. WITH(NOLOCK)należy stosować tylko wtedy, gdy dokładność wyników nie jest ważna
Ian Boyd
8
@DanielNolan, Polecanie tego artykułu jest niebezpieczne, ponieważ Jeff nie wiedział, co robi . Polecenie tylko do odczytu ma sens, ponieważ odczyt danych nigdy nie będzie modyfikowany. Próba użycia tego do odczytu tabel, do których zostałyby zapisane, oznacza, że w praktyce przeczytasz coś, co zostanie przywrócone. Nie chodzi tylko o to, że czytasz dane sprzed kilku sekund, ale .................................. ................... ‌ ‌ ........................... ....
Pacerier,
5
................................... czyta dane, które nigdy nawet dostaje popełnione. To jest właśnie definicja zepsutych odczytów. A jeśli zamierzasz pisać na podstawie wyników tych niezaangażowanych odczytów, w praktyce będziesz zapisywać uszkodzone dane. Również w artykule stwierdzono, że „MySQL, który wyrósł na aplikacjach internetowych, jest znacznie mniej pesymistyczny od samego początku niż SQL Server”. Nieprawda, Sql Server domyślnie działa na poziomie zatwierdzonym do odczytu , podczas gdy MySQL działa domyślnie na powtarzalnym czytaniu , pięć poziomów od odczytu niezaangażowanego.
Pacerier,
36

Może to być przydatne do śledzenia postępu długich zapytań o wstawianie, dokonywania przybliżonych oszacowań (podobnych COUNT(*)lub przybliżonych SUM(*)) itp.

Innymi słowy, wyniki zwracane przez brudne zapytania odczytu są w porządku, o ile traktujesz je jako szacunki i nie podejmujesz na ich podstawie żadnych krytycznych decyzji.

Quassnoi
źródło
36

Moim ulubionym przykładem użycia read uncommitedjest debugowanie czegoś, co dzieje się w transakcji.

Uruchom oprogramowanie za pomocą debugera, a gdy przechodzisz przez linie kodu, otwiera transakcję i modyfikuje bazę danych. Gdy kod jest zatrzymany, możesz otworzyć analizator zapytań, ustawić na odczytywanym niezaangażowanym poziomie izolacji i wykonać zapytania, aby zobaczyć, co się dzieje.

Możesz go również użyć, aby sprawdzić, czy długotrwałe procedury nie działają lub poprawnie aktualizują bazę danych.

To wspaniałe, jeśli Twoja firma uwielbia tworzyć zbyt złożone procedury przechowywane.

Neves
źródło
6
Moja firma uwielbia tworzyć zbyt skomplikowane procedury składowane. Cóż za świetny pomysł na rozwiązywanie problemów!
Brandon
22

Zaletą jest to, że w niektórych sytuacjach może być szybszy. Wadą jest to, że wynik może być niepoprawny (dane, które nie zostały jeszcze zatwierdzone, mogą zostać zwrócone) i nie ma gwarancji, że wynik będzie powtarzalny.

Jeśli zależy Ci na dokładności, nie używaj tego.

Więcej informacji znajduje się na MSDN :

Implementuje blokowanie odczytu lub blokowania na poziomie izolacji 0, co oznacza, że ​​nie są wydawane żadne blokady współdzielone i żadne blokady wyłączne nie są honorowane. Po ustawieniu tej opcji można odczytać nieprzypisane lub brudne dane; wartości w danych można zmieniać, a wiersze mogą pojawiać się lub znikać w zestawie danych przed końcem transakcji. Ta opcja ma taki sam efekt jak ustawienie NOLOCK na wszystkich tabelach we wszystkich instrukcjach SELECT w transakcji. Jest to najmniej restrykcyjny z czterech poziomów izolacji.

Mark Byers
źródło
Jak wpłynie to na szybkość zapytania?
Kip Real
11
@Kip - selectwyciągi nie musiałyby czekać na uzyskanie wspólnych blokad zasobów, które są blokowane wyłącznie przez inne transakcje.
Jarrod Dixon
15

Kiedy można używać READ UNCOMMITTED?

Praktyczna zasada

Dobrze : duże raporty zbiorcze pokazujące stale zmieniające się sumy.

Ryzykowne : prawie wszystko inne.

Dobra wiadomość jest taka, że ​​większość raportów tylko do odczytu należy do kategorii Dobra .

Więcej szczegółów...

Ok, aby go użyć:

  • Prawie wszystkie zagregowane raporty zorientowane na użytkownika dla bieżących, niestatycznych danych, np. Sprzedaż od początku roku. Grozi to marginesem błędu (może <0,1%), który jest znacznie niższy niż w przypadku innych czynników niepewności, takich jak błąd wprowadzania lub po prostu losowość, kiedy dokładnie dane są rejestrowane z minuty na minutę.

Dotyczy to prawdopodobnie większości tego, co zrobiłby dział Business Intelligence w, powiedzmy, SSRS. Wyjątkiem jest oczywiście wszystko ze znakami $ przed nim. Wiele osób rozlicza się z pieniędzmi z większym zapałem niż w odniesieniu do powiązanych podstawowych wskaźników wymaganych do obsługi klienta i generowania tych pieniędzy. (Obwiniam księgowych).

Kiedy ryzykowne

  • Każdy raport, który schodzi do poziomu szczegółowości. Jeśli ten szczegół jest wymagany, zwykle oznacza to, że każdy wiersz będzie odpowiedni dla decyzji. W rzeczywistości, jeśli nie możesz wyciągnąć małego podzbioru bez blokowania, może to być dobry powód, dla którego jest on aktualnie edytowany.

  • Dane historyczne. Rzadko robi to praktyczną różnicę, ale chociaż użytkownicy rozumieją, że ciągle zmieniające się dane nie mogą być idealne, nie czują tego samego w przypadku danych statycznych. Brudne odczyty nie zaszkodzą tutaj, ale czasami zdarzają się podwójne odczyty. Ponieważ i tak nie powinieneś mieć blokad danych statycznych, po co ryzykować?

  • Prawie wszystko, co karmi aplikację, która ma również możliwości zapisu.

Gdy nawet scenariusz OK jest nieprawidłowy.

  • Czy jakieś aplikacje lub procesy aktualizacji wykorzystują duże pojedyncze transakcje? Te, które usuwają, a następnie ponownie wstawiają wiele rekordów, o których piszesz? W takim przypadku naprawdę nie możesz użyć NOLOCKna tych stołach do niczego.
Adamantish
źródło
Dobra uwaga na temat raportów. Właściwie pierwszym pomysłem, jaki przyszedł mi do głowy, było to, że powinienem używać read uncommittedaplikacji internetowych, gdy użytkownik widzi siatkę interfejsu użytkownika, w której dokładność danych nie jest tak ważna. Użytkownik chce tylko szybkiego przeglądu, jakie rekordy mogą tam być, a może z jakimś stronicowaniem, sortowaniem i filtrowaniem. Tylko wtedy, gdy użytkownik kliknie przycisk Edytuj, próbuję odczytać najnowszy rekord z bardziej ścisłym poziomem izolacji. Czy takie podejście nie powinno być lepsze pod względem wydajności?
JustAMartin
Tak, myślę, że to rozsądne. Pamiętaj, że bardziej znaczącym problemem jest upewnienie się, że dane nie zostały zmienione przez kogoś innego między momentem naciśnięcia przycisku edycji a czasem przesłania. Możesz sobie z tym poradzić, rozpoczynając transakcję pobierania danych takich jak select item from things with (UPDLOCK). Umieść tam krótki limit czasu, aby jeśli nie mógł szybko uzyskać blokady, informuje użytkownika, że ​​jest edytowany. To zapewni bezpieczeństwo nie tylko użytkownikom, ale także programistom. Jedynym problemem jest to, że musisz zacząć myśleć o limitach czasu i tym, jak sobie z tym poradzić w interfejsie użytkownika.
Adamantish
6

Jeśli chodzi o raportowanie, używamy go we wszystkich naszych zapytaniach dotyczących raportowania, aby zapobiec zapchaniu się baz danych. Możemy to zrobić, ponieważ pobieramy dane historyczne, a nie dane z mikrosekund.

Hugh Seagraves
źródło
4

Użyj READ_UNCOMMITTED w sytuacji, gdy zmiana źródła prawdopodobnie nie ulegnie zmianie.

  • Podczas czytania danych historycznych. np. niektóre dzienniki wdrażania, które miały miejsce dwa dni temu.
  • Podczas ponownego czytania metadanych. np. aplikacja oparta na metadanych.

Nie używaj READ_UNCOMMITTED, jeśli wiesz, że sos może się zmienić podczas operacji pobierania.

neo
źródło
1
Czuję, że jest odwrotnie. Po pierwsze, dane statyczne powinny być odczytywane bez bloków. Jeśli to nie zablokuje to masz teraz odkryto tam ważnym problemem transakcja wiszące do naprawienia. Również użytkownicy będą oczekiwać, że dopasuje to do ostatniego miejsca po przecinku, niezależnie od tego, co wydrukowali w zeszłorocznym raporcie rocznym. Na ogół nie oczekują tego samego od raportów, o których wiedzą, że są w ciągłym przepływie. Nie dotyczy to szczegółowej, wyjątkowo czasowej lub finansowej sprawozdawczości, ale jeśli 1 błąd wprowadzania na 1000 jest dopuszczalny, to tak jest READ UNCOMMITTED.
Adamantish
TLDR: Jeśli dane się nie zmienią, nie musisz CZYTAĆ NIEZGODNE, ponieważ i tak nie ma żadnych bloków. Jeśli się mylisz i to się zmienia, to dobrze, że zablokowałeś użytkownikom uzyskanie brudniejszych danych, niż się spodziewano.
Adamantish
Tak, zgadzam się z @Adamantish tutaj - możesz READ UNCOMMITTEDnajwięcej skorzystać w sytuacjach, gdy twoje dane są aktywnie wykorzystywane i chcesz zmniejszyć obciążenie serwera, aby uniknąć możliwych impasów i wycofania transakcji tylko dlatego, że niektórzy użytkownicy nieostrożnie nadużywają „ Odśwież ”na stronie internetowej z datagrid. Użytkownicy, którzy przeglądają wiele rekordów jednocześnie, zwykle nie dbają o to, czy dane są nieco nieaktualne lub częściowo zaktualizowane. Tylko wtedy, gdy użytkownik ma zamiar edytować rekord, możesz podać mu najdokładniejsze dane.
JustAMartin
2

Zapewni to brudne odczyty i pokaże transakcje, które nie zostały jeszcze zatwierdzone. To najbardziej oczywista odpowiedź. Nie sądzę, że dobrym pomysłem jest użycie tego do przyspieszenia czytania. Istnieją inne sposoby na to, jeśli korzystasz z dobrego projektu bazy danych.

Interesujące jest również odnotowanie, co się nie dzieje. READ UNCOMMITTED nie tylko ignoruje inne blokady tabeli. Nie powoduje również żadnych blokad.

Rozważ wygenerowanie dużego raportu lub migrację danych ze swojej bazy danych za pomocą dużej i prawdopodobnie złożonej instrukcji SELECT. Spowoduje to udostępnienie blokady, która może zostać eskalowana do blokady tabeli wspólnej na czas trwania transakcji. Inne transakcje mogą czytać z tabeli, ale aktualizacje są niemożliwe. Może to być zły pomysł, jeśli jest to produkcyjna baza danych, ponieważ produkcja może zostać całkowicie zatrzymana.

Jeśli używasz CZYTAJ NIEZGODNIE, nie ustawisz blokady wspólnej na stole. Możesz uzyskać wynik z niektórych nowych transakcji lub możesz nie zależeć od tego, w której tabeli zostały wstawione dane i jak długo odczytała Twoja transakcja SELECT. Możesz również uzyskać te same dane dwa razy, jeśli na przykład nastąpi podział strony (dane zostaną skopiowane do innej lokalizacji w pliku danych).

Tak więc, jeśli jest to bardzo ważne dla Ciebie, że dane można wstawić podczas wykonywania WYBORU, CZYTAJ NIEZGODNE może mieć sens. Musisz wziąć pod uwagę, że twój raport może zawierać pewne błędy, ale jeśli jest oparty na milionach wierszy i tylko kilka z nich jest aktualizowanych przy wyborze wyniku, może to być „wystarczająco dobre”. Twoja transakcja może również zawieść razem, ponieważ unikalność wiersza może nie być gwarantowana.

Lepszym sposobem może być użycie POZIOMU ​​IZOLACJI SNAPSHOT, ale aplikacje mogą wymagać pewnych modyfikacji, aby z niego skorzystać. Jednym z przykładów jest sytuacja, gdy aplikacja blokuje wiersz w wyłącznym trybie, aby uniemożliwić innym odczytanie go i przejście do trybu edycji w interfejsie użytkownika. POZIOM IZOLACJI SNAPSHOTA wiąże się również ze znacznym spadkiem wydajności (szczególnie na dysku). Ale możesz temu zaradzić, rzucając sprzęt na problem. :)

Możesz także rozważyć przywrócenie kopii zapasowej bazy danych do użycia w celu raportowania lub ładowania danych do hurtowni danych.

Olle Johansson
źródło
0

Można go użyć do prostej tabeli, na przykład w tabeli kontrolnej tylko do wstawiania, w której nie ma aktualizacji do istniejącego wiersza ani fk do innej tabeli. Wkładka jest prostą wkładką, która nie ma lub ma małe szanse na wycofanie.

Sofian
źródło
-7

Teraz zawsze używam CZYTAJ NIEPOPOWIEDZIALNIE. Jest szybki z najmniejszymi problemami. Podczas korzystania z innych izolacji prawie zawsze natrafisz na problemy z blokowaniem.

Tak długo, jak korzystasz z pól Auto Increment i poświęcasz trochę więcej uwagi wstawkom niż grzywnie, możesz pożegnać się z problemami z blokowaniem.

Możesz popełniać błędy za pomocą READ UNCOMMITED, ale szczerze mówiąc, bardzo łatwo jest upewnić się, że twoje płytki są w pełni odporne. Wstawki / Aktualizacje, które wykorzystują wyniki z wybranych, są tylko rzeczą, na którą musisz uważać. (Użyj tutaj READ COMMITTED lub upewnij się, że brudne odczyty nie spowodują problemu)

Więc idź do Dirty Reads (specjalnie dla dużych raportów), twoje oprogramowanie będzie działało płynniej ...

Clive
źródło
6
Jest to bardzo niedokładne i dotyka tylko powierzchni problemów, które mogą wystąpić w przypadku nolocka. Strony mogą się dzielić, łączenia mogą się nie powieść, możesz odczytać nieistniejące dane lub zduplikować dane. Nie ma sposobu, aby uczynić jego użycie niezawodnym: nie można ufać dokładności czegokolwiek na tym poziomie izolacji. PRZECZYTAJ ZAANGAŻOWANY SNAPSHOT jest mniej niebezpiecznym „fałszywym panaceum”
Mark Sowul
@MarkSowul Głosowanie w dół tej odpowiedzi wydaje mi się niesprawiedliwe. @Clive wyraźnie wiedział, że przełączy się Committedna wstawki i aktualizacje. Jeśli chodzi o inne problemy, wykazał także świadomość problemów związanych z dzieleniem stron, wspominając o użyciu klucza automatycznego zwiększania. Zgadzam się z nim, że prawie wszystkie relacje na żywo, które czytają tylko ludzie, mogą tolerować niewielkie rozbieżności w miejscu po przecinku. Zgadzam się, że to inna historia dla szczegółowych list lub danych przeznaczonych do odczytu maszynowego i przekształcenia, podobnie jak Clive.
Adamantish
1
Ten komentarz pokazuje również brak pełnego zrozumienia możliwych problemów związanych z nolock. „Nieznaczne rozbieżności w końcowym miejscu po przecinku” ledwo to obejmuje. Nawet dotknięcie „po prostu użyj odczytu zatwierdzonego dla wstawień / aktualizacji” jest błędne jako ogólna rada (co jeśli to „wstaw rekord, jeśli nie istnieje”?). W każdym razie „[czytaj niezaangażowane] jest szybkie z najmniejszymi problemami” jest kategorycznie błędne.
Mark Sowul,
Dla przypomnienia, zgadzam się z twoją odpowiedzią, Adamantish: z grubsza dokładne agregacje i niewiele więcej.
Mark Sowul,