Specjaliści od baz danych często mają do czynienia z problemami z wydajnością bazy danych, takimi jak nieprawidłowe indeksowanie i źle napisany kod w produkcyjnych instancjach SQL. Załóżmy, że zaktualizowano transakcję, a program SQL Server zgłosił następujący komunikat o zakleszczeniu. Dla początkujących administratorów baz danych może to być szokiem.
W tym artykule omówimy zakleszczenia SQL Server i najlepsze sposoby ich uniknięcia.
Co to jest impas w SQL Server?
SQL Server to wysoce transakcyjna baza danych. Załóżmy na przykład, że obsługujesz bazę danych dla portalu zakupów online, w którym przez całą dobę otrzymujesz nowe zamówienia od klientów. Wielu użytkowników prawdopodobnie wykonuje tę samą czynność w tym samym czasie. W takim przypadku baza danych powinna być zgodna z właściwościami atomowości, spójności, izolacji i trwałości (ACID), aby zachować spójność, niezawodność i chronić integralność danych.
Poniższy obrazek opisuje właściwości ACID w relacyjnej bazie danych.
Aby postępować zgodnie z właściwościami ACID, SQL Server używa mechanizmów blokowania, ograniczeń i rejestrowania z wyprzedzeniem. Różne typy blokad obejmują:blokadę wyłączną (X), blokadę współdzieloną (S), blokadę aktualizacji (U), blokadę intencji (I), blokadę schematu (SCH) i blokadę zbiorczej aktualizacji (BU). Blokady te można uzyskać na poziomie klucza, tabeli, wiersza, strony i bazy danych.
Załóżmy, że masz dwóch użytkowników, Jana i Piotra, którzy są połączeni z bazą danych klientów.
- Jan chce zaktualizować rekordy klienta, który ma [customerid] 1.
- W tym samym czasie Piotr chce pobrać wartość dla klienta, który ma [customerid] 1.
W tym przypadku SQL Server używa następujących blokad zarówno dla Jana, jak i Piotra.
Blokady dla Jana
- Wymaga blokady intencji wyłącznej (IX) w tabeli klientów i stronie zawierającej rekord.
- Dodatkowo zajmuje blokadę na wyłączność (X) w wierszu, który Jan chce zaktualizować. Uniemożliwia innym użytkownikom modyfikację danych wiersza, dopóki proces A nie zwolni blokady.
Zamki dla Piotra
- Uzyskuje blokadę intencji współdzielonej (IS) w tabeli klientów i stronie zawierającej rekord zgodnie z klauzulą WHERE.
- Próbuje wziąć wspólną kłódkę, aby odczytać wiersz. Ten rząd ma już ekskluzywną blokadę dla Jana.
W takim przypadku Piotr musi poczekać, aż Jan zakończy pracę i zwolni blokadę na wyłączność. Ta sytuacja nazywana jest blokowaniem.
Załóżmy teraz, że w innym scenariuszu John i Peter mają następujące blokady.
- Jan ma wyłączną blokadę na stole klienta dla identyfikatora klienta 1.
- Piotr ma wyłączną blokadę w tabeli zamówień dla identyfikatora klienta 1.
- John wymaga wyłącznej blokady na stole zamówień, aby zakończyć transakcję. Peter ma już ekskluzywną blokadę na stole zamówień.
- Peter wymaga wyłącznej blokady na stole klienta, aby zakończyć transakcję. John ma już ekskluzywną blokadę na stole klienta.
W takim przypadku żadna z transakcji nie może być kontynuowana, ponieważ każda transakcja wymaga zasobu posiadanego przez drugą transakcję. Ta sytuacja jest znana jako zakleszczenie SQL Server.
Mechanizmy monitorowania zakleszczeń w SQL Server
SQL Server okresowo monitoruje sytuacje zakleszczenia przy użyciu wątku monitora zakleszczenia. Sprawdza procesy biorące udział w zakleszczeniu i identyfikuje, czy sesja stała się ofiarą zakleszczenia. Wykorzystuje wewnętrzny mechanizm do identyfikacji procesu ofiary zakleszczenia. Domyślnie transakcja z najmniejszą ilością zasobów wymaganych do wycofania jest uważana za ofiarę.
SQL Server zabija sesję ofiary, aby inna sesja mogła uzyskać wymaganą blokadę, aby zakończyć transakcję. Domyślnie SQL Server sprawdza sytuację zakleszczenia co 5 sekund przy użyciu monitora zakleszczenia. Jeśli wykryje zakleszczenie, może zmniejszyć częstotliwość z 5 sekund do 100 milisekund w zależności od wystąpienia zakleszczenia. Ponownie resetuje wątek monitorowania do 5 sekund, jeśli nie występują częste zakleszczenia.
Gdy SQL Server zabije proces jako ofiara zakleszczenia, otrzymasz następujący komunikat. W tej sesji proces o identyfikatorze 69 był ofiarą impasu.
Skutki używania instrukcji priorytetu zakleszczenia w SQL Server
Domyślnie SQL Server oznacza transakcję z najtańszym wycofaniem jako ofiarą impasu. Użytkownicy mogą ustawić priorytet zakleszczenia w transakcji za pomocą instrukcji DEADLOCK_PRIORITY.
SET DEADLOCK_PRIORITY
Używa następujących argumentów:
- Niski:odpowiada priorytetowi impasu -5
- Normalny:jest to domyślny priorytet zakleszczenia 0
- Wysoki:Najwyższy priorytet impasu 5.
Możemy również ustawić wartości liczbowe dla priorytetu zakleszczenia od -10 do 10 (łącznie 21 wartości).
Przyjrzyjmy się kilku przykładom zakleszczeń dotyczących priorytetów.
Przykład 1:
Sesja 1 z priorytetem zakleszczenia:Normalny (0)> Sesja 2 z priorytetem zakleszczenia:Niski (-5)
Ofiara impasu: Sesja 2
Przykład 2:
Sesja 1 z priorytetem zakleszczenia:Normalny (0)
Ofiara impasu: Sesja 1
Przykład 3
Sesja 1 z priorytetem zakleszczenia:-3> Sesja 2 z priorytetem zakleszczenia:-7
Przykład 4:
Sesja 1 z priorytetem zakleszczenia:-5
Ofiara impasu: Sesja 1
Wykres zakleszczenia to wizualna reprezentacja procesów zakleszczenia, ich blokad i ofiary zakleszczenia. Możemy włączyć flagi śledzenia 1204 i 1222, aby przechwytywać szczegółowe informacje o zakleszczeniu w formacie XML i graficznym. Możemy użyć domyślnego zdarzenia rozszerzonego system_health, aby uzyskać szczegóły impasu. Szybkim i łatwym sposobem na zinterpretowanie zakleszczenia jest wykres zakleszczenia. Zasymulujmy stan zakleszczenia i zobaczmy odpowiadający mu wykres zakleszczenia.
Na potrzeby tej demonstracji utworzyliśmy tabelę Klient i Zamówienia i wstawiliśmy kilka przykładowych rekordów.
Następnie otworzyliśmy nowe okno zapytania i włączyliśmy globalnie flagę śledzenia.
DBCC traceon(1222,-1)
Po włączeniu flagi śledzenia zakleszczenia rozpoczęliśmy dwie sesje i wykonaliśmy zapytanie w następującej kolejności:
W tym przykładzie SQL Server wybiera ofiarę zakleszczenia (identyfikator sesji 65) i zabija transakcję. Pobierzmy wykres zakleszczenia z rozszerzonej sesji zdarzeń system_health.
To zapytanie daje nam zakleszczony kod XML, który wymaga doświadczonego administratora baz danych do interpretacji informacji.
Zapisujemy ten zakleszczony kod XML za pomocą rozszerzenia .XDL, a kiedy otwieramy plik XDL w SSMS, otrzymujemy wykres zakleszczenia pokazany poniżej.
Ten wykres impasu zawiera następujące informacje:
Reprezentuje ofiarę zakleszczenia, przekreślając owal na wykresie zakleszczenia.
Informacje o zakleszczeniu programu SQL Server można przechwycić w następujący sposób:
1) Zakleszczenie wyszukiwania zakładek
Wyszukiwanie zakładek jest często spotykanym zakleszczeniem w programie SQL Server. Występuje z powodu konfliktu między instrukcją select a instrukcjami DML (insert, update i delete). Zwykle SQL Server wybiera instrukcję select jako ofiarę impasu, ponieważ nie powoduje zmian danych, a wycofanie jest szybkie. Aby uniknąć wyszukiwania zakładek, możesz użyć indeksu obejmującego. Możesz również użyć podpowiedzi do zapytania NOLOCK w instrukcjach select, ale odczytuje ona niezatwierdzone dane.
2) Zakleszczenie przy skanowaniu zasięgu
Czasami używamy SERIALIZOWAlnego poziomu izolacji na poziomie serwera lub na poziomie sesji. Jest to restrykcyjny poziom izolacji do kontroli współbieżności i może tworzyć blokady skanowania zakresu zamiast blokad na poziomie strony lub wiersza. Na poziomie izolacji SERIALIZABLE użytkownicy nie mogą odczytywać danych, jeśli są one zmodyfikowane, ale czekają na zatwierdzenie w transakcji. Podobnie, jeśli transakcja odczytuje dane, inna transakcja nie może ich modyfikować. Zapewnia najniższą współbieżność, więc powinniśmy używać tego poziomu izolacji w określonych wymaganiach aplikacji.
3) Kaskadowe zakleszczenie ograniczeń
SQL Server używa relacji nadrzędny-podrzędny między tabelami przy użyciu ograniczeń klucza obcego. W tym scenariuszu, jeśli zaktualizujemy lub usuniemy rekord z tabeli nadrzędnej, konieczne będą blokady tabeli podrzędnej, aby zapobiec rekordom osieroconym. Aby wyeliminować te zakleszczenia, należy zawsze najpierw modyfikować dane w tabeli podrzędnej, a następnie dane nadrzędne. Możesz także pracować bezpośrednio z tabelą nadrzędną za pomocą opcji DELETE CASCADE lub UPDATE CASCADE. Powinieneś także utworzyć odpowiednie indeksy w kolumnach kluczy obcych.
4) Zakleszczenie równoległości między zapytaniami
Gdy użytkownik prześle zapytanie do silnika zapytań SQL, optymalizator zapytań tworzy zoptymalizowany plan wykonania. Może wykonać zapytanie w kolejności szeregowej lub równoległej w zależności od kosztu zapytania, maksymalnego stopnia równoległości (MAXDOP) i progu kosztu równoległości.
W trybie równoległości SQL Server przypisuje wiele wątków. Czasami w przypadku dużego zapytania w trybie równoległości te wątki zaczynają się wzajemnie blokować. W końcu zamienia się w impas. W takim przypadku należy przejrzeć plan wykonania oraz MAXDOP i próg kosztów dla konfiguracji równoległości. Możesz również określić MAXDOP na poziomie sesji, aby rozwiązać problem zakleszczenia.
5) Zakleszczenie kolejności obiektów w odwrotnej kolejności
W tego typu zakleszczeniu wiele transakcji uzyskuje dostęp do obiektów w innej kolejności w języku T-SQL. Powoduje to blokowanie zasobów dla każdej sesji i przekształca je w zakleszczenie. Zawsze chcesz uzyskać dostęp do obiektów w logicznej kolejności, aby nie doprowadzić do sytuacji impasu.
Zakleszczenia to naturalny mechanizm w SQL Server, który pozwala uniknąć blokowania sesji i oczekiwania na inne zasoby. Należy przechwytywać zapytania o zakleszczeniu i optymalizować je tak, aby nie kolidowały ze sobą. Ważne jest, aby przechwycić blokadę na krótki okres i zwolnić ją, aby inne zapytania mogły z niej skutecznie korzystać.
Występują zakleszczenia programu SQL Server i chociaż program SQL Server wewnętrznie obsługuje sytuacje zakleszczeń, należy starać się je minimalizować, gdy tylko jest to możliwe. Niektóre z najlepszych sposobów na wyeliminowanie zakleszczeń to utworzenie indeksu, zastosowanie zmian w kodzie aplikacji lub dokładne sprawdzenie zasobów na wykresie zakleszczeń. Więcej wskazówek, jak uniknąć zakleszczeń SQL, znajdziesz w naszym poście:Unikanie zakleszczeń SQL dzięki dostrajaniu zapytań.Zakleszczenia w SQL Server przy użyciu wykresów zakleszczeń
CREATE TABLE Customer
(ID INT IDENTITY(1,1), CustomerName VARCHAR(20))
GO
CREATE TABLE Orders
(OrderID INT IDENTITY(1,1), ProductName VARCHAR(50))
GO
INSERT INTO Customer(CustomerName) VALUES ('Rajendra')
Go 100
S INSERT INTO Orders(ProductName) VALUES ('Laptop')
Go 100
SELECT XEvent.query('(event/data/value/deadlock)[1]') AS DeadlockGraph
FROM (
SELECT XEvent.query('.') AS XEvent
FROM (
SELECT CAST(target_data AS XML) AS TargetData
FROM sys.dm_xe_session_targets st
INNER JOIN sys.dm_xe_sessions s
ON s.address = st.event_session_address
WHERE s.NAME = ‘system_health’
AND st.target_name = ‘ring_buffer’
) AS Data
CROSS APPLY TargetData.nodes('RingBufferTarget/event[@name="xml_deadlock_report"]
') AS XEventData(XEvent)
) AS source;
5 rodzajów zakleszczeń w SQL Server
Przydatne sposoby unikania i minimalizowania zakleszczeń w SQL Server
Zagadnienia dotyczące zakleszczenia programu SQL Server