Czy istnieje sposób na uniknięcie impasu przy zachowaniu tych samych zapytań?
Wykres zakleszczenia pokazuje, że ten zakleszczenie było zakleszczeniem konwersji związanym z wyszukiwaniem zakładek (w tym przypadku wyszukiwanie RID):
Jak zauważa pytanie, ogólne ryzyko zakleszczenia powstaje, ponieważ zapytania mogą uzyskać niezgodne blokady tych samych zasobów w różnych zamówieniach. SELECT
Kwerenda musi mieć dostęp do indeksu przed tabeli ze względu na RID Lookup, natomiast UPDATE
modyfikuje kwerendy tabeli, potem indeks.
Eliminacja impasu wymaga usunięcia jednego ze składników impasu. Oto główne opcje:
- Unikaj wyszukiwania RID, tworząc indeks nieklastrowany. Prawdopodobnie nie jest to praktyczne w twoim przypadku, ponieważ
SELECT
zapytanie zwraca 26 kolumn.
- Unikaj wyszukiwania RID, tworząc indeks klastrowany. Wymagałoby to utworzenia indeksu klastrowego w kolumnie
Proposal
. Warto to rozważyć, choć wydaje się, że ta kolumna jest typu uniqueidentifier
, co może, ale nie musi być dobrym wyborem dla indeksu klastrowego, w zależności od szerszych kwestii.
- Unikaj dzielonych blokad podczas czytania, włączając opcje
READ_COMMITTED_SNAPSHOT
lub SNAPSHOT
bazy danych. Wymagałoby to starannego przetestowania, szczególnie w odniesieniu do wszelkich zaprojektowanych zachowań blokujących. Kod wyzwalający wymagałby również przetestowania, aby upewnić się, że logika działa poprawnie.
- Unikaj dzielonych blokad podczas czytania, używając
READ UNCOMMITTED
poziomu izolacji dla SELECT
zapytania. Obowiązują wszystkie zwykłe zastrzeżenia.
- Unikaj równoczesnego wykonywania dwóch zapytań, używając wyłącznej blokady aplikacji (patrz sp_getapplock ).
- Użyj wskazówek dotyczących blokowania tabeli, aby uniknąć współbieżności. Jest to większy młotek niż opcja 5, ponieważ może wpływać na inne zapytania, nie tylko na dwa wymienione w pytaniu.
Czy mogę w jakiś sposób wziąć X-Lock na indeks w transakcji aktualizacji przed aktualizacją, aby zapewnić dostęp do tabeli i indeksu w tej samej kolejności
Można spróbować, owijając aktualizację w jawnej transakcji i wykonując SELECT
z XLOCK
odrobiną na nieklastrowany wartości indeksu przed aktualizacją. To zależy od tego, czy wiesz na pewno, jaka jest bieżąca wartość w indeksie nieklastrowanym, czy poprawnie wykonałeś plan wykonania i poprawnie przewidziałeś wszystkie skutki uboczne przyjęcia tej dodatkowej blokady. Polega również na tym, że silnik blokujący nie jest wystarczająco inteligentny, aby uniknąć przejęcia blokady, jeśli zostanie uznany za zbędny .
Krótko mówiąc, chociaż jest to w zasadzie wykonalne, nie polecam tego. Zbyt łatwo jest przeoczyć coś lub przechytrzyć się w twórczy sposób. Jeśli naprawdę musisz unikać tych zakleszczeń (zamiast ich wykrywania i ponownej próby), zachęcam do spojrzenia na bardziej ogólne rozwiązania wymienione powyżej.