Edit: Wie @MaxVernon hervorhebt , ist das Folgende in keiner Weise ein Vorschlag, NOLOCK zu verwenden , und ich hätte auch nur erwähnen sollen, die Transaktionsebene auf zu setzen READ UNCOMMITED
und die negative Konnotation dort stehen zu lassen, als NOLOCK
zuerst aufzurufen. So wie ursprünglich gepostet:
Das schnelle und einfache lautet: "Ja, die erste Abfrage blockiert die zweite Abfrage, es sei denn, ein bestimmter Indexhinweis ist angegeben ( NOLOCK , manchmal als" Dirty Read "bezeichnet) oder die Transaktionsisolationsstufe der zweiten Abfrage ist auf READ UNCOMMITED
(die identisch funktioniert)." Nein, tut es nicht."
In Reaktion auf die zusätzlichen Details in der Frage, die die Aufnahme einer WITH
Klausel in die zweite beinhalten SELECT
, die sich gegenseitig ausschließt oder auf andere Weise, werden die Wechselwirkungen zwischen den beiden Abfragen weitgehend gleich sein.
IF NOT EXISTS ( SELECT 1
FROM sys.objects
WHERE name = 'Foo'
AND type = 'U' )
BEGIN
--DROP TABLE dbo.Foo;
CREATE TABLE dbo.Foo
(
Foo_PK BIGINT IDENTITY( 1, 1 ) NOT NULL,
PRIMARY KEY ( Foo_PK ),
Bar BIT,
x BIT,
y BIT,
z BIT
);
CREATE NONCLUSTERED INDEX IX_Foo_x
ON dbo.Foo ( x );
INSERT INTO dbo.Foo ( Bar, x, y, z )
VALUES ( 1, 1, 1, 1 ), ( 0, 0, 0, 0 );
END;
GO
BEGIN TRANSACTION;
UPDATE dbo.Foo
SET y = 0
WHERE x = 1;
-- COMMIT TRANSACTION;
Führen Sie in einer separaten Sitzung Folgendes aus:
SELECT *
FROM dbo.Foo WITH ( NOLOCK );
GO
SELECT *
FROM dbo.Foo;
Sie können die aktuell gehaltenen Sperren überprüfen, indem Sie sie ausführen sp_lock
, vorzugsweise in einer weiteren separaten Sitzung:
EXECUTE dbo.sp_lock;
Es sollte eine KEY
Typensperre angezeigt werden, die von der Spid gehalten wird, die die Einfügetransaktion im X
(exklusiven) Modus ausführt , nicht zu verwechseln mit den anderen IX
(absichtlich-exklusiven) Sperren. Die Sperrdokumentation gibt an, dass die KEY
Sperre zwar bereichsspezifisch ist, jedoch auch verhindert, dass andere Transaktionen die betroffenen Spalten einfügen oder aktualisieren, indem die darin enthaltenen Daten so geändert werden, dass sie in diesen Bereich der ursprünglichen Abfrage fallen. Da die Sperrung selbst exklusiv ist, verhindert die erste Abfrage den Zugriff auf die Ressource durch eine andere gleichzeitige Transaktion. Tatsächlich sind alle Zeilen der Spalte gesperrt, unabhängig davon, ob sie in den von der ersten Abfrage angegebenen Bereich fallen oder nicht.
Die S
Sperre, die von der zweiten Sitzung gehalten wird, bleibt so lange bestehen, WAIT
bis die X
Sperre aufgehoben wird, wodurch verhindert wird, dass eine andere X
(oder eine andere U
) Sperre für diese Ressource von einer anderen gleichzeitigen Spid übernommen wird, bevor die zweite Sitzung ihre Leseoperation abgeschlossen hat, was die Existenz der S
Sperre rechtfertigt .
Jetzt eine Bearbeitung für Klarheit: Wenn ich mich nicht irre, was ein zerstörendes Lesen ist aus der kurzen Beschreibung der hier genannten Risiken ... Bearbeiten 3 : Ich habe realisiert Ich betrachte nicht die Wirkung eines Hintergrund - Checkpoint , der schreibt eine als noch nicht festgeschriebene Transaktion auf Festplatte, also ja, meine Erklärung war irreführend.
In der zweiten Abfrage kann (und wird in diesem Fall) der erste Stapel nicht festgeschriebene Daten zurückgeben. Der zweite Stapel, der in der Standardtransaktionsisolationsstufe von ausgeführt READ COMMITED
wird, wird erst nach Abschluss eines Commits oder Rollbacks in der ersten Sitzung zurückgegeben.
Von hier aus können Sie Ihre Abfragepläne aussehen und die damit verbundenen Sperre Ebenen, aber noch besser, können Sie alles über Schlösser in SQL Server lesen Sie hier .
SELECT * FROM Table1
wenn das genau das ist, was ich brauche?