Co to jest „with (nolock)” w SQL Server?

610

Czy ktoś może wyjaśnić konsekwencje używania with (nolock)zapytań, kiedy powinieneś / nie powinieneś ich używać?

Na przykład, jeśli masz aplikację bankową z dużymi szybkościami transakcji i dużą ilością danych w niektórych tabelach, w jakich typach zapytań nolock byłby w porządku? Czy są przypadki, w których powinieneś zawsze go używać / nigdy nie używać?

Andy White
źródło
Podpisałem w stackoverflow.com/questions/3836282/... i stackoverflow.com/questions/3836032/... głównie Jonathan Allen odpowiedział stackoverflow.com/questions/686724/…
Gennady Vanin Геннадий Ванин
1
jeden link tutaj - mssqltips.com/sqlservertip/2470/…
Steam
1
Oto doskonałe podsumowanie implikacji korzystania z NOLOCK blogs.msdn.com/b/davidlean/archive/2009/04/06/…
Bryan

Odpowiedzi:

461

Z (NOLOCK) jest odpowiednikiem użycia CZYTAJ UNCOMMITED jako poziom izolacji transakcji. Ryzykujesz więc odczytaniem nieprzydzielonego wiersza, który jest następnie wycofywany, tj. Danych, które nigdy nie trafiły do ​​bazy danych. Tak więc, chociaż może zapobiec zakleszczeniu odczytów przez inne operacje, wiąże się z tym ryzyko. W aplikacji bankowej o wysokich stawkach transakcyjnych prawdopodobnie nie będzie to właściwe rozwiązanie problemu, który próbujesz rozwiązać za pomocą IMHO.

David M.
źródło
156
Większość aplikacji bankowych może bezpiecznie korzystać z nolock, ponieważ są transakcyjne w sensie biznesowym. Piszesz tylko nowe wiersze, nigdy ich nie aktualizujesz.
Jonathan Allen
49
@ Grauenwolf- Wstawiony, ale niezaangażowany wiersz może nadal prowadzić do brudnych odczytów.
saasman
16
@ Saasman - Jeśli nigdy nie wycofasz transakcji, to nie ma znaczenia. A przy stole tylko z wkładką szanse na wycofanie są niewielkie. A jeśli tak się stanie, nadal to wszystko naprawisz w raporcie odchyleń na koniec dnia.
Jonathan Allen
1
Jestem zakorzeniony. Zakładam, że dodano wskazówki dotyczące braku blokady. Na przykład:
Ross Bush,
11
Jeśli używasz NOLOCKz, SELECTistnieje ryzyko zwrócenia tych samych wierszy więcej niż raz (zduplikowane dane), jeśli dane zostaną kiedykolwiek wstawione (lub zaktualizowane) do tabeli podczas dokonywania wyboru.
Ian Boyd,
170

Pytanie jest gorsze:

  • impas lub
  • zła wartość?

W przypadku finansowych baz danych impasy są znacznie gorsze niż złe wartości. Wiem, że to brzmi wstecz, ale wysłuchaj mnie. Tradycyjnym przykładem transakcji DB jest aktualizacja dwóch wierszy, odejmowanie od jednego i dodawanie do drugiego. To jest złe.

W finansowej bazie danych korzystasz z transakcji biznesowych. Oznacza to dodanie jednego wiersza do każdego konta. Bardzo ważne jest, aby transakcje te zostały zakończone, a wiersze zostały pomyślnie zapisane.

Tymczasowe zebranie salda konta nie jest wielką sprawą, po to właśnie służy uzgadnianie na koniec dnia. A przekroczenie salda na rachunku jest znacznie bardziej prawdopodobne, ponieważ używane są dwa bankomaty naraz, niż z powodu niezaangażowanego odczytu z bazy danych.

To powiedziawszy, SQL Server 2005 naprawił większość NOLOCKniezbędnych błędów . Więc jeśli nie używasz SQL Server 2000 lub wcześniejszego, nie powinieneś go potrzebować.

Dalsza lektura
Wersje na poziomie wierszy

Jonathan Allen
źródło
22
Uzyskiwanie tymczasowo nieprawidłowego salda na koncie nie jest wielką sprawą? Co jeśli ta transakcja jest tą, w której pobierasz gotówkę z bankomatu bez limitu debetowego?
Nauka
13
@Learning: Co się stanie, jeśli wyjmiesz pieniądze 30 sekund, zanim ktoś obciąży twoją kartę? Dopóki wszelka komunikacja nie będzie natychmiastowa, przekroczenie stanu konta będzie faktem.
Jonathan Allen
6
+1 W aplikacji finansowej (wszędzie, nie tylko w bankach), nie ma aktualizacji ani usuwania. Nawet nieprawidłowe operacje są korygowane przez wstawienie rekordów. Co to jest po angielsku? Czy to „storno”? Google nie pomogło mi odpowiedzieć na to pytanie
Gennady Vanin Геннадий Ванин
7
Późne wejście ... zakleszczenia należy złapać i spróbować ponownie. Brudne czytanie ma konsekwencje
gbn
4
@JonathanAllen po prostu fyi, termin jest najwyższy, a nie w górę.
Jimmy D
57

Niestety nie chodzi tylko o odczytanie nieprzekazanych danych. W tle możesz skończyć czytać strony dwukrotnie (w przypadku podziału strony) lub możesz całkowicie pominąć strony. Twoje wyniki mogą być rażąco wypaczone.

Sprawdź artykuł Itzika Ben-Gana . Oto fragment:

„Dzięki podpowiedzi NOLOCK (lub ustawieniu poziomu izolacji sesji na CZYTANIE NIEZGODNE) mówisz SQL Serverowi, że nie oczekujesz spójności, więc nie ma żadnych gwarancji. Pamiętaj jednak, że„ niespójne dane ”nie tylko oznaczają, że możesz zobaczyć niezatwierdzone zmiany, które zostały później wycofane, lub zmiany danych w pośrednim stanie transakcji. Oznacza to również, że w prostym zapytaniu, które skanuje wszystkie dane tabeli / indeksu, SQL Server może utracić pozycję skanowania lub może się to skończyć uzyskanie tego samego wiersza dwa razy . ”

sqlbelle
źródło
5
Nieco dalej wyjaśnia, jak uzyskać ten sam wiersz dwa razy: Odtworzę tabelę T1 tak, aby indeks klastrowany na col1 został zdefiniowany jako unikalny indeks z opcją IGNORE_DUP_KEY. Oznacza to, że zduplikowane wartości nie mogą istnieć w kolumnie 1, a także, że próba wstawienia duplikatu klucza nie zawiedzie transakcji i wygeneruje błąd, a jedynie wygeneruje ostrzeżenie. Jeśli nie użyjesz tej dziwnej opcji, prawdopodobnie nie będziesz musiał martwić się o dwa razy wiersze
JanHudecek
Nadal możesz uzyskać duplikaty wierszy, nawet bez opcji przewodowej - jeśli twoje zapytanie wykorzystuje na przykład indeks, który nie jest unikalny. Jednak nie jest to unikalne dla nolock.
RMD
54

Przykładem podręcznika do prawidłowego użycia podpowiedzi nolock jest próbkowanie raportu w bazie danych OLTP o wysokiej aktualizacji.

Weźmy aktualny przykład. Jeśli duży amerykański bank centralny chciałby generować raport godzinowy w poszukiwaniu pierwszych oznak uruchomienia banku na poziomie miasta, zapytanie nolock mogłoby skanować tabele transakcji sumujące depozyty i wypłaty gotówki według miasta. W przypadku takiego raportu niewielki procent błędów spowodowanych wycofanymi transakcjami aktualizacji nie zmniejszyłby wartości raportu.

Saasman
źródło
31

Nie wiesz, dlaczego nie zawijasz transakcji finansowych w transakcjach w bazie danych (tak jak w przypadku transferu środków z jednego konta na drugie - nie zatwierdzasz jednej strony transakcji naraz - dlatego istnieją jawne transakcje). Nawet jeśli Twój kod jest w jakikolwiek sposób powiązany z transakcjami biznesowymi, tak jak się wydaje, wszystkie transakcyjne bazy danych mogą potencjalnie spowodować niejawne wycofanie w przypadku błędów lub awarii. Myślę, że ta dyskusja jest ponad twoją głową.

Jeśli masz problemy z blokowaniem, zaimplementuj wersjonowanie i wyczyść kod.

Żadna blokada nie tylko zwraca nieprawidłowe wartości, ale także rekordy i duplikaty fantomów.

Jest powszechnym błędnym przekonaniem, że zawsze przyspiesza uruchamianie zapytań. Jeśli na stole nie ma żadnych blokad zapisu, nie robi to żadnej różnicy. Jeśli na stole są blokady, może to przyspieszyć zapytanie, ale istnieje powód, dla którego wymyślono blokady.

Szczerze mówiąc, oto dwa specjalne scenariusze, w których podpowiedź nolocka może zapewnić użyteczność

1) Baza danych serwera SQL sprzed 2005 r., Która musi uruchamiać długie zapytania względem bazy danych OLTP na żywo, może to być jedyny sposób

2) Źle napisana aplikacja, która blokuje rekordy i zwraca kontrolę do interfejsu użytkownika, a czytniki są blokowane na czas nieokreślony. Nolock może być pomocny, jeśli aplikacja nie może zostać naprawiona (strona trzecia itp.), A baza danych jest wcześniejsza niż 2005 lub nie można włączyć wersji.

Andrzej
źródło
11
Zgadzam się z Tobą, że NOLOCK nie powinien być wykorzystywany do nadrobienia źle napisanego kodu. Myślę jednak, że twój atak na Johnathana jest nieuzasadniony, ponieważ nigdy nie wspomniał o transakcjach w bazie danych . Zwrócił po prostu uwagę, że aplikacje finansowe zazwyczaj nie pozwalają na edycję zapisów (oczywiście są pewne wyjątki). W przykładzie dotyczącym transferu środków mówi, że byłoby dziwnie, gdybyś zmienił wartość salda konta zamiast dodawać zapis debetowy / kredytowy do jakiejś księgi rachunkowej .
chrnola
19
Jak myślisz, kiedy środki są przenoszone z jednego konta na inne w różnych bankach? Niektóre bazy danych Uber blokują stolik w Bank of America, a inne w Wells Fargo? Nie. Do każdej transakcji zapisywana jest transakcja finansowa, a następnie proces na koniec dnia sprawdza, czy wszystkie rekordy są zgodne.
Jonathan Allen
24

NOLOCKjest równoważne READ UNCOMMITTED, jednak Microsoft twierdzi, że nie należy go używać do tego UPDATEani DELETEoświadczeń:

W przypadku instrukcji UPDATE lub DELETE: Ta funkcja zostanie usunięta w przyszłej wersji Microsoft SQL Server. Unikaj używania tej funkcji w nowych pracach programistycznych i planuj modyfikowanie aplikacji, które obecnie używają tej funkcji.

http://msdn.microsoft.com/en-us/library/ms187373.aspx

Ten artykuł dotyczy SQL Server 2005, więc obsługa NOLOCKistnieje, jeśli używasz tej wersji. Aby zabezpieczyć kod na przyszłość (zakładając, że zdecydowałeś się użyć brudnych odczytów), możesz użyć tego w swoich procedurach przechowywanych:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

Seibar
źródło
21

Możesz go użyć, gdy czytasz tylko dane, a tak naprawdę nie zależy ci na tym, czy odzyskujesz dane, które nie zostały jeszcze zatwierdzone.

Operacja odczytu może być szybsza, ale tak naprawdę nie mogę powiedzieć, ile.

Ogólnie rzecz biorąc, odradzam korzystanie z niego - odczytywanie nieprzekazywanych danych może być co najmniej nieco mylące.

marc_s
źródło
1
Byłoby miło, gdybyś wspomniał o tym, że SQL Server 2005 ma wersjonowanie wierszy, więc nolocks nie są już nawet potrzebne.
Jonathan Allen
Cóż, „with (nolock)” nadal ma swoje miejsce nawet w SQL Server 2005 - ale korzyści stają się coraz mniejsze, to prawda.
marc_s
18

Innym przypadkiem, w którym zwykle jest to w porządku, jest baza danych raportowania, w której dane są już prawdopodobnie przestarzałe i zapisy po prostu się nie zdarzają. W takim przypadku jednak administrator powinien ustawić tę opcję na poziomie bazy danych lub tabeli, zmieniając domyślny poziom izolacji.

W ogólnym przypadku: można go używać, gdy jesteś bardzo pewny, że to jest w porządku, aby czytać stare dane. Ważne jest, aby pamiętać, że bardzo łatwo to zrobić źle . Na przykład, nawet jeśli w momencie pisania zapytania jest to w porządku, czy na pewno coś się nie zmieni w bazie danych, aby te aktualizacje były ważniejsze?

Zastanowię się też nad tym, że w bankowości prawdopodobnie nie jest to dobry pomysł. Lub aplikacja asortymentowa. Lub gdziekolwiek myślisz o transakcjach.

Joel Coehoorn
źródło
4
Jako osoba, która pracuje nad aplikacjami bankowymi, muszę powiedzieć, że brak blokady nie stanowi problemu. Rekordy transakcyjne, czyli wiersze, które są wstawiane, ale nigdy nie aktualizowane lub usuwane, są zaskakująco odporne na problemy z odczytem nieproszonych danych.
Jonathan Allen
15

Prosta odpowiedź - ilekroć SQL nie zmienia danych i masz zapytanie, które może zakłócać inne działania (poprzez blokowanie).

Warto zastanowić się nad wszelkimi zapytaniami używanymi w raportach, zwłaszcza jeśli zapytanie zajmuje więcej niż, powiedzmy, 1 sekundę.

Jest to szczególnie przydatne, jeśli masz raporty typu OLAP uruchomione dla bazy danych OLTP.

Pierwsze pytanie, które należy zadać, to: „dlaczego się tym martwię?” Z mojego doświadczenia wynika, że ​​fałszowanie domyślnego zachowania blokowania często ma miejsce, gdy ktoś znajduje się w trybie „spróbuj czegoś” i jest to jeden przypadek, w którym nieoczekiwane konsekwencje nie są mało prawdopodobne. Zbyt często jest to przypadek przedwczesnej optymalizacji i może zbyt łatwo zostać osadzony w aplikacji „na wszelki wypadek”. Ważne jest, aby zrozumieć, dlaczego to robisz, jaki problem rozwiązuje i czy rzeczywiście masz problem.

dkretz
źródło
11

Krótka odpowiedź:

Używaj tylko WITH (NOLOCK)w instrukcji SELECT w tabelach, które mają indeks klastrowany.

Długa odpowiedź:

Z (NOLOCK) jest często wykorzystywany jako magiczny sposób na przyspieszenie odczytu bazy danych.

Zestaw wyników może zawierać wiersze, które nie zostały jeszcze zatwierdzone, a które często są później wycofywane.

Jeśli Z (NOLOCK) zostanie zastosowane do tabeli, która ma indeks nieklastrowany, wówczas indeksy wierszy można zmienić za pomocą innych transakcji, ponieważ dane wiersza są przesyłane strumieniowo do tabeli wyników. Oznacza to, że w zestawie wyników może brakować wierszy lub wyświetlać ten sam wiersz wiele razy.

CZYTAJ ZOBOWIĄZANIE dodaje dodatkowy problem, w którym dane są uszkodzone w jednej kolumnie, w której wielu użytkowników zmienia tę samą komórkę jednocześnie.

WonderWorker
źródło
2
Odczytywanie nieprzydzielonych danych jest dopuszczalne, jeśli nie zmienia ostatecznej decyzji. Na przykład, jeśli próbujesz prognozować, ile pieniędzy zarobi Twój sklep w ciągu najbliższych 6 miesięcy, to fakt, że Tammy kupiła 2 rolki ręczników papierowych, a tak naprawdę 3, nie zmieni twojego zdania na temat przyszłości .
Jonathan Allen,
1
Jeśli Twój filtr obejmuje teraz, Twoje dane będą niedokładne w momencie uruchomienia zapytania. Jeśli Twój filtr zawiera tylko dane historyczne, użycie READ UNCOMITTED go w ogóle nie wpłynie na to. Istnieje powód, dla którego został włączony do standardu ANSI.
Jonathan Allen
2
Nigdy nie mów nigdy. Jeśli POTRZEBUJESZ 100% dokładności danych, nie powinieneś używać nolocka. Dla mnie zwykle tak nie jest. Prezentując dane użytkownikowi, zanim będą one działać na danych, i tak mogły już się zmienić, ale najprawdopodobniej nie zmieniły się, a rywalizacja o blokadę nie jest warta opóźnień w odpowiedzi.
Perposterer
Trzymajmy się systemów godnych istnienia. Nie zapominaj, że Tammy ma doskonale przyzwoity mózg, więc korzystanie z bazy danych do rejestrowania drobnych zakupów ręczników papierowych, o których nikt nie zwraca uwagi, jest w najlepszym razie niedorzeczne. Koncentrujemy się na systemach, które są tak naprawdę ważne, np. Na tym, że ludzie płacą na czas, reagują na sytuacje kryzysowe itp. Jest to znaczną zaletą, że ludzie używający Z (NOLOCK) rozumieją, że ludzie programują każdy system godny istnienia. Gdy dana osoba może wykonać lepszą pracę niż baza danych, rozważ zmianę przeznaczenia tych zasobów.
WonderWorker
10

Moje 2 centy - warto używać WITH (NOLOCK), gdy trzeba generować raporty. W tym momencie dane niewiele by się zmieniły i nie chcesz blokować tych rekordów.

SoftwareGeek
źródło
2
Myślę, że Z (NoLOCK) jest lepiej, jeśli nie przejmujesz się bieżącymi zmianami.
Abdul Saboor,
9

Jeśli zajmujesz się transakcjami finansowymi, nigdy nie będziesz chciał z nich korzystać nolock. nolocknajlepiej jest wybierać z dużych tabel, które mają wiele aktualizacji i nie obchodzi cię, czy rekord, który uzyskasz, może być nieaktualny.

Dokumenty finansowe (i prawie wszystkie inne rekordy w większości aplikacji) nolockspowodowałyby spustoszenie, ponieważ potencjalnie można było odczytać dane z rekordu, który został zapisany, i nie uzyskać poprawnych danych.

Andrew Hare
źródło
5
Co zaskakujące, praca z danymi finansowymi nie stanowi problemu. Ponieważ wiersze nigdy nie są edytowane, a konta są uzgadniane na koniec dnia, odczytywanie tymczasowo fałszywych danych nic nie robi.
Jonathan Allen
8

Zwykłem pobierać „następną partię” rzeczy do zrobienia. W tym przypadku nie ma znaczenia, który dokładnie element, i mam wielu użytkowników uruchamiających to samo zapytanie.

Otávio Décio
źródło
1
Robimy coś podobnego, aby przedstawić zadanie w tle z kolejką do zrobienia. Jeśli po przejściu do określonego rekordu już nie istnieje / nie spełnia kryteriów wyboru, przechodzi do następnego.
TripeHound,
7

Korzystaj z nolock, gdy jesteś w porządku z „brudnymi” danymi. Co oznacza, że ​​nolock może również odczytywać dane, które są w trakcie modyfikacji i / lub nieprzypisane dane.

Zasadniczo nie jest dobrym pomysłem używanie go w środowisku o wysokich transakcjach i dlatego nie jest domyślną opcją dla zapytania.

Uczenie się
źródło
3
Jedyny potrzebny czas to środowisko o wysokich transakcjach. Jeśli twoje stoły są w większości bezczynne, to nic byś z tego nie zyskał.
Jonathan Allen
7

Używam ze wskazówką (nolock) szczególnie w bazach danych SQLServer 2000 o dużej aktywności. Nie jestem jednak pewien, czy jest to potrzebne w SQL Server 2005. Ostatnio dodałem tę wskazówkę w SQL Server 2000 na żądanie DBA klienta, ponieważ zauważył wiele blokad rekordów SPID.

Wszystko, co mogę powiedzieć, to to, że użycie podpowiedzi NIE zaszkodziło nam i wydaje się, że problem z blokowaniem sam się rozwiązał. DBA w tym konkretnym kliencie zasadniczo nalegało, abyśmy skorzystali z podpowiedzi.

Nawiasem mówiąc, bazy danych, którymi się zajmuję, są back-endami do korporacyjnych systemów roszczeń medycznych, więc mówimy o milionach rekordów i ponad 20 tabel w wielu połączeniach. Zazwyczaj dodaję podpowiedź Z (nolock) do każdej tabeli w złączeniu (chyba że jest to tabela pochodna, w którym to przypadku nie możesz użyć tej konkretnej wskazówki)

użytkownik52212
źródło
1
SQL Server 2005 dodał „wersjonowanie wierszy”, co powinno znacznie zmniejszyć zapotrzebowanie na nolocks. Niedawno zaktualizowaliśmy i nie szkolimy naszych DBA, aby przestały ich używać.
Jonathan Allen
5

Najprostsza odpowiedź to proste pytanie - czy chcesz, aby wyniki były powtarzalne? Jeśli tak, to NOLOCKS w żadnym wypadku nie jest odpowiedni

Jeśli nie potrzebujesz powtarzalności, przydatne mogą być nolocks, szczególnie jeśli nie masz kontroli nad wszystkimi procesami łączącymi się z docelową bazą danych.

Ed Green
źródło