Kann jemand erklären, warum ausgewählt wird mit Nolock einen Trank aktualisierter Daten abfragt?

dba.stackexchange https://dba.stackexchange.com/questions/11571

  •  16-10-2019
  •  | 
  •  

Frage

Ich las die Antwort von hier (Aus Stackoverflow sollte ich denke, dass er hier fragen sollte)

Nolock bedeutet überhaupt keine Schlösser.

Ihre Abfrage kann Abschnitte von Daten nach dem Vor Update und Teilen nach dem Update in einer einzelnen Abfrage zurückgeben.

Ich verstehe, dass Nolock das Schloss nicht an den Tisch platziert, damit andere Personen gleichzeitig abfragen können.

Aus der Antwort und dem Beispiel, das es zeigt, holt es Daten, während die Daten aktualisiert werden.

Warum passiert das?

Ich gehe davon aus, dass Normal ausgewählt wird. Es wird versuchen, die Sperre in der Tabelle zu platzieren. Wenn Sie also die Aktualisierungsanweisung ausgeführt haben, platziert sie eine Sperre auf der Zeile oder Seite. Wenn ich dann versuche, die SELECT -Anweisung auszuführen, kann die Sperre nicht eingesetzt werden, wenn die Update -Anweisung -Sperre veröffentlicht wird.

Aber in diesem Fall versucht die Auswahlanweisung nicht, die Sperre auf die Tabelle zu setzen, sodass sie ausgeführt werden kann, ohne auf die Update -Anweisung zu warten, die die Sperre veröffentlichen?

War es hilfreich?

Lösung

Es ist nicht ganz wahr, dass NOLOCK bedeutet überhaupt keine Schlösser platzieren. Abfragen unter diesem Hinweis dauern immer noch Sch-S Schlösser und (möglicherweise HOBT Schlösser).

Unter read committed Isolationsstufe SQL Server wird (normalerweise) Zeilenebene einnehmen S Sperren und veröffentlichen Sie sie, sobald die Daten gelesen werden. Diese sind mit dem unvereinbar X Schlösser, die über ungewordene Updates gehalten werden und so schmutzige Lesevorgänge verhindern.

Im Beispiel in der verknüpften Antwort die SELECT Die Abfrage wird nicht blockiert, wenn sie auf eine modifizierte Zeile stoßen, sodass das Lesen teilweise Updates sehr wahrscheinlich ist.

Es kann auch bei Standardeinstellung passieren read committed Isolationsniveau aber auch, dass a SELECT liest einige Zeilen mit dem Wert "vor" und anderen mit dem "After" -Werwert. Es ist nur erforderlich, um eine Situation zu entwickeln, in der

  1. Wählen Sie Abfrage Lesewert der Zeile aus R1 und veröffentlicht seine S sperren
  2. Aktualisierung von Abfragen -Updates R2 und nimmt an X sperren
  3. Wählen Sie Abfrage -Versuche zum Lesen R2 und ist blockiert.
  4. Aktualisierung von Abfragen -Updates R1 und nimmt an X sperren.
  5. Aktualisieren Sie die Transaktions -Commits, wodurch die Sperren veröffentlicht und das Auswählen gelesen werden kann R2

Diese Art von Situation kann zum Beispiel auftreten, wenn die SELECT und UPDATE Verwenden Sie verschiedene Indizes, um die interessierenden Zeilen zu lokalisieren.

Beispiel

CREATE TABLE T
(
X INT IDENTITY PRIMARY KEY,
Y AS -X UNIQUE,
Name varchar(10),
Filler char(4000) DEFAULT 'X'
)


INSERT INTO T (Name)
SELECT TOP 2500 'A'
FROM master..spt_values

Jetzt in einem Abfragefenster laufen

DECLARE @Sum int

SELECT 'SET @@ROWCOUNT' WHERE 1=0

WHILE (@@ROWCOUNT = 0)
SELECT @Sum = SUM(LEN(Name))
FROM T 
WHERE Y IN (-1, -2500)
HAVING SUM(LEN(Name)) = 3

Dies wird in einer unendlichen Schleife laufen. In einem anderen Lauf

UPDATE T 
SET Name=CASE WHEN Name = 'A' THEN 'AA' ELSE 'A' END

Dies wird wahrscheinlich die Schleife in der anderen Abfrage stoppen (versuchen Sie es erneut, wenn nicht). Dies bedeutet, dass sie auch gelesen haben muss A,AA oder AA,A

Andere Tipps

Der Hinweis NOLOCK entspricht der Transaktions -Isolationsstufe READ UNCOMMITTED, nur auf den Umfang einer Tabellenzugriffsmethode beschränkt.

Was macht das, was die Nichtvermittlung in Ihrem Ergebnis erscheint? Hmm, ist eigentlich eine Frage von "Was es nicht tut. Ich werde unten erklären.

Nun (dies ist eine grobe Vereinfachung, ich weiß) MSSQL (in seinem Standardverhalten) ist eine Sperrenmotor - was bedeutet, dass die Sperre zum Lesen/Schreiben von Daten auf konsistente Weise verwendet. In dieser über vereinfachten Erklärung verwendet MSSQL zwei Arten von Schlössern: gemeinsames Schloss und Exklusive Schloss.

Eine gemeinsame Sperre ist eine Sperre, mit der eine Ressource (die eine Zeile, eine Zeilenseite oder sogar eine ganze Tabelle sein kann) gelesen werden kann -, aber nicht zulässt, dass ein Schreiben darauf eingeschrieben wird. Wenn die Transaktion T1 also eine S -Sperre in der R1 -Zeile einbringt, werden alle Transaktionen, die versuchen, R1 zu lesen, diese Lektüre erhalten, aber während das S -Schloss lebendig ist, kann niemand an R1 schreiben.

Ein exklusives (x) -Schress ist das Gegenstück zum gemeinsam genutzten Schloss. Es ermöglicht den exklusiven Zugriff auf eine Ressource - keine andere Transaktion kann lesen oder schreiben, außer dem, der das X -Sperre erhielt. Wenn T1 im obigen Beispiel kein S -Schloss, sondern eine X -Sperre für R1 bekam, Niemand außer T1 kann es lesen oder schreiben.

Das ist das Teory. Die Isolationsniveaus ehren die Schlösser und respektieren ihre Prävalenz und Eigenschaften. Alle außer READ UNCOMMITTED. Es gibt einfach ein * (geben Sie hier Ihr schlechtes Mund Wort Ihrer Präferenz) den Schlössern in Bezug auf das Lesen - Sie können die Zeile immer noch nicht aktualisieren. Eine andere Transaktion hat ein X -Sperre. Es heißt einfach: "Ich werde alles lesen, was für den Abfrageplan relevant ist - ignorieren, was Sperren dran sind."Und TU es.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit dba.stackexchange
scroll top