Udostępnij za pomocą


Zoptymalizowane blokowanie

Dotyczy: SQL Server 2025 (17.x) Azure SQL DatabaseAzure SQL Managed InstanceSQL database w Microsoft Fabric

Zoptymalizowane blokowanie oferuje ulepszony mechanizm blokowania transakcji w celu zmniejszenia blokowania oraz zużycia pamięci blokady w przypadku transakcji współbieżnych.

Co to jest zoptymalizowane blokowanie?

Zoptymalizowane blokowanie pomaga zmniejszyć ilość pamięci blokady, ponieważ bardzo mało blokad jest przechowywanych nawet w przypadku dużych transakcji. Ponadto zoptymalizowane blokowanie pozwala uniknąć eskalacji blokady i uniknąć niektórych typów zakleszczeń. Umożliwia to bardziej współbieżny dostęp do tabeli.

Zoptymalizowane blokowanie składa się z dwóch podstawowych składników: blokady identyfikatora transakcji (TID) i blokowania po kwalifikacji (LAQ).

  • Identyfikator transakcji (TID) jest unikatowym identyfikatorem transakcji. Każdy wiersz ma oznaczenie z ostatnim TID, który go zmodyfikował. Zamiast potencjalnie wielu blokad klucza lub identyfikatora wiersza, do ochrony wszystkich zmodyfikowanych wierszy używana jest pojedyncza blokada TID. Aby uzyskać więcej informacji, zobacz Transaction ID (TID) locking.
  • Blokada po kwalifikacjach (LAQ) to optymalizacja, która ocenia predykaty zapytań przy użyciu najnowszej zatwierdzonej wersji wiersza bez uzyskiwania blokady, co poprawia współbieżność. Usługa LAQ wymaga izolacji migawek zatwierdzonych do odczytu (RCSI). Aby uzyskać więcej informacji, zobacz Lock after qualification (LAQ).

Przykład:

  • Bez zoptymalizowanego blokowania aktualizowanie 1000 wierszy w tabeli może wymagać 1000 wyłącznych (X) blokad wierszy przechowywanych do końca transakcji.
  • W przypadku zoptymalizowanego blokowania aktualizowanie 1000 wierszy w tabeli może wymagać 1000 X blokad wierszy, ale każda blokada jest zwalniana natychmiast po zaktualizowaniu każdego wiersza, a tylko jedna X blokada TID jest przechowywana do końca transakcji. Ponieważ blokady są szybko zwalniane, użycie pamięci blokady jest zmniejszane, a eskalacji blokady jest znacznie mniej prawdopodobne, co zwiększa współbieżność obciążenia.

Note

Włączenie zoptymalizowanego blokowania zmniejsza lub eliminuje blokady wierszy i stron uzyskanych przez instrukcje języka DML (Data Modification Language), takie jak INSERT, UPDATE, DELETE, MERGE. Nie ma wpływu na inne rodzaje blokad bazy danych i obiektów, takie jak blokady schematu.

Availability

Poniższa tabela zawiera podsumowanie dostępności i stanu włączonego zoptymalizowanego blokowania na różnych platformach SQL.

Platform Available Domyślnie włączone
Azure SQL Database Yes Tak (zawsze włączone)
Baza danych SQL w usłudze Microsoft Fabric Yes Tak (zawsze włączone)
Azure SQL Managed Instance AUTD Yes Tak (zawsze włączone)
Azure SQL Managed Instance2025 Yes Tak (zawsze włączone)
Azure SQL Managed Instance2022 No N/A
SQL Server 2025 (17.x) Yes Nie (można włączyć dla każdej bazy danych)
SQL Server 2022 (16.x) i starsze wersje No N/A

Włączanie i wyłączanie

Aby włączyć lub wyłączyć zoptymalizowane blokowanie bazy danych programu SQL Server, użyj ALTER DATABASE ... SET OPTIMIZED_LOCKING = ON | OFF polecenia . Aby uzyskać więcej informacji, zobacz opcje ALTER DATABASE SET.

Zoptymalizowane blokowanie opiera się na innych funkcjach bazy danych:

  • Przed włączeniem zoptymalizowanego blokowania należy włączyć przyspieszone odzyskiwanie bazy danych (ADR ). Z drugiej strony, aby wyłączyć regułę ADR, należy najpierw wyłączyć zoptymalizowane blokowanie, jeśli jest włączone.
  • Aby uzyskać największą korzyść z zoptymalizowanego blokowania, należy włączyć izolację migawkową z zatwierdzaniem do odczytu (RCSI) dla bazy danych. Składnik LAQ zoptymalizowanego blokowania jest skuteczny tylko wtedy, gdy funkcja RCSI jest włączona.

ADR jest zawsze włączone w Azure SQL Database, Azure SQL Managed Instance i SQL Database w Microsoft Fabric. RCSI jest domyślnie włączone w Azure SQL Database i SQL Database w Microsoft Fabric.

Aby sprawdzić, czy te opcje są włączone dla bieżącej bazy danych, połącz się z bazą danych i uruchom następujące zapytanie T-SQL:

SELECT database_id,
       name,
       is_accelerated_database_recovery_on,
       is_read_committed_snapshot_on,
       is_optimized_locking_on
FROM sys.databases
WHERE name = DB_NAME();

Czy jest włączone zoptymalizowane blokowanie?

Zoptymalizowane blokowanie jest włączone dla każdej bazy danych. Połącz się z bazą danych, a następnie użyj następującego zapytania, aby sprawdzić, czy jest włączona zoptymalizowana blokada:

SELECT DATABASEPROPERTYEX(DB_NAME(), 'IsOptimizedLockingOn') AS is_optimized_locking_enabled;
Result Description
0 Zoptymalizowane blokowanie jest wyłączone.
1 Zoptymalizowane blokowanie jest włączone.
NULL Zoptymalizowane blokowanie nie jest dostępne.

Możesz również użyć widoku katalogu sys.databases . Aby na przykład sprawdzić, czy zoptymalizowane blokowanie jest włączone dla wszystkich baz danych, wykonaj następujące zapytanie:

SELECT database_id,
       name,
       is_optimized_locking_on
FROM sys.databases;

Omówienie blokowania

Jest to krótkie podsumowanie zachowania, gdy zoptymalizowane blokowanie nie jest włączone. Aby uzyskać więcej informacji, zapoznaj się z przewodnikiem Transaction locking and row versioning (Blokowanie transakcji i przechowywanie wersji wierszy).

W aparacie bazy danych blokowanie jest mechanizmem uniemożliwiającym jednoczesne aktualizowanie tych samych danych przez wiele transakcji w celu zagwarantowania ACID właściwości transakcji.

Gdy transakcja musi zmodyfikować dane, żąda blokady danych. Blokada jest przyznawana, jeśli na danych nie są utrzymywane żadne inne blokady powodujące konflikt, a transakcja może przystąpić do modyfikacji. Jeśli na danych jest przechowywana inna blokada powodująca konflikt, transakcja musi poczekać na zwolnienie blokady, zanim będzie mogła kontynuować.

Gdy wiele transakcji próbuje uzyskać dostęp do tych samych danych jednocześnie, aparat bazy danych musi rozwiązać potencjalnie złożone konflikty z równoczesnymi operacjami odczytu i zapisu. Blokowanie jest jednym z mechanizmów, za pomocą których silnik może zapewnić semantykę transakcji ANSI SQL poziomów izolacji. Chociaż blokowanie w bazach danych jest niezbędne, to zmniejszona współbieżność, zakleszczenia, złożoność i narzut związany z blokadami mogą wpływać na wydajność i skalowalność.

Blokowanie identyfikatora transakcji (TID)

Kiedy używane są poziomy izolacji oparte na wersjonowaniu wierszy lub gdy ADR jest włączone, każdy wiersz w bazie danych wewnętrznie zawiera identyfikator transakcji (TID). Identyfikator TID jest utrwalany razem z wierszem. Każda transakcja, która modyfikuje wiersz, oznacza go swoim identyfikatorem TID.

W przypadku blokowania TID, zamiast zakładania blokady na kluczu wiersza, blokada jest zakładana na TID wiersza. Transakcja modyfikująca przechowuje blokadę X na TID. Inne transakcje uzyskują blokadę S na TID, aby poczekać na ukończenie pierwszej transakcji. Dzięki blokadzie TID, blokady stron i wierszy są nadal stosowane podczas modyfikacji, ale każda z tych blokad jest zwalniana natychmiast po dokonaniu modyfikacji wiersza. Jedyną blokadą przechowywaną do końca transakcji jest blokada X zasobu TID, która zastępuje wiele blokad strony i wiersza (klucza).

Rozważmy następujący przykład pokazujący blokady dla bieżącej sesji, gdy transakcja zapisu jest aktywna:

/* Is optimized locking is enabled? */
SELECT DATABASEPROPERTYEX(DB_NAME(), 'IsOptimizedLockingOn') AS is_optimized_locking_enabled;

CREATE TABLE t0
(
a int PRIMARY KEY,
b int NULL
);

INSERT INTO t0 VALUES (1,10),(2,20),(3,30);
GO

BEGIN TRANSACTION;

UPDATE t0
SET b = b + 10;

SELECT *
FROM sys.dm_tran_locks
WHERE request_session_id = @@SPID
      AND
      resource_type IN ('PAGE','RID','KEY','XACT');

COMMIT TRANSACTION;
GO

DROP TABLE IF EXISTS t0;

Jeśli włączono zoptymalizowane blokowanie, żądanie przechowuje tylko jedną blokadę X w zasobie XACT (transakcja).

Zrzut ekranu przedstawiający zestaw wyników zapytania dla sys.dm_tran_locks dla jednej sesji pokazuje tylko jedną blokadę po włączeniu zoptymalizowanego blokowania.

Jeśli zoptymalizowane blokowanie nie jest włączone, to samo żądanie zawiera cztery blokady — jedną blokadę IX (wyłączność intencji) na stronie zawierającej wiersze, a trzy X blokady kluczy w każdym wierszu:

Zrzut ekranu przedstawiający zestaw wyników zapytania dla sys.dm_tran_locks dla jednej sesji pokazuje trzy blokady, gdy zoptymalizowane blokowanie nie jest włączone.

Dynamiczny widok zarządzania (DMV) sys.dm_tran_locks jest przydatny podczas badania lub rozwiązywania problemów z blokowaniem. Tutaj stosuje się to do obserwowania zoptymalizowanego blokowania w praktyce.

Blokada po kwalifikacjach (LAQ)

Opierając się na infrastrukturze TID, składnik LAQ zoptymalizowanego blokowania zmienia sposób, w jaki instrukcje DML, takie jak INSERT, UPDATEi DELETE uzyskują blokady.

Bez zoptymalizowanego blokowania, predykaty zapytań są sprawdzane wiersz po wierszu podczas skanowania, najpierw aktualizując blokadę wiersza (U). Jeśli predykat jest spełniony, zostanie założona blokada wiersza na wyłączność (X) przed zaktualizowaniem wiersza i utrzymywana do końca transakcji.

W przypadku zoptymalizowanego blokowania i READ COMMITTED włączenia poziomu izolacji migawki (RCSI) predykaty mogą być optymistycznie sprawdzane w najnowszej zatwierdzonej wersji wiersza bez wprowadzania żadnych blokad. Jeśli predykat nie spełnia wymagań, zapytanie zostanie przeniesione do następnego wiersza w skanowaniu. Jeśli predykat jest spełniony, zostanie podjęta blokada wiersza X celem zaktualizowania wiersza.

Innymi słowy, blokada jest wykonywana po kwalifikacji wiersza na do modyfikacji. Blokada wiersza X jest zwalniana natychmiast po zakończeniu aktualizacji wiersza, zanim transakcja zostanie zakończona.

Ponieważ ocena predykatu jest wykonywana bez uzyskiwania żadnych blokad, współbieżne zapytania modyfikujące różne wiersze nie blokują się nawzajem.

Przykład:

/* Confirm that optimized locking and read committed snapshot isolation (RCSI) are both enabled on this database. */
SELECT database_id,
       name,
       is_accelerated_database_recovery_on,
       is_optimized_locking_on,
       is_read_committed_snapshot_on
FROM sys.databases
WHERE name = DB_NAME();

CREATE TABLE t1
(
a int NOT NULL,
b int NULL
);

INSERT INTO t1
VALUES (1,10),(2,20),(3,30);
GO
Sesja 1 Sesja 2
BEGIN TRANSACTION;
UPDATE t1
SET b = b + 10
WHERE a = 1;
BEGIN TRANSACTION;
UPDATE t1
SET b = b + 10
WHERE a = 2;
COMMIT TRANSACTION;
COMMIT TRANSACTION;

Bez zoptymalizowanego blokowania sesja 2 jest blokowana, ponieważ sesja 1 trzyma blokadę U na wierszu, który sesja 2 musi zaktualizować. Jednak w przypadku zoptymalizowanego blokowania sesja 2 nie jest blokowana, ponieważ blokady U nie są wykonywane, a ponieważ w najnowszej zatwierdzonej wersji wiersza 1 kolumna a równa się 1, co nie spełnia predykatu sesji 2.

LAQ jest wykonywane optymistycznie na założeniu, że wiersz nie jest modyfikowany po sprawdzeniu predykatu. Jeśli warunek jest spełniony, a wiersz nie został zmodyfikowany po sprawdzeniu warunku, jest modyfikowany przez bieżącą transakcję.

U Ponieważ blokady nie są wykonywane, współbieżna transakcja może zmodyfikować wiersz po ocenie predykatu. Jeśli w wierszu znajduje się aktywna transakcja zawierająca blokadę X TID, aparat bazy danych czeka na jej zakończenie. Jeśli wiersz uległ zmianie po wcześniejszym obliczeniu predykatu, aparat bazy danych ponownie ocenia (rewalifikuje) predykat ponownie przed zmodyfikowaniem wiersza. Jeśli predykat jest nadal spełniony, wiersz zostanie zmodyfikowany.

Klasyfikacja predykatu jest obsługiwana przez podzestaw operatorów silnika zapytań. Jeśli wymagana jest ponowna ocena predykatu, ale plan zapytania używa operatora, który nie obsługuje ponownej kwalifikacji predykatu, silnik bazy danych wewnętrznie przerywa przetwarzanie instrukcji i uruchamia bez LAQ. Gdy wystąpi takie anulowanie, zdarzenie rozszerzone lock_after_qual_stmt_abort zostanie wyzwolone.

Niektóre instrukcje, na przykład UPDATE instrukcje z przypisaniem zmiennej i instrukcjami z klauzulą OUTPUT , nie można przerwać i ponownie uruchomić bez zmiany ich semantyki. W przypadku takiej instrukcji LAQ nie jest używany.

W poniższym przykładzie predykat jest ponownie oceniany, ponieważ kolejna transakcja zmieniła wiersz:

CREATE TABLE t3
(
a int NOT NULL,
b int NULL
);

INSERT INTO t3 VALUES (1,10),(2,20),(3,30);
GO
Sesja 1 Sesja 2
BEGIN TRANSACTION;
UPDATE t3
SET b = b + 10
WHERE a = 1;
BEGIN TRANSACTION;
UPDATE t3
SET b = b + 10
WHERE a = 1;
COMMIT TRANSACTION;
COMMIT TRANSACTION;

Pomijanie blokad indeksu (SIL)

Blokady TID umożliwiają modyfikowanie wierszy przy użyciu blokad wierszy na wyłączność o krótkim czasie trwania (X) i blokad stron z zamierzoną wyłącznością (IX). Gdy są używane wersje RCSI i LAQ, te blokady są niezbędne tylko wtedy, gdy mogą istnieć inne zapytania, które uzyskują dostęp do wiersza i oczekują, że będzie stabilna. Przykładami takich zapytań są te, które działają pod REPEATABLE READ lub SERIALIZABLE poziomami izolacji, albo używają odpowiadających im wskazówek dotyczących blokowania. Takie zapytania są nazywane zapytaniami blokowania wierszy (RLQ).

Kiedy nie ma żadnych zapytań RLQ uzyskujących dostęp do wiersza, aparat bazy danych może pominąć wykonywanie blokad wierszy i stron przy modyfikacji wiersza oraz używać jedynie na wyłączność zatrzasku strony . Ta optymalizacja zmniejsza obciążenie związane z blokowaniem przy jednoczesnym zachowaniu semantyki transakcji ACID. Pomijanie blokad wierszy i stron szczególnie korzystnie wpływa na transakcje modyfikujące dużą liczbę wierszy.

Obecnie optymalizacja SIL jest używana tylko w następujących przypadkach:

  • INSERT oświadczenia na stercie.
    • IX blokady stron są pomijane.
  • UPDATE oświadczenia dotyczące indeksów klastrowanych, indeksów nieklastrowanych i stert.
    • IX blokady stron i X blokady wierszy są pomijane.

Optymalizacja SIL nie jest obecnie używana w następujących przypadkach:

  • DELETE Oświadczenia.
  • UPDATE deklaracje dotyczące stert, jeśli wiersz zawiera istniejące wskaźniki przekierowania lub jeśli aktualizacja dodaje nowe wskaźniki przekierowania.
  • Jeśli zmodyfikowany wiersz zawiera kolumny używające typów danych LOB, takich jak varchar(max), nvarchar(max), varbinary(max) i json.
  • W przypadku wierszy na stronach podzielonych w tej samej transakcji.

Heurystyka LAQ

Jak opisano w Lock after qualification (LAQ), gdy jest używany LAQ, instrukcje używające operatorów zapytań, które nie obsługują ponownej kwalifikacji predykatu, mogą zostać wewnętrznie zrestartowane i przetworzone bez LAQ. Jeśli dzieje się to często, obciążenie związane z ponownym przetwarzaniem może stać się znaczące. Aby zminimalizować obciążenie, zoptymalizowane blokowanie korzysta z mechanizmu przesyłania opinii opartego na heurystyce, który wyłącza funkcję LAQ, jeśli obciążenie przekracza progi.

Na potrzeby mechanizmu przesyłania opinii praca wykonywana przez instrukcję jest mierzona w liczbie odczytów logicznych. Jeśli aparat bazy danych modyfikuje wiersz, który został zmodyfikowany przez inną transakcję po rozpoczęciu przetwarzania instrukcji, praca wykonywana przez instrukcję jest traktowana jako potencjalnie zmarnowana, ponieważ może być konieczne ponowne przetworzenie instrukcji.

Podczas wykonywania instrukcji, silnik bazy danych przechowuje dane zwrotne LAQ, które śledzą potencjalnie zmarnowaną pracę, wystąpienia ponownego przetwarzania instrukcji oraz łączną pracę wykonaną przez instrukcje, które mogą być ponownie przetwarzane.

LaQ jest wyłączony, jeśli stosunek potencjalnie zmarnowanej pracy do całkowitej pracy lub stosunek liczby przetworzonych instrukcji do całkowitej liczby instrukcji przekracza ich progi. Jeśli oba te współczynniki spadną poniżej progów, funkcja LAQ zostanie ponownie włączona.

Dane opinii laQ są śledzone na dwóch poziomach:

  • W przypadku planu zapytania.

    • Aparat bazy danych rozpoczyna śledzenie informacji zwrotnej LAQ dla planu przy pierwszym wystąpieniu ponownego przetwarzania instrukcji.
    • Jeśli zapytanie jest przechwytywane w Magazynie Zapytaniowym, informacja zwrotna LAQ jest również przechwytywana w Magazynie Zapytaniowym. Silnik bazy danych korzysta z tej opinii, aby utrzymać włączenie lub wyłączenie LAQ dla planu, jeśli baza danych zostanie uruchomiona ponownie.
    • Plany zapytań z przechwyconymi informacjami zwrotnymi LAQ mają wiersz z pasującą wartością plan_id w widoku katalogu sys.query_store_plan_feedback. Kolumny feature_id i feature_desc są ustawione odpowiednio na 4 i LAQ Feedback .
  • W przypadku bazy danych.

    • Informacje zwrotne są agregowane dla wszystkich instrukcji, które nie mają informacji zwrotnych na poziomie planu zapytań, na przykład w przypadku gdy zapytanie nie jest przechwytywane w Query Store.
    • Informacja zwrotna jest śledzona od momentu uruchomienia bazy danych i jest odtwarzana po każdym uruchomieniu.

Podczas podejmowania decyzji, czy używać LAQ do zapytania, system używa informacji zwrotnej z planu zapytania, jeśli jest dostępna. W przeciwnym razie używa opinii na poziomie bazy danych. Oznacza to, że niektóre instrukcje mogą być wykonywane za pomocą metody LAQ, a niektóre mogą być wykonywane bez LAQ. Na przykład usługa LAQ może być wyłączona dla planu zapytania, ale włączona dla bazy danych i na odwrót.

Ograniczenia usługi LAQ

Zablokowanie po kwalifikacjach nie jest używane w następujących scenariuszach:

  • W przypadku wyłączenia przez heurystyka LAQ.
  • Gdy konfliktujące wskazówki dotyczące blokowania, takie jak UPDLOCK, READCOMMITTEDLOCK, XLOCK, lub HOLDLOCK są używane.
  • Gdy poziom izolacji transakcji jest inny niż READ COMMITTED, lub gdy opcja bazy danych jest wyłączona READ_COMMITTED_SNAPSHOT .
  • Gdy modyfikowana tabela ma indeks columnstore.
  • Gdy instrukcja DML zawiera przypisanie zmiennej.
  • Gdy instrukcja DML ma klauzulę OUTPUT .
  • Gdy instrukcja DML używa więcej niż jednego operatora wyszukiwania indeksu lub skanowania do odczytywania modyfikowanych wierszy.
  • W MERGE wyrażeniach.

Zmiany zachowania zapytań przy użyciu zoptymalizowanego blokowania i RCSI

Współbieżne obciążenia w ramach izolacji migawek zatwierdzonych do odczytu (RCSI), które opierają się na ścisłej kolejności wykonywania transakcji, mogą doświadczać różnic w zachowaniu zapytań, gdy włączone jest zoptymalizowane blokowanie.

Rozważmy następujący przykład, w którym transakcja T2 aktualizuje tabelę t4 na podstawie kolumny b, która została zaktualizowana podczas transakcji T1.

CREATE TABLE t4
(
a int NOT NULL,
b int NULL
);

INSERT INTO t4
VALUES (1,1);
GO
Sesja 1 Sesja 2
BEGIN TRANSACTION T1;
UPDATE t4
SET b = 2
WHERE a = 1;
BEGIN TRANSACTION T2;
UPDATE t4
SET b = 3
WHERE b = 2;
COMMIT TRANSACTION;
COMMIT TRANSACTION;

Oceńmy wynik poprzedniego scenariusza z blokadą i bez blokady po kwalifikacjach (LAQ).

Bez LAQ

Bez LAQ polecenie UPDATE w transakcji T2 jest zablokowane, czekając na zakończenie transakcji T1. Po zakończeniu T1, T2 aktualizuje kolumnę w wierszu b na 3, ponieważ jego warunek został spełniony.

Po zatwierdzeniu obu transakcji tabela t4 zawiera następujące wiersze:

 a | b
 1 | 3

z LAQ

W przypadku LAQ transakcja T2 używa najnowszej zatwierdzonej wersji wiersza, w której kolumna b równa się 1, w celu oceny jego predykatu (b = 2). Wiersz nie kwalifikuje się; w związku z tym jest pomijany, a instrukcja kończy się, nie będąc zablokowaną przez transakcję T1. W tym przykładzie LAQ usuwa blokowanie, ale prowadzi do różnych wyników.

Po zatwierdzeniu obu transakcji tabela t4 zawiera następujące wiersze:

 a | b
 1 | 2

Important

Nawet bez LAQ, aplikacje nie powinny zakładać, że silnik bazy danych gwarantuje ścisłe porządkowanie bez użycia podpowiedzi blokowania, gdy używane są poziomy izolacji oparte na wersjonowaniu wierszy. Naszym ogólnym zaleceniem dla klientów korzystających z współbieżnych obciążeń w wersji RCSI, które opierają się na ścisłej kolejności wykonywania transakcji (jak pokazano w poprzednim przykładzie), jest użycie bardziej rygorystycznych poziomów izolacji, takich jak REPEATABLE READ i SERIALIZABLE.

Dodatki diagnostyczne do zoptymalizowanego blokowania

Poniższe ulepszenia ułatwiają monitorowanie i rozwiązywanie problemów z blokowaniem i zakleszczaniem po włączeniu zoptymalizowanego blokowania:

  • Typy oczekiwania na zoptymalizowane blokowanie
    • XACT typy oczekiwania na S blokadę TID i opisy zasobów w sys.dm_os_wait_stats:
      • LCK_M_S_XACT_READ — występuje, gdy zadanie oczekuje na blokadę współdzieloną typu XACTwait_resource z zamiarem odczytu.
      • LCK_M_S_XACT_MODIFY — występuje, gdy zadanie oczekuje na wspólną blokadę typu XACTwait_resource z zamiarem modyfikacji.
      • LCK_M_S_XACT — występuje, gdy zadanie oczekuje na udostępnioną blokadę na typie XACTwait_resource, gdzie intencja nie może zostać wywnioskowana. Ten scenariusz nie jest typowy.
  • Blokowanie widoczności zasobów
    • XACT blokowanie zasobów. Aby uzyskać więcej informacji, zobacz resource_description w sys.dm_tran_locks.
  • Oczekiwanie na widoczność zasobu
    • XACT oczekuje zasobów. Aby uzyskać więcej informacji, zobacz wait_resource w sys.dm_exec_requests.
  • Wykres zakleszczenia
    • W ramach każdego zasobu w raporcie zakleszczenia <resource-list>, każdy element <xactlock> raportuje podstawowe zasoby i określone informacje dotyczące blokad każdego członka zakleszczenia. Aby uzyskać więcej informacji oraz przykład, zobacz Zoptymalizowane blokowanie i zakleszczenia.
  • Zdarzenia rozszerzone
    • Zdarzenie lock_after_qual_stmt_abort jest uruchamiane, gdy instrukcja jest ponownie przetwarzana wewnętrznie z powodu konfliktu z inną transakcją. Aby uzyskać więcej informacji, zobacz Lock after qualification (LAQ).
    • Zdarzenie locking_stats jest wyzwalane dla każdej bazy danych co kilka minut i dostarcza zagregowane statystyki blokowania dla przedziału czasu, takie jak liczba eskalacji blokady, czy blokowanie TID i składniki LAQ zoptymalizowanego blokowania są aktywne, oraz liczba zapytań, w których LAQ nie było używane z różnych powodów. To zdarzenie jest uruchamiane nawet wtedy, gdy zoptymalizowane blokowanie jest wyłączone.
    • W programie SQL Server i usłudze Azure SQL Managed Instance locking_stats2 zdarzenie jest uruchamiane co kilka minut dla każdej bazy danych i udostępnia statystyki dotyczące blokad indeksów typu skip oraz heurystyk LAQ dla tego przedziału czasu.

Najlepsze rozwiązania dotyczące zoptymalizowanego blokowania

Włączanie izolacji migawek zatwierdzonych do odczytu (RCSI)

Aby zmaksymalizować zalety zoptymalizowanego blokowania, zaleca się włączenie izolacji migawek zatwierdzonych do odczytu (RCSI) w bazie danych i używanie READ COMMITTED izolacji jako domyślnego poziomu izolacji.

W usługach Azure SQL Database i SQL Database w usłudze Microsoft Fabric usługa RCSI jest domyślnie włączona i READ COMMITTED jest domyślnym poziomem izolacji. Po włączeniu wersji RCSI i w przypadku używania READ COMMITTED poziomu izolacji czytelnicy odczytują wersję wiersza z migawki wykonanej na początku instrukcji. W przypadku LAQ pisarze kwalifikują wiersze zgodnie z predykatem na podstawie najnowszej zatwierdzonej wersji wiersza i bez uzyskiwania blokad U. W przypadku LAQ zapytanie czeka tylko wtedy, gdy wiersz spełnia kryteria i istnieje aktywna transakcja zapisu na tym wierszu. Kwalifikowanie na podstawie najnowszej zatwierdzonej wersji i blokowanie tylko kwalifikowanych wierszy zmniejsza blokowanie i zwiększa współbieżność.

Unikaj wskazówek dotyczących blokady

Podczas gdy wskazówki dotyczące tabel i zapytań, takie jak UPDLOCK, READCOMMITTEDLOCK, XLOCK, HOLDLOCKitp., są respektowane po włączeniu zoptymalizowanego blokowania, zmniejszają one korzyści płynące ze zoptymalizowanego blokowania. Wskazówki dotyczące blokady wymuszają na aparacie bazy danych tworzenie blokad wierszy lub stron i ich utrzymanie do końca transakcji, aby respektować intencje tych wskazówek. Niektóre aplikacje mają logikę, w której są potrzebne wskazówki dotyczące blokady, na przykład podczas odczytywania wiersza za pomocą wskazówki UPDLOCK, a następnie aktualizowania go później. Zalecamy używanie wskazówek dotyczących blokady tylko w razie potrzeby.

W przypadku zoptymalizowanego blokowania nie ma żadnych ograniczeń dotyczących istniejących zapytań i nie trzeba ponownie pisać zapytań. Zapytania, które nie korzystają ze wskazówek, korzystają najwięcej z zoptymalizowanego blokowania.

Wskazówka tabeli dla jednej tabeli w zapytaniu nie wyłącza zoptymalizowanego blokowania dla innych tabel w tym samym zapytaniu. Ponadto zoptymalizowane blokowanie wpływa tylko na zachowanie blokady tabel aktualizowanych przez instrukcję DML, taką jak INSERT, UPDATE, DELETElub MERGE. Przykład:

CREATE TABLE t5
(
a int NOT NULL,
b int NOT NULL
);

CREATE TABLE t6
(
a int NOT NULL,
b int NOT NULL
);
GO

INSERT INTO t5 VALUES (1,10),(2,20),(3,30);
INSERT INTO t6 VALUES (1,10),(2,20),(3,30);
GO

UPDATE t5 SET t5.b = t6.b
FROM t5
INNER JOIN t6 WITH (UPDLOCK)
ON t5.a = t6.a;

W poprzednim przykładzie zapytania tylko tabela t6 jest objęta wskazówką blokującą, podczas gdy t5 nadal może korzystać z zoptymalizowanego blokowania.

UPDATE t5
    SET t5.b = t6.b
FROM t5 WITH (REPEATABLEREAD)
     INNER JOIN t6
         ON t5.a = t6.a;

W poprzednim przykładzie zapytania tylko tabela t5 używa poziomu izolacji REPEATABLE READ i utrzymuje blokady do końca transakcji. Inne aktualizacje t5 nadal mogą korzystać z zoptymalizowanego blokowania. To samo dotyczy wskazówki HOLDLOCK.

Często zadawane pytania

Czy zoptymalizowane blokowanie jest domyślnie włączone zarówno w nowych, jak i istniejących bazach danych?

W usłudze Azure SQL Database, Azure SQL Managed Instance AUTD oraz bazie danych SQL w usłudze Microsoft Fabric, tak. W programie SQL Server 2025 (17.x) zoptymalizowane blokowanie jest domyślnie wyłączone, ale można je włączyć w dowolnej bazie danych użytkownika z włączonym przyspieszonym odzyskiwaniem bazy danych.

Jak mogę wykryć, czy zoptymalizowane blokowanie jest włączone?

Zobacz Czy włączono zoptymalizowane blokowanie?

Co zrobić, jeśli chcę wymusić blokowanie zapytań pomimo zoptymalizowanego blokowania?

Jeśli włączono funkcję RCSI, użyj READCOMMITTEDLOCK wskazówki tabeli, aby wymusić blokowanie między dwoma zapytaniami po włączeniu zoptymalizowanego blokowania.

Czy zoptymalizowane blokowanie jest używane w replikach wtórnych tylko do odczytu?

Nie, ponieważ instrukcje DML nie mogą działać na replikach tylko do odczytu, a odpowiednie blokady na poziomie wierszy i stron nie są zakładane.

Czy zoptymalizowane blokowanie jest używane podczas modyfikowania danych w bazie danych tempdb i w tabelach tymczasowych?

Nie w tej chwili.