Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

SQL Server-Sperreneskalation

Einführung

Relationale Datenbanken folgen den ACID-Eigenschaften bei der Implementierung von Transaktionen – Atomizität, Konsistenz, Isolation und Dauerhaftigkeit. Isolation ist notwendig, um sicherzustellen, dass mehrere Transaktionen keine Änderungen an Daten verursachen und die letztendlichen Ergebnisse inkonsistent bleiben können. Um sicherzustellen, dass die Vorgänge isoliert bleiben, wendet SQL Server Sperrmechanismen an.

Sperrmodi und Hierarchie

Der Mechanismus von SQL Server für die Parallelitätssteuerung ist beteiligt. Um die Leistung in Bezug auf Sperrwartezeiten, Deadlocks und dergleichen zu optimieren, müssen Sie eine Entscheidung basierend auf dem spezifischen Szenario treffen.

In SQL Server können Sperren auf verschiedene Weise und auf mehreren Granularitätsebenen gehalten werden. Sperrmodi sind die spezifischen Möglichkeiten, dies zu tun, und ihre Ebenen sind Sperrhierarchien.

Abbildung 1 zeigt die in SQL Server verfügbaren Sperrmodi für die standardmäßige Transaktionsisolationsstufe (READ COMMITTED):

Übersicht über die Sperreneskalation

SQL Server kann Ressourcen auf mehreren Ebenen sperren. Es hängt von den effizientesten Handlungen gemäß der Art der Arbeitsbelastung ab. Tabelle 1 zeigt die Ressourcen, die gesperrt werden können.

  • Sperren auf einer granulareren Ebene (z. B. Sperren auf Zeilenebene) ermöglichen eine höhere Parallelität und weniger Blockierung.
  • Sperren auf höherer Ebene (z. B. Sperre auf Tabellenebene) verringern die Parallelität. Je nachdem, wie lange die eigentliche Anweisung dauert, können sie weitere Blockierungen verursachen.

SQL Server wählt die erforderliche Sperrebene gemäß internen Metriken aus.

Eine Sperreneskalation findet statt, wenn eine Sperre von einer feineren Granularitätsebene zu einer gröberen Ebene konvertiert wird.

Z. B. Konvertieren einer Zeilensperre in eine Tabellensperre (siehe Tabelle 1).

Ressource Beschreibung
RID Die Zeilenkennung, die verwendet wird, um eine einzelne Zeile innerhalb eines Heaps zu sperren.
SCHLÜSSEL Die Zeilensperre innerhalb eines Indexes, die verwendet wird, um Schlüsselbereiche in serialisierbaren Transaktionen zu schützen.
SEITE Die 8-Kilobyte (KB)-Seite in einer Datenbank, z. B. Daten- oder Indexseiten.
UMFANG Die zusammenhängende Gruppe von acht Seiten, z. B. Daten- oder Indexseiten.
HoBT Der Haufen oder B-Baum. Die Sperre schützt einen B-Baum (Index) oder die Heap-Datenseiten in einer Tabelle, die keinen gruppierten Index hat.
TABELLE Die gesamte Tabelle, einschließlich aller Daten und Indizes.
DATEI Die Datenbankdatei.
ANWENDUNG Die anwendungsspezifische Ressource.
METADATEN Metadatensperren.
ALLOCATION_UNIT Die Zuordnungseinheit.
DATENBANK Die gesamte Datenbank.

Die Gründe für die Sperreneskalation

Sperren in SQL Server können ziemlich teuer sein. Für jede Sperre, die der Lock Manager erwirbt, muss SQL Server Speicher reservieren – 64 Bytes oder 128 Bytes. Die Höhe hängt davon ab, ob es sich jeweils um ein 32-Bit- oder ein 64-Bit-System handelt.

Wenn die Anzahl der Zeilensperren für eine Tabelle zunimmt, muss SQL Server immer mehr Arbeitsspeicher erwerben. Daher hungern andere Prozesse und haben keinen Speicher mehr.

Es ist sinnvoll, Zeilensperren und Seitensperren in eine einzige Sperre auf Tabellenebene (Objektebene) umzuwandeln. Dies passiert, wenn die Anzahl der Sperren für diese Tabelle 5000 überschreitet.

Die Kompromittierung tritt auf, wenn die gesamte Tabelle für andere Sitzungen im Transaktionsprozess nicht mehr verfügbar ist.

Demonstration der Sperrenausweitung

Wir können Lock Escalation mit dem Code in Listing 1 demonstrieren.

Lassen Sie uns zunächst die Tabelle ein wenig beschreiben. Produktion.ProdukteI ist eine relativ kleine Tabelle mit etwa 7777 Zeilen. Die Bauelemente sind der gleiche Satz von 77 Reihen, 101 Mal dupliziert. Der Code in Listing 1 besteht aus drei Versionen derselben Update-Anweisung, die jeweils in einer Transaktion eingeschlossen sind.

-- Listing 1: Demonstrating Lock Escalation

-- Update very few rows
BEGIN TRAN

use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice='18.00';

ROLLBACK

-- Update a large number of rows
BEGIN TRAN

use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice>'18.00';

ROLLBACK

-- Update over 5000 rows
BEGIN TRAN

use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00';

ROLLBACK 

Zur besseren Übersicht werden wir den Inhalt von Listing 1 aufschlüsseln.

Sehen wir uns vorher Listing 2 an – eine Abfrage zur Anzeige der in der TSQLV4-Datenbank gehaltenen Sperren.

Unsere erste Aktion besteht darin, Listing 1a auszuführen. Dann verwenden wir Listing 2, um zu untersuchen, wie der Lock Manager das Sperren in dem Szenario durchführt. Wir führen Listing 1a aus, ohne die Rollback-Anweisung abzusetzen. Auf diese Weise bewahren wir die Sperren lange genug, damit die Abfrage in Listing 2 sie erfassen kann.

-- Listing 1a: Demonstrating Lock Escalation
-- Update very few rows

BEGIN TRAN

use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice='18.00';

ROLLBACK

-- Listing 2: Displaying Locks Held in Database TSQLV4

USE TSQLV4
GO
SELECT 
resource_type
, DB_NAME (resource_database_id) database_name
--, OBJECT_NAME(resource_associated_entity_id) resource_name
, request_mode
, request_type
, request_status
, request_reference_count
, request_session_id
, resource_associated_entity_id
, OBJECT_NAME(resource_associated_entity_id) [object_name] --small obj ids
, getuser.login_name
FROM sys.dm_tran_locks
CROSS APPLY dmv.dbo.getuser(request_session_id) as getuser
WHERE DB_NAME (resource_database_id)='TSQLV4';

Wenn wir die Abfrage in Listing 1a ausführen und dann die Sperren mit der Abfrage in Listing 2 überprüfen, gibt SQL Server das in Abbildung 2 gezeigte Ergebnis zurück.

404 Zeilen in der Tabelle haben unitprice=’18.00’ . Der Lock Manager sperrt diese Zeilen zusammen mit den anderen Sperren jeder erforderlichen Ebene. Es erhöht die Zeilenanzahl in Abbildung 2 auf 467.

-- Listing 1b: Demonstrating Lock Escalation
-- Update a large number of rows
BEGIN TRAN

use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice>'18.00';

ROLLBACK

Wir beobachten ein ähnliches Verhalten, wenn wir die Abfrage in Listing 1b ausführen. Diesmal haben wir es mit 4406 Zeilen zu tun. Es spiegelt die Anzahl der Zeilen in der Tabelle Production.ProductI mit dem Einheitspreis> 18,00 wider.

-- Listing 1c: Demonstrating Lock Escalation
-- Update over 5000 rows
BEGIN TRAN

use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00';

ROLLBACK

Wenn wir weiter gehen und den Code in Listing 1c ausführen, sehen wir ein anderes Verhalten (siehe Abbildung 4).

Listing 1c versucht, alle 7777 Zeilen in der Production.ProductI-Tabelle zu aktualisieren. SQL Server stellt fest, dass das Sperren so vieler Zeilen nicht mehr effizient ist, um die Isolation zu gewährleisten. Stattdessen wird die gesamte Tabelle gesperrt.

Mehr zur Sperreneskalation

Die Tabellensperre impliziert, dass keine andere Sitzung ihre Zeilen für die Transaktionsdauer ändern kann, was passieren kann, selbst wenn eine blockierende Sitzung nicht alle Zeilen in der Tabelle manipuliert.

Erwähnenswert ist auch, dass andere Faktoren beeinflussen können, wie Sperren in SQL Server erworben und eskaliert werden. Dies sind die konfigurierte Isolationsstufe, Indizierung und Trace-Flags.

Die Ablaufverfolgungsflags T1211 und T1224 können angewendet werden, um die Sperrenausweitung vollständig zu deaktivieren. Die Sperrenausweitung kann auch mit dem folgenden Code für eine bestimmte Tabelle deaktiviert und aktiviert werden:

-- Listing 5: Disable and Enable Lock Escalation

ALTER TABLE Production.ProductsI SET (LOCK_ESCALATION=DISABLE);

ALTER TABLE Production.ProductsI SET (LOCK_ESCALATION=TABLE);

Möglicherweise möchten Sie dies tun, um das Blockieren des damit verbundenen Sperrens der gesamten Tabelle zu reduzieren. Aufgrund der Auswirkungen auf das Gedächtnis sollte eine vorübergehende Maßnahme in Erwägung gezogen werden.

Schlussfolgerung

SQL Server verwendet die Sperrenausweitung, um die Auswirkungen einer differenzierteren Sperrung auf Serverressourcen zu steuern. Um anzuzeigen, wie diese Sperren auftreten – Zeilensperren, Seitensperren, Objektsperren usw. – fragen Sie die dynamische Verwaltungsansicht sys.dm_tran_locks ab. Es bietet neben der Sperreneskalation viele Informationen zum Sperren.

Obwohl es möglich ist, das Verhalten des Lock Managers zu manipulieren, ist es wichtig, dies mit großer Sorgfalt zu tun. Es ist auch wichtig, die genauen Leistungsauswirkungen aller Bemühungen zu kennen, die darauf gerichtet sind, solche Änderungen vorzunehmen.

Referenzen

  1. Korotkevitch, D., 2016. Pro SQL Server Internals. Florida:Dmitri Korotkevitch
  2. Sperren von Szenarien mit Sys.dm_tran_locks
  3. Leitfaden für Transaktionssperrung und Zeilenversionierung