Przyczyna procesu będącego ofiarą impasu

105

Mam proces z Select, który zajmuje dużo czasu, w kolejności od 5 do 10 minut.
Obecnie nie używam NOLOCK jako wskazówki do silnika bazy danych MS SQL.
W tym samym czasie mamy inny proces, który dokonuje aktualizacji i wstawia do tej samej bazy danych i tych samych tabel.
Rozpoczął się pierwszy proces, który niedawno zakończył się przedwcześnie przekazem wiadomości

SQLEXCEPTION: transakcja została zablokowana na zasobach blokady z innym procesem i została wybrana jako ofiara zakleszczenia.

Ten pierwszy proces przebiega w innych witrynach w identycznych warunkach, ale z mniejszymi bazami danych, a zatem omawiana instrukcja select zajmuje znacznie krótszy okres czasu (rzędu około 30 sekund). W innych witrynach nie widzę komunikatu o zakleszczeniu w innych witrynach. Również nie dostałem tego komunikatu na stronie, na której początkowo występuje problem, ale zakładam, że wraz z rozrostem bazy danych, wydaje mi się, że przekroczyłem jakiś próg. Oto moje pytania:

  1. Czy czas potrzebny na wykonanie transakcji może zwiększyć prawdopodobieństwo, że powiązany proces zostanie oflagowany jako ofiara zakleszczenia?
  2. Jeśli wykonam selekcję ze wskazówką NOLOCK, czy spowoduje to usunięcie problemu?
  3. Podejrzewam, że pole datetime, które jest sprawdzane jako część klauzuli WHERE w instrukcji select, powoduje powolny czas wyszukiwania. Czy mogę utworzyć indeks na podstawie tego pola? Czy to jest wskazane?
Elliott
źródło
Częściowa odpowiedź na punkt 1: Nie myl impasu z przekroczeniem limitu czasu. Jeśli miałeś limit czasu, czas związany z zakończeniem jednej transakcji może być odpowiedzialny za przerwanie drugiej. Ponadto dobrze byłoby wiedzieć, na jakim zasobie jesteś zakleszczony (czy jest to indeks czy tabela?).
NealB,
1
SET DEADLOCK_PRIORITY HIGH ALTER DATABASE dbname SET MULTI_USER;
gstackoverflow

Odpowiedzi:

128

P1: Czy czas potrzebny na wykonanie transakcji może zwiększyć prawdopodobieństwo, że powiązany proces zostanie oznaczony jako ofiara zakleszczenia?

Nie. SELECT jest ofiarą, ponieważ miał tylko odczytane dane, dlatego transakcja wiąże się z niższym kosztem , więc zostaje wybrana jako ofiara:

Domyślnie aparat bazy danych wybiera jako ofiarę zakleszczenia sesję, w której odbywa się transakcja, której wycofanie jest najtańsze . Alternatywnie użytkownik może określić priorytet sesji w sytuacji zakleszczenia za pomocą SET DEADLOCK_PRIORITYinstrukcji. DEADLOCK_PRIORITY można ustawić na NISKI, NORMALNY lub WYSOKI, lub alternatywnie można ustawić dowolną wartość całkowitą w zakresie (od -10 do 10).

Q2. Jeśli wykonam selekcję ze wskazówką NOLOCK, czy spowoduje to usunięcie problemu?

Nie. Z kilku powodów:

Pytanie 3. Podejrzewam, że pole datetime, które jest sprawdzane jako część klauzuli WHERE w instrukcji select, powoduje powolny czas wyszukiwania. Czy mogę utworzyć indeks na podstawie tego pola? Czy to jest wskazane?

Prawdopodobnie. Przyczyną zakleszczenia jest prawie bardzo prawdopodobne, że baza danych jest słabo zindeksowana. 10 minut zapytań jest akceptowalnych w tak wąskich warunkach, że jestem w 100% pewien, że w twoim przypadku jest to nie do przyjęcia.

Z 99% pewnością oświadczam, że zakleszczenie jest spowodowane dużym skanowaniem tabeli, które powoduje konflikt z aktualizacjami. Zacznij od uchwycenia wykresu zakleszczenia, aby przeanalizować przyczynę. Najprawdopodobniej będziesz musiał zoptymalizować schemat swojej bazy danych. Przed wprowadzeniem jakichkolwiek modyfikacji przeczytaj ten temat Projektowanie indeksów i artykuły podrzędne.

Remus Rusanu
źródło
Dziękuję za wyczerpującą odpowiedź. Myślę, że wciąż mam jedno pytanie. Dlaczego miałbym wpadać w impas tylko w jednym środowisku, a nie w innym. Mimo że oprogramowanie jest takie samo. Twoja odpowiedź sugeruje, że czas potrzebny na uruchomienie zapytania wybierającego nie ma znaczenia i to fakt, że samo zapytanie wybierające jest przyczyną niepowodzenia procesu. Ale dlaczego tylko wtedy, gdy wykonanie zapytania wybierającego zajmuje dużo czasu?
Elliott,
4
Długość zapytania nie ma znaczenia przy wyborze ofiary zakleszczenia . Ma to znaczenie w powodowaniu impasu przez co najmniej dwa czynniki: 1) proste prawdopodobieństwa. Im dłuższe zapytanie, tym większe prawdopodobieństwo nakładania się współbieżnych aktualizacji i blokowania. 2) większa tabela może korzystać z zupełnie innego planu zapytań, który jest podatny na zakleszczenia.
Remus Rusanu
12

Oto, w jaki sposób ten konkretny problem z zakleszczeniem faktycznie wystąpił i jak został faktycznie rozwiązany. Jest to dość aktywna baza danych, w której codziennie występuje 130 tys. Transakcji. Indeksy w tabelach w tej bazie danych były pierwotnie zgrupowane. Klient zażądał, aby indeksy nie były klastrowane. Tak szybko, jak to zrobiliśmy, rozpoczął się impas. Kiedy ponownie ustanowiliśmy indeksy jako klastrowe, impas ustał.

Elliott
źródło
34
Czy ktoś może wyjaśnić, dlaczego? (Magiczne rozwiązania nie są zbyt pomocne)
OGrandeDiEnne
1
Ten facet wyjaśnia to w swoim poście: mssqltips.com/sqlservertip/2517/ ...
siga0984
6

Warto spróbować odpowiedzi, ale powinieneś także przejrzeć swój kod. W szczególności przeczytaj odpowiedź Polyfuna: Jak pozbyć się zakleszczenia w SQL Server 2005 i aplikacji C #?

Wyjaśnia problem współbieżności i jak użycie "with (updlock)" w zapytaniach może poprawić sytuację zakleszczenia - w zależności od tego, co dokładnie robi twój kod. Jeśli twój kod jest zgodny z tym wzorcem, jest to prawdopodobnie lepsze rozwiązanie przed uciekaniem się do brudnych odczytów itp.

Peter Barton
źródło