Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Anatomia zakleszczeń w SQL Server i najlepsze sposoby ich uniknięcia

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

Zakleszczenia w SQL Server przy użyciu wykresów zakleszczeń

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.

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

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:

  • Pierwsza sesja rozpoczyna transakcję w celu aktualizacji tabeli klientów dla identyfikatora klienta 1.
  • Druga sesja rozpoczyna transakcję w celu aktualizacji tabeli zamówień dla zamówienia o identyfikatorze 10.
  • Pierwsza sesja próbuje zaktualizować tabelę zamówień dla tego samego identyfikatora zamówienia 10. Druga sesja już blokuje ten wiersz. Sesja 1 jest zablokowana z powodu blokad utrzymywanych przez sesję 2.
  • Teraz dla sesji 2 chcemy zaktualizować tabelę klientów o identyfikator klienta 1. Generuje to sytuację impasu, w której zarówno sesje o identyfikatorze 63, jak i identyfikatorze 65 nie mogą się rozwijać.

W tym przykładzie SQL Server wybiera ofiarę zakleszczenia (identyfikator sesji 65) i zabija transakcję. Pobierzmy wykres zakleszczenia z rozszerzonej sesji zdarzeń system_health.

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;

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:

  • Węzły procesowe:  W owalu otrzymujesz informacje związane z procesem.
  • Węzły zasobów:  Węzły zasobów (square box) dostarczają informacji o obiektach biorących udział w transakcjach wraz z blokadami. W tym przykładzie pokazuje blokady RID, ponieważ nie mamy żadnych indeksów dla obu tabel.
  • Krawędzie:  Krawędź łączy węzeł procesu i węzeł zasobów. Pokazuje właściciela zasobu i tryb blokady żądania.

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:

  • Profil serwera SQL
  • Rozszerzone zdarzenia SQL Server
  • Dzienniki błędów SQL Server
  • Domyślne ślady w SQL Server

5 rodzajów zakleszczeń w SQL Server

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.

Przydatne sposoby unikania i minimalizowania zakleszczeń w SQL Server

  • Staraj się, aby transakcje były krótkie; pozwoli to uniknąć blokowania transakcji przez długi czas.
  • Dostęp do obiektów w podobny logiczny sposób w wielu transakcjach.
  • Utwórz indeks pokrycia, aby zmniejszyć możliwość wystąpienia impasu.
  • Utwórz indeksy zgodne z kolumnami kluczy obcych. W ten sposób możesz wyeliminować zakleszczenia spowodowane kaskadową integralnością referencyjną.
  • Ustaw priorytety zakleszczenia za pomocą zmiennej sesji SET DEADLOCK_PRIORITY. Jeśli ustawisz priorytet zakleszczenia, SQL Server zabije sesję z najniższym priorytetem zakleszczenia.
  • Wykorzystaj obsługę błędów za pomocą bloków try-catch. Możesz złapać błąd zakleszczenia i ponownie uruchomić transakcję w przypadku ofiary zakleszczenia.
  • Zmień poziom izolacji na READ COMMITTED SNAPSHOT ISOLATION lub SNAPSHOT ISOLATION. Zmienia to mechanizm blokowania SQL Server. Chociaż należy zachować ostrożność przy zmianie poziomu izolacji, ponieważ może to negatywnie wpłynąć na inne zapytania.

Zagadnienia dotyczące zakleszczenia programu SQL Server

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ń.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak edytować tabelę, aby włączyć opcję CASCADE DELETE?

  2. Wyrażenie regularne MSSQL

  3. Koncepcje projektowania bazy danych za pomocą programu SQL Server Management Studio (SSMS) część 1

  4. Jak utworzyć tabelę z ograniczeniem klucza obcego w SQL Server — samouczek SQL Server / TSQL, część 66

  5. Jak uzyskać informacje statystyczne programu SQL Server za pomocą funkcji statystycznych systemu?