Dwa zapytania powodujące zakleszczenie to SELECT
poniżej (process id="process3980de4558"
):
select @existing = team_it_cube_attr_05 from tbl_Ref_Attr_Prod_Team where prod_id = @rec_key
Oraz UPDATE
zapytanie poniżej (process id="process386ed48188"
):
UPDATE D
SET D.team_rss_attr_01 = LEFT(S.mkt_prodchar_13,25)...
<resource-list>
sekcja zwraca uwagę na SELECT
zapytanie posiadało blokadę na wyłączność (X) na stronie i próbowało uzyskać blokadę współdzieloną intencją (IS) na innej stronie podczas odczytu danych. UPDATE
zapytanie miało już blokadę IS i próbowało uzyskać blokadę X na stronie w celu wykonania aktualizacji.
Biorąc pod uwagę sprzężenie z tą tabelą:
...from tbl_Ref_Attr_Prod_Team where prod_id = @rec_key...
...INNER JOIN tbl_Ref_Attr_Prod_Team D ON D.prod_key=P.prod_key...
SELECT
zapytanie posiada już wyłączną blokadę. To prawdopodobnie oznacza, że jest to część większej transakcji, która już wykonała UPDATE
w poprzednim zapytaniu. Blokady z wcześniejszych zapytań zostaną zachowane w celu zachowania integralności danych podczas transakcji (w zależności od poziom izolacji transakcji
).
UPDATE
zapytanie musi odczytać tabelę tbl_Ref_Attr_Prod_team
. Uzyskuje współdzielone intencje na stronach i wierszach podczas odczytu danych. Gdy UPDATE
zapytanie znajdzie pasujące wiersze, spróbuje przekonwertować blokady IS na blokady X. Zamki IS nie są kompatybilne z blokadami X. Ponieważ SELECT
zapytanie ma już blokadę IS na jednej lub więcej z tych stron, zapytania zakleszczą się nawzajem.
Jedną z możliwych przyczyn może być brak indeksów w tbl_Ref_Attr_Prod_team.prod_key
. Bez indeksu w tej kolumnie UPDATE
zapytanie będzie skanować wszystkie wiersze w tabeli tbl_Ref_Attr_Prod_team
.
Nawet jeśli indeks istnieje na prod_key
, jeśli w tabeli jest niewielka liczba wierszy, SQL Server może zdecydować, że wydajność byłaby lepsza, gdyby zapytanie przeskanowało całą tabelę zamiast szukać indeksu. Zapisanie planu zapytania w momencie wystąpienia impasu zweryfikowałoby tę teorię.
Regularnie spotykamy się z zakleszczeniami małych tabel podczas uruchamiania nowych baz danych. Początkowo tabele są małe, a skanowanie tabel powoduje różnego rodzaju zakleszczenia. Później, gdy tabele są większe, obliczony koszt skanowania tabeli przekracza koszt wyszukiwania indeksu i zakleszczenia już nie występują. W środowiskach testowych, w których liczba wierszy jest zawsze mała, uciekliśmy się do użycia FORESEEK
i WITH INDEX
wskazówki, aby wymusić wyszukiwanie indeksu zamiast skanowania. Nie możemy się doczekać, aby móc wymusić plany zapytań za pomocą funkcji magazynu zapytań w SQL Server 2016.