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.
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
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
Nie zawsze jest to dobry pomysł ... http: // sqlblogcasts .pl/blogs/tonyrogerson/archive/2006/11/16/1345.aspx – gbn