Jak odtworzyć „Nie można kontynuować skanowania za pomocą NOLOCK z powodu przenoszenia danych”

10

Czasami pojawia się komunikat „Nie można kontynuować skanowania z NOLOCKpowodu przenoszenia danych” w przypadku niektórych dużych zadań, które WITH (NOLOCK)dotyczą wybranych zapytań.

Rozumiem, że ma to coś wspólnego z próbą wybrania danych, gdy nastąpił podział strony, który spowodował, że dane nie były już tam, gdzie powinny być - Zakładam, że tak właśnie dzieje się w moim środowisku.

Jak mam to odtworzyć?

Próbuję zrobić krótkoterminowe obejście, aby złapać błąd i spróbować ponownie, gdy to się stanie, ale nie mogę go przetestować, jeśli nie mogę go odtworzyć. Czy istnieje rozsądnie niezawodny sposób na spowodowanie tego?

Kiedy tak się stanie, ponowne wykonanie zapytania zakończy się sukcesem - więc tak naprawdę nie mam obaw o trwałe uszkodzenie danych lub bazy danych. Niektóre tabele w zapytaniu (wraz z ich indeksami) są często usuwane, ponownie tworzone i ponownie wypełniane, więc zakładam, że jest to z tym związane.

Usunięcie NOLOCKjest moim długoterminowym problemem do rozwiązania. Powodem tego NOLOCKbyło przede wszystkim to, że zapytania były tak złe, że blokowały się w codziennych transakcjach, podobnie NOLOCKjak pomoc dla zespołu, aby zatrzymać impas (który zadziałał). Potrzebuję więc opaski na opasce, dopóki nie możemy zrobić trwałego rozwiązania.

Gdybym mógł to odtworzyć w Hello World, planowałbym prawdopodobnie nakleić pomoc zespołu na pracę w niecałą godzinę. Nie można usunąć wyszukiwania i zastąpienia NOLOCK, ponieważ zacznę ponownie dostawać się impasów aplikacji, które są dla mnie gorsze niż okazjonalne nieudane zadanie.

Dobrym rozwiązaniem jest użycie izolacji odczytu zatwierdzonych migawek - będę musiał współpracować z naszym zespołem bazy danych, aby uzyskać więcej informacji na ten temat. Częścią naszego problemu jest to, że nie mamy eksperta od SQL Servera, który poradziłby sobie z tego rodzaju sprawami i nie rozumiem poziomów izolacji wystarczająco dobrze, aby dokonać tej zmiany teraz.

wookie23
źródło
1
Czy rozważałeś po prostu usunięcie NOLOCKz tych miejsc pracy? 601 powinno być najmniejszym z twoich zmartwień, jeśli wyniki tych zapytań mają być dokładne . Paul White pokazuje szczególnie okropny przykład odczytu danych, który nie powinien być tutaj możliwy .
Aaron Bertrand
3
Można ustawić DEADLOCK_PRIORITY, aby LOWw pracy, tak, że jeśli istnieje zakleszczenia, zadania zakończy się niepowodzeniem, a nie aplikacji. Następnie możesz zbadać impasy i dowiedzieć się, dlaczego tak się dzieje, i rozwiązać ten problem. Może to być bardzo prosta poprawka, na przykład zamiana kolejności dwóch instrukcji. Jakikolwiek jest problem, nieNOLOCK jest to rozwiązanie , więc przestań próbować wymuszać, aby było tak tylko dlatego, że jest to najłatwiejsze.
Aaron Bertrand
@AaronBertrand Dzięki, nie wiedziałem o DEADLOCK_PRIORITY - przyjrzę się temu. Próbowaliśmy wyśledzić impasy, ale zdarzały się one w różnych pozornie losowych porach i tylko raz lub dwa razy dziennie i nigdy nie są powtarzalne na żądanie - nasze zaplanowane zadania uruchamiają dziesiątki tysięcy zapytań co godzinę, a nasza aplikacja wykonuje setki zapytań, gdy tylko ładuje stronę lub coś zapisuje, a my nie wyśledziliśmy, które zapytanie po obu stronach bierze udział w impasie. Nie miałem zamiaru pozostawiać NOLOCK na zawsze, dlatego szukamy lepszych długoterminowych rozwiązań.
wookie23,
1
Wspomniałeś, że miałeś trudności z wyśledzeniem impasu. Biorąc pod uwagę, że jesteś w 2008 R2 można zajrzeć tutaj: sqlservercentral.com/articles/deadlock/65658 Jonathan Kehayias podchodzi ciągnąc informacji zakleszczenia z bufora pierścieniowego.
Kenneth Fisher
Odpowiedzi i komentarze dobrze rozwiązują podstawowy problem, ale czy nadal interesuje Cię znalezienie sposobu na odtworzenie tego jako ćwiczenia intelektualnego?
James L

Odpowiedzi:

8

Ponieważ jedną z potencjalnych „pomocy zespołu” w kwestiach NOLOCK jest zaprzestanie używania NOLOCK i rozpoczęcie korzystania z izolacji READ_COMMITTED_SNAPSHOT, chcę skierować cię do postu na blogu na stronie http://www.brentozar.com autorstwa Kendry Little: Implementacja migawki lub przeczytanie Izolacja migawek w programie SQL Server: przewodnik .

Kendra zapewnia sporo szczegółów na temat korzyści i ryzyka związanych z użyciem poziomu izolacji READ_COMMITTED_SNAPSHOT.

  1. Ten poziom izolacji staje się domyślnym poziomem izolacji dla kodu bazy danych.
  2. Musisz mieć tylko jednego użytkownika w bazie danych, aby dokonać zmiany na poziom izolacji READ_COMMITTED_SNAPSHOT.
  3. Nawet jeśli użyjesz izolacji READ_COMMITTED_SNAPSHOT , nadal będziesz musiał usunąć wskazówki NOLOCK, ponieważ zastępują one domyślne.
  4. Część twojego kodu może mieć problemy, które wymagają naprawy.

Kilka lat temu wdrożyliśmy izolację READ_COMMITTED_SNAPSHOT w bazie danych, która poważnie cierpiała z powodu blokowania . Ale kiedy zmieniliśmy poziom izolacji, zaczęliśmy otrzymywać impasy w kilku krytycznych obszarach.

Dlaczego się to stało? Ponieważ poprzedni poziom izolacji powodował silne blokowanie, kod „nigdy” nie może osiągnąć punktu zakleszczenia. Jednak dzięki izolacji READ_COMMITTED_SNAPSHOT zapytania mogą iść naprzód. Jednak pewien procent nieużywanych transakcji zaczął się blokować.

Na szczęście nasza sprawa została szybko rozwiązana poprzez określenie punktów zakleszczenia i dostosowanie indeksów w kilku tabelach, aby uzyskać bardziej racjonalną kolejność kolumn. To znacznie zmniejszyło nasze problemy z blokowaniem.

RLF
źródło