2011-01-03 11 views
14

To jest naprawdę bardziej dyskusja niż konkretne pytanie o nolock.Do NOLOCK lub NOT to NOLOCK, to jest pytanie

Niedawno przejąłem aplikację, że prawie każde zapytanie (i jest ich dużo) ma opcję nolock na nich. Teraz jestem całkiem nowym użytkownikiem serwera SQL (korzystałem z Oracle przez 10 lat), ale uważam to za dość niepokojące. W ten weekend rozmawiałem z jednym z moich przyjaciół, który prowadzi raczej dużą witrynę e-commerce (nazwa zostanie zatrzymana, aby chronić winnych) i mówi, że musi to zrobić ze wszystkimi swoimi serwerami SQL, ponieważ zawsze będzie kończył się impasem.

Czy to jest po prostu wielki krótki spadek z serwerem SQL? Czy to po prostu błąd w projekcie DB (mój nie jest na trzecim poziomie, ale jest blisko) Czy ktoś tam używa aplikacji serwera SQL bez nolocks? Są to problemy, które Oracle radzi sobie lepiej z większymi blokadami nagrań.

Czy serwer SQL nie jest w stanie obsłużyć dużych obciążeń? Czy jest jakieś lepsze obejście niż czytanie niezamówionych danych? Chciałbym usłyszeć, co ludzie myślą.

Dzięki

Odpowiedz

13

SQL Server dodał snapshot isolation w SQL Server 2005, będzie to pozwalają nadal czytać ostatnią poprawną wartość bez konieczności oczekiwania na zamki. StackOverflow używa również Snapshot Isolation. Poziom izolacji migawki jest mniej więcej taki sam, jaki stosuje Oracle, dlatego też zakleszczenia nie występują zbyt często w skrzynce Oracle. Wystarczy mieć świadomość, aby mieć dużo przestrzeni tempdb jeśli nie pozwalają mu

z Books On Line

Gdy opcja bazie READ_COMMITTED_SNAPSHOT jest włączona, czytać zaangażowana izolacja wykorzystuje rząd wersjonowanie świadczenia Instrukcja- poziom czytaj spójność. Operacje odczytu wymagają tylko blokad poziomu stołu SCH-S i żadnych blokad strony ani wiersza. Kiedy opcja READ_COMMITTED_SNAPSHOT bazy danych jest ustawiona na WYŁ., Co jest domyślnym ustawieniem , odczyt zatwierdzonej izolacji zachowuje się tak, jak we wcześniejszych wersjach serwera SQL Server . Obie implementacje spełniają definicję przeczytanej zatwierdzonej odczytu .

+0

Z aktywną migawką, jakie są Twoje szanse na wejście w zakleszczenie? Nie sugerowałbym, że możesz dać mi procent, ale czy kiedykolwiek wpadłeś w impas z jego działaniem? – Limey

+0

Wygląda na to, że naprawiłem problem z StackOverflow, sam nie widziałem w nim zakleszczeń, ale również wprowadziłem pewne najlepsze praktyki w zakresie programowania serwerów SQl, które minimalizują to począwszy od – SQLMenace

+0

Nie zawsze jest to dobry pomysł ... http: // sqlblogcasts .pl/blogs/tonyrogerson/archive/2006/11/16/1345.aspx – gbn

4

Nie, nie ma potrzeby używania NOLOCK. Linki: SO 1

chodzi o obciążenia, mamy do czynienia z 2000 wierszy na sekundę, która jest mała zmiana w porównaniu do 35k TPS

Blokady są spowodowane przez blokady niezgody i zwykle spowodowane przez niezgodny kolejności zapisu na stołach w transakcjach. Zwłaszcza ORM to śmieci. Dostajemy je bardzo rzadko. Dobrze napisany DAL powinien również spróbować ponownie, jak na MSDN.

2

W tradycyjnym znormalizowanym środowisku OLTP NOLOCK to zapach kodu i prawie na pewno niepotrzebny w prawidłowo zaprojektowanym systemie.

W modelu wymiarowym intensywnie korzystałem z NOLOCK, aby uniknąć blokowania bardzo dużych tabel faktów i wymiarów, które zostały zapełnione późniejszymi danymi faktycznymi (i wymiary mogły wygasnąć). W modelu wymiarowym fakty albo nigdy się nie zmieniają, albo nigdy się nie zmieniają po pewnym punkcie.Podobnie każdy wymiar, do którego się odwołuje, będzie również statyczny, więc na przykład NOLOCK zatrzyma twoją długą operację analizy na wczorajszych danych przed blokowaniem wygaśnięcia wymiaru podczas ładowania danych dla dzisiejszych danych.

11

Jeśli ktoś mówi, że bez NOLOCK ich aplikacja zawsze zostaje zablokowana, to jest (bardziej niż prawdopodobny) problem z ich zapytaniami. Impozycja impozycja oznacza, że ​​dwie transakcje nie mogą zostać wykonane z powodu rywalizacji o zasoby i problemu nie można rozwiązać. Przykład:

Rozważ Transakcje A i B. Obie są w trakcie lotu. Transakcja A wprowadziła wiersz do tabeli X, a transakcja B wstawiła wiersz do tabeli Y, więc transakcja A ma wyłączną blokadę na X, a transakcja B ma wyłączną blokadę na Y.

Teraz transakcja A wymaga uruchomienia WYBIERZ w stosunku do tabeli Y, a transakcja B musi uruchomić SELECT względem tabeli X.

Obie transakcje są zakleszczone: A potrzebuje zasobu Y i B potrzebuje zasobu X. Ponieważ żadna transakcja nie może być kontynuowana, dopóki druga nie zakończy się, nie można rozwiązane: żadne transakcje nie wymagają zasobu, mogą zostać spełnione, dopóki druga transakcja nie zwolni blokady zasobu w rywalizacji (przez ROLLBACK lub COMMIT, nie ma znaczenia.)

Serwer SQL identyfikuje tę sytuację i wybiera jedną lub drugą transakcję jako ofiarę zakleszczenia, przerywa tę transakcję i wycofuje, pozostawiając drugą transakcję za darmo, aby przejść do jej prawdopodobnego zakończenia.

Zakleszczenia są rzadkie w życiu (IMHO). Jeden prostuje je

  • zapewnienie, że zakres transakcji jest tak mały, jak to możliwe, serwer coś SQL działa automatycznie (zakres domyślny transakcja SQL Server jest pojedynczy rachunek z niejawna COMMIT) i
  • zapewnienie, że zasoby transakcje dostępu w tej samej kolejności. W powyższym przykładzie, jeśli transakcje A i B zablokowały zasoby X i Y w tej samej sekwencji, nie wystąpiłaby zakleszczenie.

Timeouts

timeout, z drugiej strony, występuje wtedy, gdy transakcja przekracza czas oczekiwania i zostaje wycofana z powodu niezgody zasobów. Na przykład transakcja A wymaga zasobu X. Zasób X jest zablokowany przez transakcję B, więc transakcja A czeka na zwolnienie blokady. Jeśli blokada nie zostanie zwolniona w limicie czasu limitu czasu zapytania, transakcja oczekująca zostanie przerwana i wycofana. Każde zapytanie ma powiązany z nim limit czasu zapytania (domyślna wartość to 30 s, jak sądzę), po którym to czasie transakcja zostaje przerwana i wycofana. Limit czasu zapytania można ustawić na 0s, w którym to przypadku SQL Server pozwoli, aby zapytanie trwać wiecznie.

Jest to prawdopodobnie to, o czym mówią. Z mojego doświadczenia wynika, że ​​limity czasu takie jak te zwykle występują w dużych bazach danych, gdy duże zadania wsadowe aktualizują tysiące i tysiące rekordów w pojedynczej transakcji, chociaż mogą się zdarzyć, ponieważ transakcja idzie długo (połączyć się z bazą danych produkcji w Query Abalyzer, wykonać BEGIN TRANSACTION, zaktualizuj pojedynczy wiersz w często trafionej tabeli w Query Analyzer i idź na lunch bez wykonywania ROLLBACK lub COMMIT TRANSACTION i zobacz, jak długo trwa produkcja DBAs dla małpek ** t na ciebie.Nie pytaj mnie, skąd to wiem)

Ten rodzaj limitu czasu jest zazwyczaj co skutkuje splattering doskonale niewinnego SQL z wszelkiego rodzaju NOLOCK wskazówki

[TIP: jeśli będzie to zrobić, po prostu Wykonaj SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED jako pierwszą instrukcję w procedurze przechowywanej i już to zrobiono.]

Problem z tym podejściem (NOLOCK/READ UNCOMMITTED) polega na tym, że możesz odczytać niezatwierdzone dane z innych transakcji: rzeczy, które jest niekompletne lub może zostać wycofane później, więc integralność danych jest zsynchronizowana. Możesz wysyłać rachunek na podstawie danych o wysokim poziomie zagrożenia.

Moja ogólna zasada jest taka, że ​​należy unikać używania wskazówek na stole, o ile to możliwe. Niech SQL Server i jego optymalizator zapytań wykonają swoje zadania.

Właściwym sposobem na uniknięcie tego rodzaju problemów jest uniknięcie tego rodzaju transakcji (na przykład wstawienie miliona wierszy za jednym zamachem), które powodują problemy. Strategia blokowania zawarta w relacyjnej bazie danych SQL została zaprojektowana w oparciu o małe transakcje o krótkim zasięgu. Zamek powinien mieć mały zasięg i krótki czas działania. Pomyśl "kasjer bankowy aktualizujący czyjeś konto czekowe z depozytu". jako podstawowy przypadek użycia. Zaprojektuj swoje procesy, aby działały w tym modelu, a będziesz szczęśliwszy przez cały czas.

Zamiast wstawiać milion wierszy w jednej instrukcji wstawiania mondo, należy wykonać pracę w niezależnych porcjach i zatwierdzić każdy fragment niezależnie. Jeśli twój milion wierszy wstawi się po przetworzeniu 999,000 wierszy, cała praca zostanie utracona (nie wspominając o tym, że wycofanie może być ab * tch, a tabela jest nadal blokowana również podczas wycofywania). Jeśli wstawisz milion wierszy w bloku po 1000 rzędów każdy, popełniając po każdym bloku, unikasz rywalizacji o blokadę, która powoduje zakleszczenia, ponieważ zamki będą uzyskiwane i uwalniane, a rzeczy będą się dalej poruszać. Jeśli coś pójdzie na południe w 999. bloku 1000 rzędów, a transakcja zostanie przerwana i wycofana, wciąż otrzymujesz 998 000 wierszy wstawionych; straciłeś tylko 1000 rzędów pracy. Restart/Retry jest znacznie łatwiejsze.

Ponadto eskalacja blokady występuje w dużych transakcjach. W celu zwiększenia efektywności zamki zwiększają się do coraz większego zasięgu, gdy liczba blokad przechowywanych przez transakcje rośnie. Jeśli pojedyncza transakcja wstawia/aktualizuje/usuwa pojedynczy wiersz w tabeli, otrzymuję blokadę wiersza. Rób tak dalej, a gdy liczba blokad wiersza przechowywanych przez tę transakcję względem tej tabeli osiągnie wartość progową, SQL Server będzie eskalować strategię blokowania: blokady wierszy zostaną skonsolidowane i zamienione na mniejsze blokady numerów stron, zwiększając tym samym zakres trzymane zamki. Od tego momentu wstawianie/usuwanie/aktualizacja pojedynczego wiersza spowoduje zablokowanie tej strony w tabeli. Gdy zatrzymana liczba zablokowanych stron osiągnie wartość progową, blokady stron są ponownie konsolidowane, a strategia blokowania przechodzi do blokad tabel: transakcja blokuje teraz całą tabelę i nikt nie może grać, dopóki transakcja nie zostanie zatwierdzona lub wycofana.

Niezależnie od tego, czy można uniknąć funkcjonalnego unikania NOLOCK/READ UNCOMMITTED, zależy to całkowicie od natury procesów trafiających do bazowej bazy danych (oraz kultury organizacji będącej właścicielem).

Ja sam staram się unikać jego używania w jak największym stopniu.

Mam nadzieję, że to pomoże.

+0

Dzięki! Myślę, że to dodaje dobrej informacji do dyskusji. – Limey

1

Powinieneś używać tylko nolock na niezmiennym stole. Oczywiście będzie to to samo, co Read Zatwierdzona migawka. Bez migawki oszczędza się tylko czas potrzebny na zastosowanie blokady wspólnej, a następnie jej usunięcie, co w większości przypadków nie jest konieczne.

Jeśli chodzi o przewijanie stołu ... Żadna blokada nie oznacza tylko pobrania wiersza przed zakończeniem transakcji, aktualizując wszystkie wiersze. Możesz uzyskać dane o duchach jako podzielone strony danych, a nawet podzielić strony indeksowe. Lub brak danych. To mnie przeraziło, ale wydaje mi się, że może być jeszcze więcej scenariuszy, w których po prostu dostaniesz niewłaściwe dane.

Oczywiście nolock za uzyskanie przybliżonych szacunków lub po prostu zaewidencjonowanie procesu może być uzasadnione.

Podstawowa zasada - jeśli w ogóle zależy ci na danych, a dane się zmieniają, nie używaj funkcji NoLOCK.

+0

Noggins - to nie dane, które muszą być trywialne; to jest żądanie danych. Podałem dwa przykłady - szacunkowe lub uzyskać jakiś pomysł, w którym się znajdujesz. Zatem dane/proces mogą być i będą całkowicie potrzebne. Ale te szczególne przypadki użycia do czytania mogą zrobić z Nolockiem, ponieważ nie zamierzacie używać danych do projektowania nuke'a. Tylko sprawdzam. –