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

Grundlagen und Verwendung des NOLOCK-Hinweises in SQL Server

Die Hauptidee des Sperrmechanismus von SQL Server besteht darin, dass er die Konsistenz von Transaktionen steuert. Wenn ein Prozess gemäß diesem Prinzip Einfüge-, Lösch- oder Aktualisierungsvorgänge ausführen möchte, sperrt die SQL Server-Engine die Zeile oder Zeilen und lässt keinen anderen Prozess zu, bis die Transaktion abgeschlossen ist. Dieser Verriegelungsmechanismus kann unter Umständen zu Performance-Problemen wie hohen gleichzeitigen Prozessdrücken führen. So können Deadlock-Probleme (Deadlock ist ein Nebenläufigkeitsproblem, bei dem zwei Transaktionen gleichzeitig auf dieselben Daten zugreifen möchten) in Ihrer Datenbank auftreten. In diesem Artikel konzentrieren wir uns darauf, wie Sie Sperrprobleme mit Hilfe des NOLOCK-Hinweises vermeiden können. Lassen Sie uns zunächst die wichtigsten Grundlagen und Details der Dirty-Read-Methodik lernen, da der NOLOCK-Hinweis Dirty-Reading verursachen kann.

Dirty Read: Bei dieser Lesemethodik liest der Leseprozess nicht festgeschriebene Daten, und der Leseprozess kümmert sich nicht um offene Transaktionen, sodass die Sperren zu keinen Problemen im Leseprozess führen. Im Ergebnis reduziert diese Art des Lesens die Verriegelungsprobleme. Die Dirty-Reading-Methode hat jedoch Vor- und Nachteile, da Dirty-Reading zu Inkonsistenzproblemen in der Ergebnismenge der SELECT-Anweisung führen kann. Wie bereits erwähnt, können diese Ergebnissätze nicht festgeschriebene Transaktionsdaten enthalten, deshalb müssen wir das Dirty Reading berücksichtigen, wenn wir uns für diese Art des Lesens entscheiden. Wir können uns über die Genauigkeit der Zeilen, die wir beim Dirty Reading erstellen, nicht sicher sein, da diese Zeilen rückgängig gemacht werden können. Andererseits ermöglicht uns diese Art des Lesens, Sperrprobleme zu vermeiden und die Leistung von SQL Server zu steigern.

NOLOCK: Die Standard-Isolationsstufe von SQL Server ist Read Committed, und in dieser Isolationsstufe erlaubt SQL Server nicht, gesperrte Objekte zu lesen, die durch nicht festgeschriebene Transaktionen gesperrt sind. Außerdem können diese gesperrten Objekte entsprechend der Sperreskalation geändert werden.

Hinweis:In diesem Artikel zum Hauptkonzept von SQL Server-Sperren finden Sie Details zu Sperren und Sperrenausweitung.

Stellen Sie sich vor, Sie haben zwei Datenbankbenutzer und diese Benutzer möchten den Update- und Select-Vorgang für die Datenbank ausführen. Ein erster Benutzer beginnt, eine bestimmte Zeile in der Tabelle zu aktualisieren, und dann möchte der andere Benutzer dieselbe Zeile lesen. Diese beiden Benutzer führen die folgenden Update- und Select-Anweisungen aus, die im folgenden Bild dargestellt sind.

In diesem Fall wartet Benutzer2 mindestens 10 Sekunden, dann wird die Transaktion von Benutzer1 rückgängig gemacht, und dann Benutzer2 kann die grüne Zeile lesen, da die gesperrte Zeile von Benutzer1 freigegeben wird. Dies ist das Standardverhalten der SQL Server-Isolationsstufe Read Committed.

Nun werden wir diesen Fall in SQL Server demonstrieren. Zuerst erstellen wir die FruitSales-Tabelle und ihre Zeilen.

CREATE TABLE FruitSales
(Id INT IDENTITY (1,1)  PRIMARY KEY, [Name] Varchar(20) ,
SalesTotal Float)
GO

INSERT INTO FruitSales VALUES
('Apple',10) ,('Orange',8), ('Banana',2)

In diesem Schritt öffnen wir zwei SQL Server Management Studio-Abfragefenster und führen die user1-Abfrage und dann die user2-Abfrage aus.

	  ---USER1----

BEGIN TRAN 
UPDATE FruitSales SET SalesTotal =20 WHERE Id=2 
WAITFOR DELAY '00:00:10'
ROLLBACK TRANSACTION

	---USER2----
SET STATISTICS TIME ON
SELECT * FROM FruitSales WHERE Id=2

Wie Sie im obigen Bild sehen können, wartet die zweite Abfrage bis zum Rollback der user1-Transaktion.

Jetzt werden wir den NOLOCK-Hinweis und die Verwendungsdetails besprechen. Der NOLOCK-Hinweis ist der beliebteste Tabellenhinweis, der von Datenbankentwicklern und -administratoren verwendet wird, um Sperrprobleme in SQL Server-Datenbanken zu beseitigen. Mit Hilfe des NOLOCK-Tabellenhinweises können wir gesperrte Objekte (Zeile, Seite oder Tabelle) lesen, die durch offene Transaktionen gesperrt sind. Der NOLOCK-Hinweis setzt das Standardverhalten des SQL Server-Abfrageoptimierers außer Kraft, sodass die Select-Anweisung die gesperrten Objekte lesen kann.

Jetzt fügen wir den NOLOCK-Hinweis zur User2-Select-Anweisung hinzu und starten dann das User1-Update und führen dann die User2-Select-Anweisung aus.

---USER1----

BEGIN TRAN 
UPDATE FruitSales SET SalesTotal =20 WHERE Id=2 
WAITFOR DELAY '00:00:10'
ROLLBACK TRANSACTION

			---USER2----
SET STATISTICS TIME ON
SELECT * FROM FruitSales WITH(NOLOCK) WHERE Id=2

In diesem Schritt erklären wir, wie der NOLOCK-Hinweis auf die user2-Select-Anweisung wirkt. Benutzer1 führt die aktualisierte Anweisung in einer expliziten Transaktion aus, und dann führt Benutzer2 die Auswahlanweisung aus, und die Ergebnismenge gibt ohne Verzögerung den Abschluss der Transaktion zurück. Das ist die Hauptidee von NOLOCK, es liest gesperrte Objekte.

Jetzt konzentrieren wir uns auf die Ergebnismenge der select-Anweisung. Die select-Anweisung von user2 hat den SalesTotal-Wert 20 abgerufen, aber der tatsächliche Wert von SalesTotal ist immer noch 8. Denken Sie daran, dass Sie mit dieser Art von ungenauen Datenergebnissen konfrontiert werden können, wenn Sie den NOLOCK-Tabellenhinweis in Ihrer select-Anweisung verwenden.

Tipp: Das Schlüsselwort „WITH“ ist ein veraltetes Feature, daher empfiehlt Microsoft, es in Ihrer neuen Datenbankentwicklung nicht zu verwenden und das Schlüsselwort „WITH“ in Ihren aktuellen Entwicklungen zu entfernen. Sie können die Verwendung des NOLOCK-Hinweises ohne das Schlüsselwort „WITH“ finden.

---USER1----
BEGIN TRAN 
UPDATE FruitSales SET SalesTotal =20 WHERE Id=2 
WAITFOR DELAY '00:00:10'
ROLLBACK TRANSACTION
SELECT * FROM FruitSales WHERE Id=2

   --USER2---
SELECT * FROM FruitSales (NOLOCK) WHERE Id=2

Außerdem entspricht der READUNCOMMITTED-Tabellenhinweis dem NOLOCK-Hinweis und wir können den READUNCOMMITTED-Hinweis anstelle des NOLOCK-Hinweises verwenden.

SELECT * FROM FruitSales (READUNCOMMITTED) WHERE Id=2

Trotzdem gibt es einen besonderen Fall bezüglich des NOLOCK-Hinweises, der die Sperrbarriere nicht passieren kann. Wenn ein Prozess eine Tabelle ändert, kann der NOLOCK-Hinweis diese Art von Sperre nicht überwinden und den Lesevorgang nicht fortsetzen. Der Grund für dieses Problem ist, dass der NOLOCK-Hinweis die Sch-S-Sperre (Schema-Stabilität) und die ALTER TABLE-Anweisung die SCH-M-Sperre (Schema-Änderung) erhält, sodass ein Konflikt auftritt.

Zuerst lernen wir die Object_Id der FruitSales-Tabelle mit Hilfe der folgenden Abfrage kennen.

select OBJECT_ID('FruitSales')

Führen Sie die folgende user1-Abfrage und dann die user2-Abfrage aus. Infolgedessen verzögert die Benutzer2-Abfrage den Abschluss des Benutzer1-Tabellenänderungsprozesses.

--USER1---
BEGIN TRAN
ALTER TABLE FruitSales
ADD ColorofFruit varchar(200) 
WAITFOR DELAY '00:00:35
GO
COMMIT TRAN

   --USER2---
SELECT * FROM FruitSales (NOLOCK) WHERE Id=2

Öffnen Sie das neue Abfragefenster und führen Sie die folgende Abfrage aus. Diese Abfrage hilft dabei, den Sperrtyp der Abfragen user1 und user2 herauszufinden.

SELECT Resource_type,
	 Resource_database_id,
	 Resource_description,
	 Resource_associated_entity_id,
	 Resource_lock_partition,
	 Request_mode,
	 Request_type,
	 Request_status,
	 Request_session_id,
	 Request_request_id,
	 Request_owner_type,
	 Request_owner_id,
	 Lock_owner_address
FROM sys.dm_tran_locks
where resource_associated_entity_id =647673355

Jetzt sehen wir uns die Lock-Kompatibilitätsmatrix für die SCH-M- und SCH-S-Interaktion an. Die Matrix beschreibt, dass die Interaktion zwischen SCH-M und SCH-S einen Konflikt verursacht.

Fazit

In diesem Artikel haben wir den Dirty-Reading-Prozess und den NOLOCK-Hinweis erwähnt. Die Verwendung des NOLOCK-Hinweises ist eine effektive Methode, um eine gesperrte Seite zu lesen, hat aber auch einige Vor- und Nachteile. Aus diesem Grund müssen Sie den NOLOCK-Hinweis beachten, bevor Sie ihn verwenden.

Referenzen

SQL Server Transaction Locking and Row Versioning Guide

Hinweise (Transact-SQL) – Tabelle

TRANSAKTIONSISOLATIONSLEVEL FESTLEGEN (Transact-SQL)