WYBIERZ / WSTAW Zakleszczenie

10

To wystąpienie obsługuje bazy danych SharePoint 2007 (SP). Występuje wiele zakleszczeń SELECT / INSERT wobec jednej mocno wykorzystywanej tabeli w bazie danych zawartości SP. Zawęziłem zasoby, oba procesy wymagają blokady indeksu nieklastrowanego.
INSERT potrzebuje blokady IX w zasobie SELECT, a SELECT potrzebuje blokady S w zasobie INSERT. Wykres impasu przedstawia trzy zasoby: 1.) dwa z SELECT (równoległe wątki producent / konsument) i 2.) WSTAW.
Dołączyłem wykres impasu do twojej recenzji. Ponieważ jest to kod Microsoft i struktury tabel, nie możemy dokonywać żadnych zmian.
Jednak przeczytałem na stronie MSFT SP, że zalecają ustawienie opcji konfiguracji poziomu wystąpienia MAXDOP na 1. Ponieważ to wystąpienie jest współużytkowane przez wiele innych baz danych / aplikacji, ustawienia tego nie można wyłączyć.


Dlatego postanowiłem spróbować nie dopuścić do równoległości tych instrukcji SELECT. Wiem, że to nie jest rozwiązanie, ale bardziej tymczasowa modyfikacja, która pomaga w rozwiązywaniu problemów. Dlatego zwiększyłem „próg kosztu dla równoległości” z naszego standardowego 25 do 40, robiąc to, mimo że obciążenie się nie zmieniło (często pojawia się WYBIERZ / WSTAW) impasy zniknęły. Moje pytanie brzmi: dlaczego?

SPID 356 INSERT ma blokadę IX na stronie należącej do indeksu nieklastrowego
SPID 690 SELECT ID wykonania 0 blokuje S na stronie należącej do tego samego indeksu nieklastrowanego

Teraz

SPID 356 chce IX blokady na zasobie SPID 690, ale nie może go utrzymać, ponieważ SPID 356 jest blokowany przez SPID 690 ID wykonania 0 Blokada S
SPID 690 ID wykonania 1 chce blokady S na zasobu SPID 356, ale nie może go uzyskać, ponieważ identyfikator wykonania SPID 690 1 jest blokowany przez SPID 356, a teraz mamy impas.

Plan wykonania można znaleźć na mojej SkyDrive

Pełne szczegóły impasu można znaleźć tutaj

Jeśli ktoś może mi pomóc zrozumieć, dlaczego naprawdę to doceniam.

Tabela EventReceivers.
Identyfikator unikalny nr 16
Nazwa nvarchar nr 512
SiteId unikalny identyfikator nr 16
WebId unikalny identyfikator nr 16
HostId unikalny identyfikator nr 16
HostType int nr 4
ItemId int nr 4
DirName nvarchar nie 512
LiśćName nvarchar nr 256
Typ int nr 4
Sekwencja Numer int 4
Montaż nvarchar nr 512
Klasa nvarchar nie 512
Dane nvarchar nie 512
Filtr nvarchar nie 512
SourceId tContentTypeId nie 512
SourceType int nie 4
Referencje int nie 4
ContextType varbinary nr 16
ContextEventType varbinary no 16
ContextId varbinary no 16
ContextObjectId varbinary no 16
ContextCollectionId varbinary no 16

index_name index_description index_keys
EventReceivers_ByContextCollectionId nieklastrowany się na pierwotnych siteid, ContextCollectionId
EventReceivers_ByContextObjectId nieklastrowany się na pierwotnych siteid, ContextObjectId
EventReceivers_ById nieklastrowany, niepowtarzalny się na pierwotnych siteid, Id
EventReceivers_ByTarget skupione, niepowtarzalny się na pierwotnych siteid, WebId, hostid, HostType, typ, ContextCollectionId, ContextObjectId, ContextId, ContextType, ContextEventType, SequenceNumber, Assembly, Class
EventReceivers_IdUnique nieklastrowany, unikalny, unikalny klucz umieszczony na PODSTAWOWYM Id

SQLJarHead
źródło
2
Co robimy proc_InsertEventReceiveri proc_InsertContextEventReceiverczego nie możemy zobaczyć w XDL? Również, aby zmniejszyć paralelizm, dlaczego po prostu nie wpłynąć bezpośrednio na tę instrukcję (za pomocą MAXDOP 1) zamiast na próżno z ustawieniami całego serwera?
Aaron Bertrand
1
Jestem ciekawy, jakie jest twoje ustawienie MAXDOP dla całego serwera i ile masz procesorów (logicznych). SharePoint naprawdę działa lepiej i wolę być na serwerze z serwerem MAXDOP szerokim na 1 .. Nie podoba mi się to, ale tak właśnie go opracowali. Czy możesz opublikować aktualne plany wykonania? Wszystko, co widzę pod tym linkiem, to .xdl (wykres zakleszczenia)
Mike Walsh
Witajcie, panowie. Naprawdę doceniam, że poświęciłeś mi trochę czasu poza napiętym harmonogramem na udzielenie odpowiedzi. Zamieszczę zarówno procedury, jak i plany wykonania twojej recenzji na stronie SkyDrive. Myślałem o zmodyfikowaniu kodu w celu włączenia opcji zapytania MAXDOP (1), jednak spowoduje to unieważnienie naszego wsparcia dla Microsoft. Serwer fizyczny ma ustawienie ProLiant DL580 G4 MAXDOP to 4 z łącznie 8 procesorami fizycznymi, a H / T jest wyłączone.
SQLJarHead
Witam Panowie, stworzyłem pakiet zip ze wszystkimi szczegółami na SkyDrive. Zmodyfikowałem treść oryginalnego postu, aby uwzględnić adres URL paczki. Proszę, nie mów mi, na czym polega problem, po prostu podaj wskazówki i pozwól mi nad tym popracować. UWAGA: Nie jestem w stanie dokonać żadnych zmian kodu ani modyfikacji DDL w podstawowym schemacie.
SQLJarHead
1
Nie możesz więc zmienić kodu ani schematu. Jakie inne rozwiązania oczekujesz od nas? Jeśli martwisz się o unieważnienie techniczną firmy Microsoft, to oznacza, że mają wsparcie firmy Microsoft, w tym przypadku - biorąc pod uwagę wszystkie ograniczenia Powiedziałeś nam, że nie można zrobić - czy uważa się za otwarcie bilet wsparcia z firmą Microsoft?
Aaron Bertrand

Odpowiedzi:

14

Na pierwszy rzut oka wygląda to jak klasyczny impas wyszukiwania . Podstawowymi składnikami tego impasu są:

  • SELECTkwerenda, która używa zakaz obejmujący nieklastrowany indeks z kluczem Lookup
  • INSERTzapytania, który modyfikuje klastra indeks i indeks nieklastrowany

SELECTDostęp pierwszy indeks nieklastrowany, a następnie indeksu klastrowego. INSERTDostęp indeks klastra, potem indeks nieklastrowany. Dostęp do tych samych zasobów w innej kolejności i uzyskiwanie niekompatybilnych zamków jest oczywiście świetnym sposobem na osiągnięcie impasu.

W takim przypadku SELECTzapytanie to:

WYBIERZ zapytanie

... a INSERTzapytanie brzmi:

WSTAW zapytanie

Zwróć uwagę na podświetloną na zielono obsługę indeksów nieklastrowych.

SELECTMusielibyśmy zobaczyć wersję seryjną planu na wypadek, gdyby różniła się bardzo od wersji równoległej, ale jak zauważa Jonathan Kehayias w swoim przewodniku dotyczącym obsługi zakleszczeń, ten szczególny wzorzec zakleszczenia jest bardzo wrażliwy na szczegóły dotyczące czasu i wykonania wewnętrznego zapytania. Ten rodzaj impasu często przychodzi i odchodzi bez oczywistej przyczyny zewnętrznej.

Biorąc pod uwagę dostęp do danego systemu i odpowiednie uprawnienia, jestem pewien, że w końcu moglibyśmy dokładnie ustalić, dlaczego impas występuje z planem równoległym, ale nie szeregowym (przyjmując ten sam ogólny kształt). Potencjalne kierunki śledztwa obejmują sprawdzanie zoptymalizowanych zagnieżdżonych pętli i / lub preselekcji - z których oba mogą wewnętrznie eskalacji poziom izolacji , aby REPEATABLE READw czasie trwania zestawienia. Możliwe jest również, że pewna funkcja równoległego przypisywania zakresu wyszukiwania indeksu przyczynia się do tego problemu. Jeśli plan seryjny stanie się dostępny, mógłbym poświęcić trochę czasu na dalsze analizowanie szczegółów, ponieważ jest to potencjalnie interesujące.

Zwykłym rozwiązaniem tego typu zakleszczenia jest sprawienie, by indeks był zakryty, chociaż liczba kolumn w tym przypadku może sprawić, że będzie to niepraktyczne (a poza tym nie powinniśmy zadzierać z takimi rzeczami w SharePoint, jak mi powiedziano). Ostatecznie zalecenie dotyczące planów tylko szeregowych przy korzystaniu z SharePoint istnieje z jakiegoś powodu (choć niekoniecznie dobrego, jeśli chodzi o to). Jeśli zmiana progu kosztu dla równoległości rozwiązuje problem w tej chwili, to dobrze. W dłuższej perspektywie prawdopodobnie chciałbym rozdzielić obciążenia, być może używając Resource Governor, aby wewnętrzne zapytania SharePoint uzyskały pożądane MAXDOP 1zachowanie, a druga aplikacja mogła korzystać z równoległości.

Pytanie o wymiany pojawiające się w impasie wydaje mi się czerwonym śledziem; po prostu konsekwencja posiadania przez niezależne wątki zasobów, które technicznie muszą pojawić się w drzewie. Nie widzę nic, co sugerowałoby, że same wymiany przyczyniają się bezpośrednio do problemu impasu.

Paul White 9
źródło
6

Jeśli byłby to klasyczny impas wyszukiwania , lista zasobów zawiera zarówno Indeks klastrowany, jak i Indeks nieklastrowany. Zazwyczaj WYBIERZ będzie trzymał blokadę SHARED na indeksie NC i czekał na blokadę SHARED na CI, tymczasem INSERT uzyska blokadę EXCLUSIVE na CI i czeka na blokadę EXCLUSIVE na NC. Lista zasobów w zakleszczonym pliku XML wyświetli oba te obiekty w tym przypadku.

Ponieważ wykres impasu obejmuje tylko Indeks NC, możemy wykluczyć tę opcję.

Ponadto, jeśli był to martwy zamek z powodu łączenia zagnieżdżonej pętli z NIEZGODNYM PREFETKIEM , plan wykonania powie nam, czy używany jest algorytm NIEPRZERWANY PREFETCH, co znowu nie ma miejsca (patrz aktualizacja poniżej).

To pozwala nam założyć, że jest to impas z powodu planu równoległego.

Wykres zakleszczenia nie jest poprawnie renderowany, ale jeśli spojrzysz na kod zakleszczenia XML, możesz zauważyć, że w impasie są zaangażowane dwa wątki z instrukcji SELECT (SPID 690). Wątek konsumenta trzyma blokadę SHARED na STRONIE 1219645 i czeka na producenta na porcie 801f8ed0 (e_waitPipeGetRow). Wątek producenta czeka na udostępnioną blokadę na STRONIE 1155940.

Instrukcja INSERT trzyma blokadę IX na STRONIE 1155940 i czeka na blokadę IX na STRONIE 1219645, co powoduje zakleszczenie.

Uważam, że impas zostanie uniknięty podczas korzystania z planu szeregowego instrukcji SELECT, ponieważ w żadnym momencie nie będzie wymagał blokady SHARED na więcej niż jednej stronie. Myślę też, że plan szeregowy będzie prawie taki sam jak plan równoległy (bez operatora równoległości).

[AKTUALIZACJA na podstawie komentarza Paula]

Najwyraźniej plan wykorzystuje OPTYMALIZOWANY algorytm zagnieżdżonej pętli

To wyjaśnia, dlaczego blokady SHARED są utrzymywane do końca instrukcji. POWTARZALNE CZYTANIE w połączeniu z planem równoległym jest bardziej narażone na zakleszczenie niż plan szeregowy, ponieważ plan równoległy może uzyskiwać i utrzymywać blokady z różnych zakresów indeksu, podczas gdy plan szeregowy uzyskuje blokady w bardziej sekwencyjny sposób.

Roji P Thomas
źródło
Zgoda. Gdyby ten impas był związany z faktycznym WYSZUKAJENIEM, zasób oczekiwania dla WYBORU odwoływałby się do indeksu klastrowego. Udało mi się to wykluczyć, wyświetlając nagłówek strony dla każdego zasobu oczekiwania (SPID 690 Zasób oczekiwania = STRONA: 1155940 | SPID 356 Zasób oczekiwania = STRONA 1219645) za pośrednictwem strony DBCC i oba były na indeksie ID 5 (IndexID 5 = EventReceivers_ByContextObjectId) który wskazuje na indeks NC w określonej tabeli (EventReceivers).
SQLJarHead
Panowie, jeszcze raz dziękuję za poświęcenie czasu na przeanalizowanie tego interesującego problemu. Kilka pytań: 1.) Roji wskazuje, że równoległy SPID wymaga więcej niż jednej strony. Nie widzę tego w żadnym planie wykonania. Patrząc na liczbę wierszy, dla operatora INDEX SEEK tylko jeden wątek z dwóch producentów przetwarza dowolne wiersze. Jak ustaliłeś, że żąda więcej niż jednej strony? (1/2)
SQLJarHead
2.) Czy algorytm OPTYMALIZOWANEJ zagnieżdżonej pętli zawsze ustawi poziom izolacji na REAPTABLE READ? Sprawdziłem dane wyjściowe XML planów wykonania i widzę tylko odczyt zatwierdzony dla połączenia SPID. Zakładam, że jest to wywoływane tylko na poziomie operatora planu. (2/2)
SQLJarHead
Zachowanie blokujące OPTYMALIZOWANYCH Pętli Zagnieżdżonych jest porównywalne z POWTARZALNYM CZYTANIEM (utrzymuje blokady do końca instrukcji ), ale nie powoduje jawności ustawienia poziomu izolacji transakcji na POWTARZALNE CZYTANIE. Myślę, że to również odpowiada na twoje pytanie. Nie jest tak, że równoległe wątki żądają więcej niż jednej strony na raz, ale jeden równoległy wątek trzyma blokadę na jednej stronie, a inny wątek czeka na blokadę na innej stronie
Roji P Thomas