Analizowanie i zapobieganie zakleszczeniom w usłudze Azure SQL Database

Dotyczy:Azure SQL Database

W tym artykule wyjaśniono, jak identyfikować zakleszczenia w usłudze Azure SQL Database, używać wykresów zakleszczeń i magazynu zapytań do identyfikowania zapytań w zakleszczeniu oraz planować i testować zmiany w celu zapobiegania występowaniu ponownych zakleszczeń.

Ten artykuł koncentruje się na identyfikowaniu i analizowaniu zakleszczeń ze względu na rywalizację o blokadę. Dowiedz się więcej o innych typach zakleszczeń w zasobach, które mogą zakleszczeć.

Jak występują zakleszczenia w usłudze Azure SQL Database

Każda nowa baza danych w usłudze Azure SQL Database ma domyślnie włączone ustawienie bazy danych migawki zatwierdzonej do odczytu (RCSI). Blokowanie między sesjami odczytu danych i sesji zapisywania danych jest zminimalizowane w obszarze RCSI, co używa przechowywania wersji wierszy w celu zwiększenia współbieżności. Jednak blokowanie i zakleszczenia mogą nadal występować w bazach danych w usłudze Azure SQL Database, ponieważ:

  • Zapytania modyfikujące dane mogą blokować się nawzajem.
  • Zapytania mogą być uruchamiane na poziomach izolacji, które zwiększają blokowanie. Poziomy izolacji można określić za pomocą metod biblioteki klienta, wskazówek dotyczących zapytań lub instrukcji SET w języku Transact-SQL.
  • Funkcja RCSI może być wyłączona, co powoduje, że baza danych może używać blokad udostępnionych (S) w celu ochrony instrukcji SELECT uruchamianych na poziomie izolacji zatwierdzonej do odczytu. Może to zwiększyć blokowanie i zakleszczenia.

Przykład zakleszczenia

Zakleszczenie występuje, gdy co najmniej dwa zadania trwale blokują się nawzajem, ponieważ każde zadanie ma blokadę zasobu, który próbuje zablokować drugie zadanie. Zakleszczenie jest również nazywane cykliczną zależnością: w przypadku zakleszczenia dwóch zadań transakcja A ma zależność od transakcji B, a transakcja B zamyka koło, mając zależność od transakcji A.

Na przykład:

  1. Sesja A rozpoczyna transakcję jawną i uruchamia instrukcję aktualizacji, która uzyskuje blokadę aktualizacji (U) w jednym wierszu w tabeliSalesLT.Product, który jest konwertowany na blokadę wyłączną (X).
  2. Sesja B uruchamia instrukcję aktualizacji, która modyfikuje tabelę SalesLT.ProductDescription . Instrukcja update łączy się z tabelą, SalesLT.Product aby znaleźć poprawne wiersze do zaktualizowania.
    • Sesja B uzyskuje blokadę aktualizacji (U) na 72 wierszach w SalesLT.ProductDescription tabeli.
    • Sesja B wymaga udostępnionej blokady wierszy w tabeli SalesLT.Product, w tym wiersza zablokowanego przez sesję A. Sesja B jest zablokowana w dniu SalesLT.Product.
  3. Sesja A kontynuuje transakcję, a teraz uruchamia aktualizację względem SalesLT.ProductDescription tabeli. Sesja A jest blokowana przez sesję B w dniu SalesLT.ProductDescription.

Diagram przedstawiający dwie sesje w impasie. Każda sesja jest właścicielem zasobu, którego potrzebuje inny proces, aby kontynuować.

Wszystkie transakcje w blokadzie będą czekać przez nieokreślony czas, chyba że jedna z uczestniczących transakcji zostanie wycofana, na przykład z powodu zakończenia jej transakcji.

Monitor zablokowania aparatu bazy danych okresowo sprawdza pod kątem zadań, które są blokowane. Jeśli monitor zakleszczenia wykryje cykliczną zależność, wybiera jedno z zadań jako ofiarę i kończy transakcję z błędem 1205" Transakcja (identyfikator procesu N) została zakleszona w przypadku zablokowanych zasobów z innym procesem i została wybrana jako ofiara zakleszczenia. Uruchom ponownie transakcję". Przerwanie zakleszczenia w ten sposób pozwala innym zadaniom lub zakleszczeniom zakończyć transakcje.

Uwaga

Dowiedz się więcej o kryteriach wybierania ofiary zakleszczenia w sekcji lista procesów zakleszczenia w tym artykule.

Omówienie zakleszczenia między dwiema sesjami. Jedna sesja została wybrana jako ofiara impasu.

Aplikacja z transakcją wybraną jako ofiara zakleszczenia powinna ponowić próbę transakcji, która zwykle kończy się po zakończeniu drugiej transakcji lub transakcji zaangażowanych w zakleszczenie.

Najlepszym rozwiązaniem jest wprowadzenie krótkiego, losowego opóźnienia przed ponowną próbą, aby uniknąć ponownego napotkania tego samego zakleszczenia. Dowiedz się więcej na temat projektowania logiki ponawiania prób dla błędów przejściowych.

Domyślny poziom izolacji w usłudze Azure SQL Database

Nowe bazy danych w usłudze Azure SQL Database domyślnie włączają migawkę zatwierdzoną do odczytu (RCSI). RCSI zmienia zachowanie poziomu izolacji zatwierdzonej do odczytu, aby używać przechowywania wersji wierszy w celu zapewnienia spójności na poziomie instrukcji bez używania udostępnionych blokad (S) dla instrukcji SELECT.

Z włączoną funkcją RCSI:

  • Instrukcje odczytujące dane nie blokują instrukcji modyfikujących dane.
  • Instrukcje modyfikujące dane nie blokują instrukcji odczytu danych.

Poziom izolacji migawek jest również domyślnie włączony dla nowych baz danych w usłudze Azure SQL Database. Izolacja migawki to dodatkowy poziom izolacji oparty na wierszach, który zapewnia spójność na poziomie transakcji dla danych i który używa wersji wierszy do wybierania wierszy do aktualizacji. Aby użyć izolacji migawki, zapytania lub połączenia muszą jawnie ustawić poziom izolacji transakcji na SNAPSHOTwartość . Można to zrobić tylko wtedy, gdy dla bazy danych jest włączona izolacja migawki.

Możesz określić, czy izolacja RCSI i/lub migawki jest włączona w języku Transact-SQL. Połączenie do bazy danych w usłudze Azure SQL Database i uruchom następujące zapytanie:

SELECT name, is_read_committed_snapshot_on, snapshot_isolation_state_desc
FROM sys.databases
WHERE name = DB_NAME();
GO

Jeśli funkcja RCSI jest włączona, kolumna is_read_committed_snapshot_on zwróci wartość 1. Jeśli izolacja migawki jest włączona, kolumna snapshot_isolation_state_desc zwróci wartość WŁĄCZONE.

Jeśli usługa RCSI została wyłączona dla bazy danych w usłudze Azure SQL Database, przed ponownym włączeniem sprawdź, dlaczego funkcja RCSI została wyłączona. Kod aplikacji mógł zostać napisany, spodziewając się, że zapytania odczytujące dane będą blokowane przez zapytania zapisujące dane, co powoduje nieprawidłowe wyniki z warunków wyścigu po włączeniu funkcji RCSI.

Interpretowanie zdarzeń zakleszczenia

Zdarzenie zakleszczenia jest emitowane po wykryciu zakleszczenia przez menedżera zakleszczenia w usłudze Azure SQL Database i wybraniu transakcji jako ofiary. Innymi słowy, jeśli skonfigurujesz alerty dotyczące zakleszczeń, powiadomienie zostanie wyzwolone po rozwiązaniu pojedynczego zakleszczenia. Nie ma żadnych działań użytkownika, które należy podjąć w przypadku tego zakleszczenia. Aplikacje powinny być zapisywane w celu uwzględnienia logiki ponawiania prób, tak aby były one automatycznie kontynuowane po otrzymaniu błędu 1205: "Transakcja (identyfikator procesu N) została zakleszona w zasobach blokady z innym procesem i została wybrana jako ofiara zakleszczenia. Uruchom ponownie transakcję".

Warto jednak skonfigurować alerty, ponieważ zakleszczenia mogą się powtarzać. Alerty zakleszczenia umożliwiają sprawdzenie, czy w bazie danych występuje wzorzec powtarzających się zakleszczeń, w którym przypadku możesz podjąć działania, aby zapobiec ponownemu zakleszczeniom. Dowiedz się więcej na temat alertów w sekcji Monitorowanie i alerty dotyczące zakleszczeń w tym artykule.

Najważniejsze metody zapobiegania zakleszczeniom

Najniższym podejściem do ryzyka zapobiegania zakleszczeniom z reoccurringu jest zazwyczaj dostrajanie indeksów nieklastrowanych w celu optymalizacji zapytań związanych z zakleszczeniem.

  • Ryzyko jest niskie w przypadku tego podejścia, ponieważ dostrajanie indeksów nieklastrowanych nie wymaga zmian w kodzie zapytania, co zmniejsza ryzyko błędu użytkownika podczas ponownego zapisywania języka Transact-SQL, co powoduje zwrócenie użytkownikowi nieprawidłowych danych.
  • Skuteczne dostrajanie indeksu nieklastrowanego pomaga wyszukiwać dane w celu bardziej wydajnego odczytywania i modyfikowania. Dzięki zmniejszeniu ilości danych, do których musi uzyskać dostęp zapytanie, prawdopodobieństwo blokowania jest zmniejszane i często można zapobiec zakleszczeniom.

W niektórych przypadkach tworzenie lub dostrajanie indeksu klastrowanego może zmniejszyć blokowanie i zakleszczenia. Ponieważ indeks klastrowany jest uwzględniany we wszystkich nieklastrowanych definicjach indeksu, tworzenie lub modyfikowanie indeksu klastrowanego może być operacją intensywnie korzystającą z operacji we/wy i czasochłonną operacją na większych tabelach z istniejącymi indeksami nieklastrowanym. Dowiedz się więcej na temat wytycznych dotyczących projektowania indeksu klastrowanego.

Gdy dostrajanie indeksu nie powiedzie się w zapobieganiu zakleszczeniom, dostępne są inne metody:

  • Jeśli zakleszczenie występuje tylko wtedy, gdy określony plan zostanie wybrany dla jednego z zapytań zaangażowanych w zakleszczenie, wymuszanie planu zapytania z magazynem zapytań może uniemożliwić ponowne zakleszczenia.
  • Ponowne zapisywanie języka Transact-SQL dla co najmniej jednej transakcji zaangażowanej w zakleszczenie może również pomóc w zapobieganiu zakleszczeniom. Podzielenie jawnych transakcji na mniejsze transakcje wymaga starannego kodowania i testowania, aby zapewnić ważność danych podczas współbieżnych modyfikacji.

Dowiedz się więcej o każdym z tych podejść w sekcji Zapobieganie zakleszczeniom w tym artykule.

Monitorowanie zakleszczeń i zgłaszanie alertów

W tym artykule użyjemy przykładowej AdventureWorksLT bazy danych, aby skonfigurować alerty dotyczące zakleszczenia, spowodować przykład zakleszczenia, przeanalizować wykres zakleszczenia dla przykładowego zakleszczenia i przetestować zmiany, aby zapobiec ponownemu zakleszczeniu.

W tym artykule użyjemy klienta programu SQL Server Management Studio (SSMS), ponieważ zawiera on funkcje wyświetlania wykresów zakleszczenia w trybie interaktywnym wizualizacji. Możesz użyć innych klientów, takich jak Azure Data Studio , aby postępować zgodnie z przykładami, ale możesz wyświetlać tylko wykresy zakleszczenia jako XML.

Tworzenie bazy danych AdventureWorksLT

Aby postępować zgodnie z przykładami, utwórz nową bazę danych w usłudze Azure SQL Database i wybierz pozycję Przykładowe dane jako źródło danych.

Aby uzyskać szczegółowe instrukcje dotyczące tworzenia za AdventureWorksLT pomocą witryny Azure Portal, interfejsu wiersza polecenia platformy Azure lub programu PowerShell, wybierz wybrane podejście w przewodniku Szybki start: Tworzenie pojedynczej bazy danych usługi Azure SQL Database.

Konfigurowanie alertów zakleszczenia w witrynie Azure Portal

Aby skonfigurować alerty dotyczące zdarzeń zakleszczenia, wykonaj kroki opisane w artykule Tworzenie alertów dla usług Azure SQL Database i Azure Synapse Analytics przy użyciu witryny Azure Portal.

Wybierz pozycję Zakleszczenia jako nazwę sygnału alertu. Skonfiguruj grupę akcji, aby powiadomić Cię przy użyciu wybranej metody, takiej jak typ akcji Email/SMS/Push/Voice.

Zbieranie wykresów zakleszczenia w usłudze Azure SQL Database przy użyciu zdarzeń rozszerzonych

Wykresy zakleszczenia są bogatym źródłem informacji dotyczących procesów i blokad związanych z impasem. Aby zebrać wykresy zakleszczenia z zdarzeniami rozszerzonymi (XEvents) w usłudze Azure SQL Database, przechwyć sqlserver.database_xml_deadlock_report zdarzenie.

Wykresy zakleszczenia można zbierać z elementami XEvents przy użyciu docelowego buforu pierścieniowego lub docelowego pliku zdarzeń. Zagadnienia dotyczące wybierania odpowiedniego typu docelowego zostały podsumowane w poniższej tabeli:

Metoda Świadczenia Kwestie wymagające rozważenia Scenariusze użycia
Element docelowy buforu pierścieniowego
  • Prosta konfiguracja tylko z językiem Transact-SQL.
  • Dane zdarzenia są czyszczone, gdy sesja XEvents zostanie zatrzymana z jakiegokolwiek powodu, na przykład przełączeniu bazy danych w tryb offline lub przełączeniu bazy danych w tryb failover.
  • Zasoby bazy danych są używane do obsługi danych w buforze pierścieniowym i wykonywania zapytań dotyczących danych sesji.
  • Zbieranie przykładowych danych śledzenia na potrzeby testowania i uczenia się.
  • Utwórz dla potrzeb krótkoterminowych, jeśli nie można natychmiast skonfigurować sesji przy użyciu obiektu docelowego pliku zdarzeń.
  • Użyj jako "lądowiska" dla danych śledzenia, gdy skonfigurowaliśmy zautomatyzowany proces utrwalania danych śledzenia w tabeli.
Miejsce docelowe pliku zdarzenia
  • Utrwala dane zdarzeń do obiektu blob w usłudze Azure Storage, dzięki czemu dane są dostępne nawet po zatrzymaniu sesji.
  • Pliki zdarzeń mogą być pobierane z witryny Azure Portal lub Eksplorator usługi Azure Storage i analizowane lokalnie, co nie wymaga używania zasobów bazy danych do wykonywania zapytań dotyczących danych sesji.
  • Konfiguracja jest bardziej złożona i wymaga konfiguracji kontenera usługi Azure Storage i poświadczeń o zakresie bazy danych.
  • Ogólne użycie, gdy dane zdarzeń mają być utrwalane nawet po zatrzymaniu sesji zdarzeń.
  • Chcesz uruchomić ślad, który generuje większe ilości danych zdarzenia, niż chcesz zachować w pamięci.

Wybierz typ docelowy, którego chcesz użyć:

Cel buforu pierścieniowego jest wygodny i łatwy do skonfigurowania, ale ma ograniczoną pojemność, co może spowodować utratę starszych zdarzeń. Bufor pierścieniowy nie utrwala zdarzeń w magazynie, a obiekt docelowy buforu pierścienia jest czyszczone po zatrzymaniu sesji XEvents. Oznacza to, że wszystkie zebrane elementy XEvent nie będą dostępne w przypadku ponownego uruchomienia aparatu bazy danych z jakiegokolwiek powodu, takiego jak tryb failover. Cel buforu pierścieniowego najlepiej nadaje się do uczenia się i krótkoterminowych potrzeb, jeśli nie masz możliwości natychmiastowego skonfigurowania sesji XEvents w obiekcie docelowym pliku zdarzeń.

Ten przykładowy kod tworzy sesję XEvents, która przechwytuje wykresy zakleszczenia w pamięci przy użyciu docelowego buforu pierścienia. Maksymalna ilość pamięci dozwolonej dla docelowego buforu pierścieniowego wynosi 4 MB, a sesja zostanie automatycznie uruchomiona, gdy baza danych zostanie przełączona w tryb online, na przykład po przejściu w tryb failover.

Aby utworzyć, a następnie uruchomić sesję XEvents dla sqlserver.database_xml_deadlock_report zdarzenia, które zapisuje w docelowym buforze pierścienia, połącz się z bazą danych i uruchom następujący kod Transact-SQL:

CREATE EVENT SESSION [deadlocks] ON DATABASE 
ADD EVENT sqlserver.database_xml_deadlock_report
ADD TARGET package0.ring_buffer 
WITH (STARTUP_STATE=ON, MAX_MEMORY=4 MB)
GO

ALTER EVENT SESSION [deadlocks] ON DATABASE
    STATE = START;
GO

Przyczyna zakleszczenia w AdventureWorksLT

Uwaga

Ten przykład działa w AdventureWorksLT bazie danych z domyślnym schematem i danymi po włączeniu wersji RCSI. Aby uzyskać instrukcje dotyczące tworzenia bazy danych, zobacz Tworzenie bazy danych AdventureWorksLT.

Aby spowodować zakleszczenie, należy połączyć dwie sesje z bazą AdventureWorksLT danych. Te sesje będą nazywane sesjami A i sesją B.

W sesji A uruchom następujące polecenie Języka Transact-SQL. Ten kod rozpoczyna jawną transakcję i uruchamia pojedynczą instrukcję, która aktualizuje tabelęSalesLT.Product. W tym celu transakcja uzyskuje blokadę aktualizacji (U) w jednym wierszu w tabeliSalesLT.Product, który jest konwertowany na blokadę wyłączną (X). Pozostawimy otwartą transakcję.

BEGIN TRAN

    UPDATE SalesLT.Product SET SellEndDate = SellEndDate + 1
        WHERE Color = 'Red';

Teraz w sesji B uruchom następujący kod Transact-SQL. Ten kod nie rozpoczyna jawnie transakcji. Zamiast tego działa w trybie automatycznej transakcji. Ta instrukcja aktualizuje tabelę SalesLT.ProductDescription . Aktualizacja spowoduje wycofanie blokady aktualizacji (U) na 72 wierszach w SalesLT.ProductDescription tabeli. Zapytanie łączy się z innymi tabelami, w tym z tabelą SalesLT.Product .

UPDATE SalesLT.ProductDescription SET Description = Description
    FROM SalesLT.ProductDescription as pd
    JOIN SalesLT.ProductModelProductDescription as pmpd on
        pd.ProductDescriptionID = pmpd.ProductDescriptionID
    JOIN SalesLT.ProductModel as pm on
        pmpd.ProductModelID = pm.ProductModelID
    JOIN SalesLT.Product as p on
        pm.ProductModelID=p.ProductModelID
    WHERE p.Color = 'Silver';

Aby ukończyć tę aktualizację, sesja B wymaga blokady udostępnionej (S) w wierszach w tabeli SalesLT.Product, w tym wiersza zablokowanego przez sesję A. Sesja B zostanie zablokowana w dniu SalesLT.Product.

Wróć do sesji A. Uruchom następującą instrukcję języka Transact-SQL. Spowoduje to uruchomienie drugiej instrukcji UPDATE w ramach otwartej transakcji.

    UPDATE SalesLT.ProductDescription SET Description = Description
        FROM SalesLT.ProductDescription as pd
        JOIN SalesLT.ProductModelProductDescription as pmpd on
            pd.ProductDescriptionID = pmpd.ProductDescriptionID
        JOIN SalesLT.ProductModel as pm on
            pmpd.ProductModelID = pm.ProductModelID
        JOIN SalesLT.Product as p on
            pm.ProductModelID=p.ProductModelID
        WHERE p.Color = 'Red';

Druga instrukcja aktualizacji w sesji A zostanie zablokowana przez sesję B w pliku SalesLT.ProductDescription.

Sesja A i Sesja B wzajemnie się blokują. Żadna transakcja nie może kontynuować, ponieważ każda z nich potrzebuje zasobu zablokowanego przez drugą.

Po kilku sekundach monitor zakleszczenia zidentyfikuje, że transakcje w sesji A i sesji B wzajemnie się blokują i że żaden z nich nie może poczynić postępów. Powinna pojawić się impas, a sesja A wybrana jako ofiara zakleszczenia. W sesji A zostanie wyświetlony komunikat o błędzie z tekstem podobnym do następującego:

Msg 1205, Level 13, State 51, Line 7 Transaction (Identyfikator procesu 91) został zakleszczone w zasobach blokady z innym procesem i został wybrany jako ofiara zakleszczenia. Uruchom ponownie transakcję.

Sesja B zakończy się pomyślnie.

W przypadku skonfigurowania alertów zakleszczenia w witrynie Azure Portal powinno zostać wyświetlone powiadomienie wkrótce po wystąpieniu zakleszczenia.

Wyświetlanie wykresów zakleszczenia z sesji XEvents

Jeśli skonfigurowano sesję XEvents w celu zbierania zakleszczeń i zakleszczenia wystąpiły po rozpoczęciu sesji, możesz wyświetlić interaktywną grafikę wykresu zakleszczenia, a także kod XML dla grafu zakleszczenia.

Dostępne są różne metody uzyskiwania informacji o zakleszczeniach dla obiektów docelowych buforu pierścienia i obiektów docelowych plików zdarzeń. Wybierz element docelowy używany dla sesji XEvents:

Jeśli skonfigurujesz sesję XEvents zapisu w buforze pierścienia, możesz wykonywać zapytania dotyczące zakleszczenia przy użyciu następującego języka Transact-SQL. Przed uruchomieniem zapytania zastąp wartość @tracename nazwą sesji xEvents.

DECLARE @tracename sysname = N'deadlocks';

WITH ring_buffer AS (
    SELECT CAST(target_data AS XML) as rb
    FROM sys.dm_xe_database_sessions AS s 
    JOIN sys.dm_xe_database_session_targets AS t 
        ON CAST(t.event_session_address AS BINARY(8)) = CAST(s.address AS BINARY(8))
    WHERE s.name = @tracename and
    t.target_name = N'ring_buffer'
), dx AS (
    SELECT 
        dxdr.evtdata.query('.') as deadlock_xml_deadlock_report
    FROM ring_buffer
    CROSS APPLY rb.nodes('/RingBufferTarget/event[@name=''database_xml_deadlock_report'']') AS dxdr(evtdata)
) 
SELECT 
    d.query('/event/data[@name=''deadlock_cycle_id'']/value').value('(/value)[1]', 'int') AS [deadlock_cycle_id],
    d.value('(/event/@timestamp)[1]', 'DateTime2') AS [deadlock_timestamp],
    d.query('/event/data[@name=''database_name'']/value').value('(/value)[1]', 'nvarchar(256)') AS [database_name],
    d.query('/event/data[@name=''xml_report'']/value/deadlock') AS deadlock_xml,
    LTRIM(RTRIM(REPLACE(REPLACE(d.value('.', 'nvarchar(2000)'),CHAR(10),' '),CHAR(13),' '))) as query_text
FROM dx
CROSS APPLY deadlock_xml_deadlock_report.nodes('(/event/data/value/deadlock/process-list/process/inputbuf)') AS ib(d)
ORDER BY [deadlock_timestamp] DESC;
GO

Wyświetlanie i zapisywanie grafu zakleszczenia w formacie XML

Wyświetlanie wykresu zakleszczenia w formacie XML umożliwia skopiowanie inputbuffer instrukcji języka Transact-SQL zaangażowanych w zakleszczenie. Możesz również przeanalizować zakleszczenia w formacie tekstowym.

Jeśli użyto zapytania Transact-SQL w celu zwrócenia informacji o grafie zakleszczenia, aby wyświetlić kod XML grafu zakleszczenia, wybierz wartość w deadlock_xml kolumnie z dowolnego wiersza, aby otworzyć kod XML grafu zakleszczenia w nowym oknie w programie SSMS.

Kod XML dla tego przykładowego grafu zakleszczenia to:

<deadlock>
  <victim-list>
    <victimProcess id="process24756e75088" />
  </victim-list>
  <process-list>
    <process id="process24756e75088" taskpriority="0" logused="6528" waitresource="KEY: 8:72057594045202432 (98ec012aa510)" waittime="192" ownerId="1011123" transactionname="user_transaction" lasttranstarted="2022-03-08T15:44:43.490" XDES="0x2475c980428" lockMode="U" schedulerid="3" kpid="30192" status="suspended" spid="89" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2022-03-08T15:44:49.250" lastbatchcompleted="2022-03-08T15:44:49.210" lastattention="1900-01-01T00:00:00.210" clientapp="Microsoft SQL Server Management Studio - Query" hostname="LAPTOP-CHRISQ" hostpid="16716" loginname="chrisqpublic" isolationlevel="read committed (2)" xactid="1011123" currentdb="8" currentdbname="AdventureWorksLT" lockTimeout="4294967295" clientoption1="671096864" clientoption2="128056">
      <executionStack>
        <frame procname="unknown" queryhash="0xef52b103e8b9b8ca" queryplanhash="0x02b0f58d7730f798" line="1" stmtstart="2" stmtend="792" sqlhandle="0x02000000c58b8f1e24e8f104a930776e21254b1771f92a520000000000000000000000000000000000000000">
unknown    </frame>
      </executionStack>
      <inputbuf>
    UPDATE SalesLT.ProductDescription SET Description = Description
        FROM SalesLT.ProductDescription as pd
        JOIN SalesLT.ProductModelProductDescription as pmpd on
            pd.ProductDescriptionID = pmpd.ProductDescriptionID
        JOIN SalesLT.ProductModel as pm on
            pmpd.ProductModelID = pm.ProductModelID
        JOIN SalesLT.Product as p on
            pm.ProductModelID=p.ProductModelID
        WHERE p.Color = 'Red'   </inputbuf>
    </process>
    <process id="process2476d07d088" taskpriority="0" logused="11360" waitresource="KEY: 8:72057594045267968 (39e18040972e)" waittime="2641" ownerId="1013536" transactionname="UPDATE" lasttranstarted="2022-03-08T15:44:46.807" XDES="0x2475ca80428" lockMode="S" schedulerid="2" kpid="94040" status="suspended" spid="95" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2022-03-08T15:44:46.807" lastbatchcompleted="2022-03-08T15:44:46.760" lastattention="1900-01-01T00:00:00.760" clientapp="Microsoft SQL Server Management Studio - Query" hostname="LAPTOP-CHRISQ" hostpid="16716" loginname="chrisqpublic" isolationlevel="read committed (2)" xactid="1013536" currentdb="8" currentdbname="AdventureWorksLT" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
      <executionStack>
        <frame procname="unknown" queryhash="0xef52b103e8b9b8ca" queryplanhash="0x02b0f58d7730f798" line="1" stmtstart="2" stmtend="798" sqlhandle="0x020000002c85bb06327c0852c0be840fc1e30efce2b7c8090000000000000000000000000000000000000000">
unknown    </frame>
      </executionStack>
      <inputbuf>
    UPDATE SalesLT.ProductDescription SET Description = Description
        FROM SalesLT.ProductDescription as pd
        JOIN SalesLT.ProductModelProductDescription as pmpd on
            pd.ProductDescriptionID = pmpd.ProductDescriptionID
        JOIN SalesLT.ProductModel as pm on
            pmpd.ProductModelID = pm.ProductModelID
        JOIN SalesLT.Product as p on
            pm.ProductModelID=p.ProductModelID
        WHERE p.Color = 'Silver';   </inputbuf>
    </process>
  </process-list>
  <resource-list>
    <keylock hobtid="72057594045202432" dbid="8" objectname="9e011567-2446-4213-9617-bad2624ccc30.SalesLT.ProductDescription" indexname="PK_ProductDescription_ProductDescriptionID" id="lock2474df12080" mode="U" associatedObjectId="72057594045202432">
      <owner-list>
        <owner id="process2476d07d088" mode="U" />
      </owner-list>
      <waiter-list>
        <waiter id="process24756e75088" mode="U" requestType="wait" />
      </waiter-list>
    </keylock>
    <keylock hobtid="72057594045267968" dbid="8" objectname="9e011567-2446-4213-9617-bad2624ccc30.SalesLT.Product" indexname="PK_Product_ProductID" id="lock2474b588580" mode="X" associatedObjectId="72057594045267968">
      <owner-list>
        <owner id="process24756e75088" mode="X" />
      </owner-list>
      <waiter-list>
        <waiter id="process2476d07d088" mode="S" requestType="wait" />
      </waiter-list>
    </keylock>
  </resource-list>
</deadlock>

Aby zapisać graf zakleszczenia jako plik XML:

  1. Wybierz pozycję Plik i Zapisz jako....
  2. Pozostaw wartość Zapisz jako typ jako domyślną wartość Pliki XML (*.xml)
  3. Ustaw nazwę pliku na wybraną nazwę.
  4. Wybierz pozycję Zapisz.

Zapisywanie grafu zakleszczenia jako pliku XDL, który może być wyświetlany interaktywnie w programie SSMS

Wyświetlenie interaktywnej reprezentacji grafu zakleszczenia może być przydatne, aby uzyskać szybki przegląd procesów i zasobów związanych z impasem oraz szybkie identyfikowanie ofiary zakleszczenia.

Aby zapisać wykres zakleszczenia jako plik, który może być wyświetlany graficznie przez program SSMS:

  1. Wybierz wartość w kolumnie deadlock_xml z dowolnego wiersza, aby otworzyć kod XML grafu zakleszczenia w nowym oknie w programie SSMS.

  2. Wybierz pozycję Plik i Zapisz jako....

  3. Ustaw pozycję Zapisz jako typ na Wszystkie pliki.

  4. Ustaw wybraną nazwę pliku z rozszerzeniem na .xdl.

  5. Wybierz pozycję Zapisz.

    Zrzut ekranu programu SSMS przedstawiający zapisywanie pliku XML grafu zakleszczenia w pliku z rozszerzeniem xsd.

  6. Zamknij plik, wybierając ikonę X na karcie w górnej części okna lub wybierając pozycję Plik, a następnie zamknij.

  7. Otwórz ponownie plik w programie SSMS, wybierając pozycję Plik, a następnie otwórz, a następnie pozycję Plik. Wybierz zapisany plik z .xdl rozszerzeniem .

    Wykres zakleszczenia będzie teraz wyświetlany w programie SSMS z wizualną reprezentacją procesów i zasobów zaangażowanych w zakleszczenie.

    Zrzut ekranu przedstawiający plik xdl otwarty w programie SSMS. Wykres zakleszczenia jest wyświetlany graficznie z procesami wskazywanymi przez owalne i zablokowane zasoby jako prostokąty.

Analizowanie zakleszczenia dla usługi Azure SQL Database

Wykres zakleszczenia zwykle ma trzy węzły:

  • Lista ofiar. Identyfikator procesu ofiary zakleszczenia.
  • Lista procesów. Informacje na temat wszystkich procesów związanych z zakleszczeniem. Wykresy zakleszczenia używają terminu "proces" do reprezentowania sesji uruchamianej transakcji.
  • Lista zasobów. Informacje o zasobach powiązanych z zakleszczeniem.

Podczas analizowania zakleszczenia warto przejść przez te węzły.

Lista ofiar zakleszczenia

Lista ofiar zakleszczenia pokazuje proces, który został wybrany jako ofiara impasu. W wizualnej reprezentacji grafu zakleszczenia procesy są reprezentowane przez owalny. Proces ofiary impasu ma "X" narysowany na owalnym.

Zrzut ekranu przedstawiający wizualizację zakleszczenia. Owalu reprezentującego proces wybrany jako ofiara ma naciągnięty znak X.

W widoku XML grafuvictim-list zakleszczenia węzeł podaje identyfikator procesu, który był ofiarą zakleszczenia.

W naszym przykładzie impas identyfikator procesu ofiary to process24756e75088. Możemy użyć tego identyfikatora podczas badania węzłów listy procesów i listy zasobów, aby dowiedzieć się więcej o procesie ofiary i zasobach, które zablokowała lub zażądała blokady.

Lista procesów zakleszczenia

Lista procesów zakleszczenia jest bogatym źródłem informacji o transakcjach związanych z impasem.

Graficzna reprezentacja grafu zakleszczenia przedstawia tylko podzbiór informacji zawartych w grafie zakleszczenia XML. Owalny na wykresie zakleszczenia reprezentują proces i pokazują informacje, w tym:

  • Identyfikator procesu serwera, znany również jako identyfikator sesji lub SPID.

  • Priorytet zakleszczenia sesji. Jeśli dwie sesje mają różne priorytety zakleszczenia, sesja o niższym priorytecie zostanie wybrana jako ofiara zakleszczenia. W tym przykładzie obie sesje mają ten sam priorytet zakleszczenia.

  • Ilość dziennika transakcji używanego przez sesję w bajtach. Jeśli obie sesje mają taki sam priorytet zakleszczenia, monitor zakleszczenia wybiera sesję, która jest tańsza, aby wycofać się jako ofiara zakleszczenia. Koszt jest określany przez porównanie liczby bajtów dziennika zapisanych w tym punkcie w każdej transakcji.

    W naszym przykładzie impas session_id 89 użył mniejszej ilości dziennika transakcji i został wybrany jako ofiara zakleszczenia.

Ponadto można wyświetlić bufor wejściowy ostatniego uruchomienia instrukcji w każdej sesji przed zakleszczeniem, umieszczając wskaźnik myszy nad każdym procesem. Bufor wejściowy pojawi się w etykietce narzędzia.

Zrzut ekranu przedstawiający wykres zakleszczenia wyświetlany wizualnie w programie SSMS. Dwa owalny reprezentują procesy. Zostanie wyświetlona funkcja inputbuff dla jednego procesu.

Dodatkowe informacje są dostępne dla procesów w widoku XML grafu zakleszczenia, w tym:

  • Identyfikowanie informacji dotyczących sesji, takich jak nazwa klienta, nazwa hosta i nazwa logowania.
  • Skrót planu zapytania dla ostatniej instrukcji uruchamiane przez każdą sesję przed zakleszczeniem. Skrót planu zapytania jest przydatny do pobierania dodatkowych informacji o zapytaniu z magazynu zapytań.

W naszym przykładzie zakleszczenia:

  • Widzimy, że obie sesje zostały uruchomione przy użyciu klienta programu SSMS w ramach logowania chrisqpublic .
  • Skrót planu zapytania ostatniego uruchomienia instrukcji przed zakleszczeniem przez naszą ofiarę zakleszczenia jest 0x02b0f58d7730f798. Tekst tej instrukcji można zobaczyć w buforze wejściowym.
  • Skrót planu zapytania ostatniej instrukcji uruchomionej przez drugą sesję w naszej zakleszczenia jest również 0x02b0f58d7730f798. Tekst tej instrukcji można zobaczyć w buforze wejściowym. W takim przypadku oba zapytania mają ten sam skrót planu zapytania, ponieważ zapytania są identyczne, z wyjątkiem wartości literału używanej jako predykat równości.

Użyjemy tych wartości w dalszej części tego artykułu, aby znaleźć dodatkowe informacje w magazynie zapytań.

Ograniczenia buforu wejściowego na liście procesów zakleszczenia

Istnieją pewne ograniczenia dotyczące informacji o buforze wejściowym na liście procesów zakleszczenia.

Tekst zapytania może zostać obcięty w buforze wejściowym. Bufor wejściowy jest ograniczony do pierwszych 4000 znaków wykonywanej instrukcji.

Ponadto niektóre instrukcje związane z impasem mogą nie być uwzględnione w grafie zakleszczenia. W naszym przykładzie sesja A uruchomiła dwie instrukcje aktualizacji w ramach jednej transakcji. Tylko druga instrukcja aktualizacji, aktualizacja, która spowodowała zakleszczenie, jest uwzględniona w grafie zakleszczenia. Pierwsza instrukcja aktualizacji uruchomiona przez sesję A odegrała rolę w impasie przez zablokowanie sesji B. Bufor wejściowy, query_hashi powiązane informacje dotyczące pierwszej instrukcji uruchamianej przez sesję A nie są uwzględniane w grafie zakleszczenia.

Aby zidentyfikować pełne uruchomienie języka Transact-SQL w transakcji obejmującej wiele instrukcji związanych z zakleszczeniem, należy znaleźć odpowiednie informacje w procedurze składowanej lub kodzie aplikacji, który uruchomił zapytanie, lub uruchomić ślad przy użyciu zdarzeń rozszerzonych w celu przechwycenia pełnych instrukcji uruchamianych przez sesje zaangażowane w zakleszczenie podczas jego wystąpienia. Jeśli instrukcja związana z zakleszczeniem została obcięta i w buforze wejściowym pojawia się tylko częściowa instrukcja Transact-SQL, możesz znaleźć transact-SQL dla instrukcji w magazynie zapytań z planem wykonywania.

Lista zasobów zakleszczenia

Lista zasobów zakleszczenia pokazuje, które zasoby blokady są własnością i czekane przez procesy w impasie.

Zasoby są reprezentowane przez prostokąty w wizualnej reprezentacji zakleszczenia:

Zrzut ekranu przedstawiający wykres zakleszczenia wyświetlany wizualnie w programie SSMS. Prostokąty pokazują zasoby, które są zaangażowane w zakleszczenie.

Uwaga

Można zauważyć, że nazwy baz danych są reprezentowane jako unikatowe grafy zakleszczenia dla baz danych w usłudze Azure SQL Database. Jest physical_database_name to element bazy danych wymieniony w bazach danych sys.databases i sys.dm_user_db_resource_governance dynamicznych widokach zarządzania.

W tym przykładzie zakleszczenia:

  • Ofiara zakleszczenia, którą nazwaliśmy sesją A:

    • Jest właścicielem blokady wyłącznej (X) na kluczu w indeksie PK_Product_ProductID w SalesLT.Product tabeli.
    • Żąda blokady aktualizacji (U) na kluczu w indeksie PK_ProductDescription_ProductDescriptionID w SalesLT.ProductDescription tabeli.
  • Drugi proces, który nazywamy sesją B:

    • Jest właścicielem blokady aktualizacji (U) na kluczu w indeksie PK_ProductDescription_ProductDescriptionID w SalesLT.ProductDescription tabeli.
    • Żąda blokady udostępnionej (S) na kluczu w indeksie PK_ProductDescription_ProductDescriptionID w SalesLT.ProductDescription tabeli.

Te same informacje są widoczne w kodzie XML grafu zakleszczenia w węźle lista zasobów.

Znajdowanie planów wykonywania zapytań w magazynie zapytań

Często warto sprawdzić plany wykonywania zapytań dla instrukcji związanych z zakleszczeniem. Te plany wykonywania można często znaleźć w magazynie zapytań przy użyciu skrótu planu zapytania z widoku XML listy procesów grafu zakleszczenia.

To zapytanie Transact-SQL wyszukuje plany zapytań pasujące do skrótu planu zapytania, który znaleźliśmy na potrzeby naszego przykładowego zakleszczenia. Połączenie do bazy danych użytkownika w usłudze Azure SQL Database, aby uruchomić zapytanie.

DECLARE @query_plan_hash binary(8) = 0x02b0f58d7730f798

SELECT 
    qrsi.end_time as interval_end_time,
    qs.query_id,
    qp.plan_id,
    qt.query_sql_text, 
    TRY_CAST(qp.query_plan as XML) as query_plan,
    qrs.count_executions
FROM sys.query_store_query as qs
JOIN sys.query_store_query_text as qt on qs.query_text_id=qt.query_text_id
JOIN sys.query_store_plan as qp on qs.query_id=qp.query_id
JOIN sys.query_store_runtime_stats qrs on qp.plan_id = qrs.plan_id
JOIN sys.query_store_runtime_stats_interval qrsi on qrs.runtime_stats_interval_id=qrsi.runtime_stats_interval_id
WHERE query_plan_hash =  @query_plan_hash
ORDER BY interval_end_time, query_id;
GO

W zależności od ustawień CLEANUP_POLICY magazynu zapytań lub QUERY_CAPTURE_MODE magazynu zapytań może nie być możliwe uzyskanie planu wykonywania zapytań. W takim przypadku często można uzyskać potrzebne informacje , wyświetlając szacowany plan wykonania zapytania.

Poszukaj wzorców, które zwiększają blokowanie

Podczas badania planów wykonywania zapytań związanych z zakleszczeniami poszukaj wzorców, które mogą przyczynić się do blokowania i zakleszczenia.

  • Skanowanie tabeli lub indeksu. Gdy zapytania modyfikujące dane są uruchamiane w obszarze RCSI, wybór wierszy do aktualizacji odbywa się przy użyciu skanowania blokującego, w którym blokada aktualizacji (U) jest wykonywana w wierszu danych w miarę odczytywania wartości danych. Jeśli wiersz danych nie spełnia kryteriów aktualizacji, blokada aktualizacji zostanie zwolniona, a następny wiersz zostanie zablokowany i zeskanowany.

    Dostrajanie indeksów w celu ułatwienia modyfikacji zapytań dotyczących znajdowania wierszy wydajniej zmniejsza liczbę wystawionych blokad aktualizacji. Zmniejsza to prawdopodobieństwo blokowania i zakleszczenia.

  • Indeksowane widoki odwołujące się do więcej niż jednej tabeli. Podczas modyfikowania tabeli, do której odwołuje się widok indeksowany, aparat bazy danych musi również obsługiwać indeksowany widok. Wymaga to wyjęcie większej liczby blokad i może prowadzić do zwiększenia blokowania i zakleszczenia. Indeksowane widoki mogą również spowodować, że operacje aktualizacji są wykonywane wewnętrznie na poziomie izolacji zatwierdzonej do odczytu.

  • Modyfikacje kolumn, do których odwołuje się ograniczenia klucza obcego. Podczas modyfikowania kolumn w tabeli, do której odwołuje się ograniczenie KLUCZ OBCY, aparat bazy danych musi wyszukać powiązane wiersze w tabeli odwołującej się. Nie można używać wersji wierszy dla tych operacji odczytu. W przypadkach włączenia aktualizacji kaskadowych lub usuwania poziom izolacji może być eskalowany do serializacji przez czas trwania instrukcji w celu ochrony przed wstawkami fantomowymi.

  • Zablokuj wskazówki. Poszukaj wskazówek tabeli, które określają poziomy izolacji wymagające większej liczby blokad. Te wskazówki obejmują HOLDLOCK (co jest równoważne serializacji), SERIALIZABLE, READCOMMITTEDLOCK (co wyłącza RCSI) i REPEATABLEREAD. Ponadto wskazówki, takie jak PAGLOCK, TABLOCK, UPDLOCKi XLOCK mogą zwiększyć ryzyko blokowania i zakleszczenia.

    Jeśli te wskazówki są w miejscu, badania, dlaczego wskazówki zostały wdrożone. Te wskazówki mogą uniemożliwić warunki wyścigu i zapewnić ważność danych. Może być możliwe pozostawienie tych wskazówek i zapobieganie przyszłym zakleszczeniom przy użyciu alternatywnej metody w sekcji Zapobieganie zakleszczaniu w razie potrzeby.

    Uwaga

    Dowiedz się więcej o zachowaniu podczas modyfikowania danych przy użyciu przechowywania wersji wierszy w przewodniku Dotyczącym blokowania transakcji i przechowywania wersji wierszy.

Podczas badania pełnego kodu transakcji w planie wykonywania lub w kodzie zapytania aplikacji poszukaj dodatkowych problematycznych wzorców:

  • Interakcja użytkownika w transakcjach. Interakcja użytkownika wewnątrz jawnej transakcji obejmującej wiele instrukcji znacznie zwiększa czas trwania transakcji. To sprawia, że bardziej prawdopodobne jest, aby te transakcje nakładały się i blokowały i zakleszczenia.

    Podobnie przechowywanie otwartej transakcji i wykonywanie zapytań względem niepowiązanej bazy danych lub systemowej transakcji w połowie transakcji znacznie zwiększa prawdopodobieństwo blokowania i zakleszczenia.

  • Transakcje uzyskiwania dostępu do obiektów w różnych zamówieniach. Zakleszczenia są mniej prawdopodobne, gdy równoczesne transakcje z wieloma instrukcjami są zgodne z tymi samymi wzorcami i dostępem do obiektów w tej samej kolejności.

Zapobieganie zakleszczeniom

Dostępnych jest wiele technik, które uniemożliwiają powtarzanie zakleszczenia, w tym dostrajanie indeksu, wymuszanie planów za pomocą magazynu zapytań i modyfikowanie zapytań Języka Transact-SQL.

  • Przejrzyj indeks klastrowany tabeli. Większość tabel korzysta z indeksów klastrowanych, ale często tabele są implementowane w sposób przypadkowy.

    Jednym ze sposobów sprawdzenia indeksu klastrowanego jest użycie procedury składowanej systemu sp_helpindex . Na przykład możemy wyświetlić podsumowanie indeksów w SalesLT.Product tabeli, wykonując następującą instrukcję:

    exec sp_helpindex 'SalesLT.Product';
    GO
    

    Przejrzyj kolumnę index_description. Tabela może zawierać tylko jeden indeks klastrowany. Jeśli dla tabeli zaimplementowano indeks klastrowany, index_description będzie zawierać słowo "clustered".

    Jeśli nie ma indeksu klastrowanego, tabela jest stertą. W takim przypadku sprawdź, czy tabela została celowo utworzona jako sterta w celu rozwiązania określonego problemu z wydajnością. Rozważ zaimplementowanie indeksu klastrowanego na podstawie wytycznych dotyczących projektowania indeksu klastrowanego.

    W niektórych przypadkach tworzenie lub dostrajanie indeksu klastrowanego może zmniejszyć lub wyeliminować blokowanie zakleszczeń. W innych przypadkach może być konieczne zastosowanie dodatkowej techniki, takiej jak inne na tej liście.

  • Utwórz lub zmodyfikuj indeksy nieklastrowane. Dostrajanie indeksów nieklastrowanych może pomóc w wyszukiwaniu danych w celu szybszego aktualizowania zapytań modyfikacji, co zmniejsza liczbę wymaganych blokad aktualizacji.

    W naszym przykładowym zakleszczeniu plan wykonywania zapytania znaleziony w magazynie zapytań zawiera skanowanie indeksu klastrowanego względem indeksu PK_Product_ProductID . Wykres zakleszczenia wskazuje, że współużytkowany (S) oczekiwanie na ten indeks jest składnikiem zakleszczenia.

    Zrzut ekranu przedstawiający plan wykonywania zapytania. Skanowanie indeksu klastrowanego jest wykonywane względem indeksu PK_Product_ProductID w tabeli Product.

    To skanowanie indeksu jest wykonywane, ponieważ nasze zapytanie aktualizacji musi zmodyfikować indeksowany widok o nazwie vProductAndDescription. Jak wspomniano w sekcji Wyszukiwanie wzorców, które zwiększają blokowanie w tym artykule, indeksowane widoki odwołujące się do wielu tabel mogą zwiększyć blokowanie i prawdopodobieństwo zakleszczenia.

    Jeśli utworzymy następujący indeks nieklastrowany w AdventureWorksLT bazie danych, który "obejmuje" kolumny z SalesLT.Product przywoływanego przez indeksowany widok, pomoże to zapytaniu znaleźć wiersze znacznie wydajniej:

    CREATE INDEX ix_Product_ProductID_Name_ProductModelID on SalesLT.Product (ProductID, Name, ProductModelID);
    GO
    

    Po utworzeniu tego indeksu zakleszczenie nie będzie już powtarzane.

    Gdy zakleszczenia obejmują modyfikacje kolumn przywoływanych w ograniczeniach klucza obcego, upewnij się, że indeksy w tabeli odwołującej się klucza obcego obsługują efektywne znajdowanie powiązanych wierszy.

    Chociaż indeksy mogą znacznie poprawić wydajność zapytań w niektórych przypadkach, indeksy również mają koszty związane z obciążeniem i zarządzaniem. Zapoznaj się z ogólnymi wytycznymi dotyczącymi projektowania indeksów, aby ułatwić ocenę korzyści z indeksów przed utworzeniem indeksów, szczególnie szerokich indeksów i indeksów w dużych tabelach.

  • Oceń wartość indeksowanych widoków. Inną opcją zapobiegania ponownemu zakleszczaniu naszego przykładowego SalesLT.vProductAndDescription zakleszczenia jest usunięcie widoku indeksowanego. Jeśli ten indeksowany widok nie jest używany, zmniejszy to obciążenie związane z konserwowanie widoku indeksowanego w czasie.

  • Użyj izolacji migawki. W niektórych przypadkach ustawienie poziomu izolacji transakcji na migawkę dla co najmniej jednej transakcji biorącej udział w impasie może uniemożliwić blokowanie i zakleszczenia.

    Ta technika najprawdopodobniej powiedzie się w przypadku użycia instrukcji SELECT, gdy migawka zatwierdzona do odczytu jest wyłączona w bazie danych. Po wyłączeniu migawki zatwierdzonej do odczytu zapytania SELECT przy użyciu poziomu izolacji zatwierdzonej do odczytu wymagają blokad udostępnionych (S). Użycie izolacji migawki w tych transakcjach eliminuje konieczność blokowania udostępnionych blokad, co może uniemożliwić blokowanie i zakleszczenia.

    W bazach danych, w których włączono izolację zatwierdzonych migawek odczytu, zapytania SELECT nie wymagają udostępnionych blokad (S), więc zakleszczenia są bardziej narażone na występowanie transakcji modyfikujących dane. W przypadkach, gdy zakleszczenia występują między wieloma transakcjami modyfikującymi dane, izolacja migawki może spowodować konflikt aktualizacji zamiast zakleszczenia. Podobnie wymaga to wykonania jednej z transakcji, aby ponowić próbę wykonania operacji.

  • Wymuś plan z magazynem zapytań. Może się okazać, że jedno z zapytań w impasie zawiera wiele planów wykonywania, a zakleszczenie występuje tylko wtedy, gdy jest używany określony plan. Możesz zapobiec ponownemu zakleszczaniu, wymuszając plan w magazynie zapytań.

  • Zmodyfikuj język Transact-SQL. Może być konieczne zmodyfikowanie języka Transact-SQL, aby zapobiec ponownemu zakleszczaniu. Należy starannie zmodyfikować język Transact-SQL, a zmiany powinny być rygorystycznie testowane, aby upewnić się, że dane są poprawne podczas równoczesnego uruchamiania modyfikacji. Podczas ponownego pisania języka Transact-SQL należy wziąć pod uwagę następujące kwestie:

    • Porządkowanie instrukcji w transakcjach w taki sposób, aby uzyskiwały dostęp do obiektów w tej samej kolejności.
    • Podział transakcji na mniejsze transakcje, gdy jest to możliwe.
    • W razie potrzeby użyj wskazówek dotyczących zapytań, aby zoptymalizować wydajność. Wskazówki można stosować bez zmieniania kodu aplikacji przy użyciu magazynu zapytań.

Znajdź więcej sposobów zminimalizowania zakleszczeń w przewodniku Zakleszczenia.

Uwaga

W niektórych przypadkach możesz dostosować priorytet zakleszczenia co najmniej jednej sesji biorącej udział w impasie, jeśli ważne jest, aby jedna z sesji zakończyła się pomyślnie bez ponawiania próby lub gdy jeden z zapytań zaangażowanych w impas nie jest krytyczny i powinien być zawsze wybierany jako ofiara. Chociaż nie zapobiega to reoccurringowi zakleszczenia, może to zmniejszyć wpływ przyszłych zakleszczeń.

Usuwanie sesji XEvents

Możesz pozostawić sesję XEvents zbierając informacje o impasie działające w krytycznych bazach danych przez długi czas. Należy pamiętać, że jeśli używasz obiektu docelowego pliku zdarzeń, może to spowodować powstanie dużych plików, jeśli wystąpi wiele zakleszczeń. Możesz usunąć pliki obiektów blob z usługi Azure Storage dla aktywnego śledzenia, z wyjątkiem pliku, do którego jest obecnie zapisywany.

Jeśli chcesz usunąć sesję XEvents, sesja transact-SQL jest taka sama, niezależnie od wybranego typu docelowego.

Aby usunąć sesję XEvents, uruchom następujące polecenie Języka Transact-SQL. Przed uruchomieniem kodu zastąp nazwę sesji odpowiednią wartością.

ALTER EVENT SESSION [deadlocks] ON DATABASE
    STATE = STOP;
GO

DROP EVENT SESSION [deadlocks] ON DATABASE;
GO

Korzystanie z Eksploratora usługi Azure Storage

Eksplorator usługi Azure Storage to autonomiczna aplikacja, która upraszcza pracę z obiektami docelowymi plików zdarzeń przechowywanymi w obiektach blob w usłudze Azure Storage. Za pomocą Eksplorator usługi Storage można wykonywać następujące czynności:

Pobierz Eksplorator usługi Azure Storage..

Następne kroki

Dowiedz się więcej o wydajności w usłudze Azure SQL Database: