Was ist "with (nolock)" in SQL Server?

610

Kann jemand die Auswirkungen der Verwendung with (nolock)auf Abfragen erklären , wenn Sie sie verwenden sollten / nicht?

Wenn Sie beispielsweise eine Bankanwendung mit hohen Transaktionsraten und vielen Daten in bestimmten Tabellen haben, in welchen Arten von Abfragen wäre nolock in Ordnung? Gibt es Fälle, in denen Sie es immer verwenden sollten / nie verwenden sollten?

Andy White
quelle
Ich habe in stackoverflow.com/questions/3836282/… und stackoverflow.com/questions/3836032/… hauptsächlich Jonathan Allens Antwort stackoverflow.com/questions/686724/…
Gennady Vanin Геннадий Ванин
1
Ein Link hier - mssqltips.com/sqlservertip/2470/…
Steam
1
Hier ist eine hervorragende Zusammenfassung der Auswirkungen der Verwendung von NOLOCK blogs.msdn.com/b/davidlean/archive/2009/04/06/…
Bryan

Antworten:

461

WITH (NOLOCK) entspricht der Verwendung von READ UNCOMMITED als Transaktionsisolationsstufe. Sie laufen also Gefahr, eine nicht festgeschriebene Zeile zu lesen, die anschließend zurückgesetzt wird, dh Daten, die es nie in die Datenbank geschafft haben. Dies kann zwar verhindern, dass Lesevorgänge durch andere Vorgänge blockiert werden, birgt jedoch ein Risiko. In einer Bankanwendung mit hohen Transaktionsraten wird es wahrscheinlich nicht die richtige Lösung für das Problem sein, das Sie meiner Meinung nach damit lösen möchten.

David M.
quelle
156
Die meisten Bankanwendungen können nolock sicher verwenden, da sie im geschäftlichen Sinne transaktional sind. Sie schreiben nur neue Zeilen, Sie aktualisieren sie nie.
Jonathan Allen
49
@ Grauenwolf- Eine eingefügte, aber nicht festgeschriebene Zeile kann immer noch zu fehlerhaften Lesevorgängen führen.
Saasman
16
@ Saasman- Wenn Sie niemals Rollback-Transaktionen durchführen, spielt das keine Rolle. Und bei einer Tabelle nur zum Einfügen sind die Chancen für einen Rollback gering. Und wenn sie dennoch auftreten, werden Sie alles im Abweichungsbericht am Ende des Tages beheben.
Jonathan Allen
1
Ich bin verwurzelt. Ich gehe davon aus, dass die Hinzufügung keine Sperrhinweise hinzugefügt hat. Zum Beispiel:
Ross Bush
11
Wenn Sie NOLOCKmit a verwenden SELECT, besteht das Risiko, dass dieselben Zeilen mehrmals zurückgegeben werden (doppelte Daten), wenn während einer Auswahl jemals Daten in die Tabelle eingefügt (oder aktualisiert) werden.
Ian Boyd
170

Die Frage ist, was schlimmer ist:

  • eine Sackgasse, oder
  • ein falscher Wert?

Bei Finanzdatenbanken sind Deadlocks weitaus schlechter als falsche Werte. Ich weiß, das klingt rückwärts, aber höre mich an. Das traditionelle Beispiel für DB-Transaktionen besteht darin, dass Sie zwei Zeilen aktualisieren, von einer subtrahieren und zu einer anderen hinzufügen. Das ist falsch.

In einer Finanzdatenbank verwenden Sie Geschäftsvorfälle. Das bedeutet, dass jedem Konto eine Zeile hinzugefügt wird. Es ist äußerst wichtig, dass diese Transaktionen abgeschlossen sind und die Zeilen erfolgreich geschrieben wurden.

Es ist keine große Sache, den Kontostand vorübergehend falsch zu machen. Dafür ist die Abstimmung am Ende des Tages gedacht. Und ein Überziehungskredit von einem Konto tritt weitaus häufiger auf, weil zwei Geldautomaten gleichzeitig verwendet werden, als aufgrund eines nicht festgeschriebenen Lesevorgangs aus einer Datenbank.

Trotzdem hat SQL Server 2005 die meisten Fehler behoben, die NOLOCKerforderlich wurden. Wenn Sie SQL Server 2000 oder früher nicht verwenden, sollten Sie es nicht benötigen.

Weiterführende
Literatur Versionierung auf Zeilenebene

Jonathan Allen
quelle
22
Einen Kontostand vorübergehend falsch zu machen, ist keine große Sache? Was ist, wenn Sie bei dieser Transaktion Bargeld aus einem Geldautomaten ohne Überziehungslimit abheben?
Lernen
13
@Learning: Was passiert, wenn Sie das Geld 30 Sekunden vor dem Aufladen Ihrer Karte herausnehmen? Bis die gesamte Kommunikation augenblicklich erfolgt, werden Überziehungskredite eine Tatsache des Lebens sein.
Jonathan Allen
6
+1 In der Finanz-App (überall, nicht nur in Banken) gibt es weder Aktualisierungen noch Löschungen. Auch fehlerhafte Vorgänge werden durch Einfügen von Datensätzen korrigiert. Was ist dieser Begriff auf Englisch? Ist es "storno"? Google hat mir nicht geholfen, diese Frage zu beantworten
Gennady Vanin Геннадий Ванин
7
Später Eintritt ... Deadlocks sollten abgefangen und erneut versucht werden. Schmutzige Lesungen haben Konsequenzen
gbn
4
@ JonathanAllen nur ein Fyi, der Begriff ist UTmost, nicht UP.
Jimmy D
57

Leider geht es nicht nur darum, nicht festgeschriebene Daten zu lesen. Im Hintergrund lesen Sie möglicherweise zweimal Seiten (im Falle eines Seitensplits), oder Sie verpassen die Seiten insgesamt. Daher können Ihre Ergebnisse stark verzerrt sein.

Lesen Sie den Artikel von Itzik Ben-Gan . Hier ist ein Auszug:

"Mit dem NOLOCK-Hinweis (oder dem Festlegen der Isolationsstufe der Sitzung auf READ UNCOMMITTED) teilen Sie SQL Server mit, dass Sie keine Konsistenz erwarten, daher gibt es keine Garantien. Beachten Sie jedoch, dass" inkonsistente Daten "nicht nur dies bedeuten Möglicherweise werden nicht festgeschriebene Änderungen angezeigt, die später rückgängig gemacht wurden, oder Datenänderungen in einem Zwischenstatus der Transaktion. Dies bedeutet auch, dass SQL Server in einer einfachen Abfrage, die alle Tabellen- / Indexdaten scannt, möglicherweise die Scanposition verliert oder Sie möglicherweise enden zweimal die gleiche Reihe bekommen . "

sqlbelle
quelle
5
Etwas weiter unten erklärt er, wie man dieselbe Zeile zweimal erhält: Ich werde die Tabelle T1 so neu erstellen, dass der Clustered-Index für col1 als eindeutiger Index mit der Option IGNORE_DUP_KEY definiert wird. Dies bedeutet, dass in Spalte 1 keine doppelten Werte vorhanden sein können und dass ein Versuch, einen doppelten Schlüssel einzufügen, die Transaktion nicht fehlschlägt und einen Fehler generiert, sondern lediglich eine Warnung generiert. Wenn Sie diese seltsame Option nicht verwenden, müssen Sie sich wahrscheinlich nicht darum kümmern, zweimal Zeilen zu erhalten
JanHudecek
Sie können auch ohne die verkabelte Option immer noch betrügerische Zeilen erhalten - wenn Ihre Abfrage beispielsweise einen Index verwendet, der nicht eindeutig ist. Dies gilt jedoch nicht nur für Nolock.
RMD
54

Das Lehrbuchbeispiel für die legitime Verwendung des Nolock-Hinweises ist die Berichterhebung anhand einer OLTP-Datenbank mit hohem Update.

Um ein aktuelles Beispiel zu nehmen. Wenn eine große US-amerikanische High Street Bank einen stündlichen Bericht erstellen wollte, um nach den ersten Anzeichen eines Stadtebens auf der Bank zu suchen, könnte eine Nolock-Abfrage Transaktionstabellen scannen, in denen Bareinzahlungen und Bargeldabhebungen pro Stadt summiert werden. Für einen solchen Bericht würde der winzige Prozentsatz an Fehlern, der durch zurückgesetzte Aktualisierungstransaktionen verursacht wird, den Wert des Berichts nicht verringern.

Saasman
quelle
31

Sie sind sich nicht sicher, warum Sie Finanztransaktionen nicht in Datenbanktransaktionen verpacken (z. B. wenn Sie Geld von einem Konto auf ein anderes überweisen - Sie legen nicht jeweils eine Seite der Transaktion fest - aus diesem Grund existieren explizite Transaktionen). Selbst wenn Ihr Code auf Geschäftstransaktionen ausgerichtet ist, wie es sich anhört, können alle Transaktionsdatenbanken bei Fehlern oder Ausfällen implizite Rollbacks durchführen. Ich denke, diese Diskussion geht Ihnen weit über den Kopf.

Wenn Sie Probleme beim Sperren haben, implementieren Sie die Versionierung und bereinigen Sie Ihren Code.

Keine Sperre gibt nicht nur falsche Werte zurück, sondern auch Phantomdatensätze und Duplikate.

Es ist ein weit verbreitetes Missverständnis, dass Abfragen dadurch immer schneller ausgeführt werden. Wenn eine Tabelle keine Schreibsperren enthält, macht dies keinen Unterschied. Wenn die Tabelle gesperrt ist, wird die Abfrage möglicherweise schneller, aber es gibt einen Grund, warum Sperren überhaupt erfunden wurden.

Um fair zu sein, hier sind zwei spezielle Szenarien, in denen ein Nolock-Hinweis nützlich sein kann

1) SQL Server-Datenbank vor 2005, die eine lange Abfrage für eine Live-OLTP-Datenbank ausführen muss, ist möglicherweise der einzige Weg

2) Schlecht geschriebene Anwendungen, die Datensätze sperren und die Kontrolle an die Benutzeroberfläche und die Leser zurückgeben, werden auf unbestimmte Zeit blockiert. Nolock kann hier hilfreich sein, wenn die Anwendung nicht repariert werden kann (von Drittanbietern usw.) und die Datenbank entweder vor 2005 ist oder die Versionierung nicht aktiviert werden kann.

Andrew
quelle
11
Ich stimme Ihnen zu, dass NOLOCK nicht verwendet werden sollte, um schlecht geschriebenen Code auszugleichen. Ich denke jedoch, dass Ihr Angriff auf Johnathan nicht gerechtfertigt ist, da er Datenbanktransaktionen nie erwähnt hat . Er wies lediglich darauf hin, dass Finanzanwendungen normalerweise keine Änderungen an Aufzeichnungen zulassen (offensichtlich gibt es einige Ausnahmen). In Ihrem Geldtransfer Beispiel er sagt es seltsam wäre , wenn Sie waren mutieren den Wert des Kontos des Balance statt Hinzufügen eines Soll / Gutschrift zu einem Ledger der Arten.
Chrnola
19
Was passiert Ihrer Meinung nach, wenn Gelder bei verschiedenen Banken von einem Konto auf ein anderes überwiesen werden? Eine Uber-Datenbank sperrt einen Tisch bei der Bank of America und eine andere bei Wells Fargo? Nein. Es wird jeweils eine Finanztransaktion geschrieben, und dann überprüft ein Prozess am Ende des Tages, ob alle Datensätze übereinstimmen.
Jonathan Allen
24

NOLOCKist gleichbedeutend mit READ UNCOMMITTED, Microsoft sagt jedoch, dass Sie es nicht für UPDATEoder DELETEAnweisungen verwenden sollten:

Für UPDATE- oder DELETE-Anweisungen: Diese Funktion wird in einer zukünftigen Version von Microsoft SQL Server entfernt. Vermeiden Sie die Verwendung dieser Funktion in neuen Entwicklungsarbeiten und planen Sie, Anwendungen zu ändern, die diese Funktion derzeit verwenden.

http://msdn.microsoft.com/en-us/library/ms187373.aspx

Dieser Artikel gilt für SQL Server 2005, sodass die Unterstützung für NOLOCKvorhanden ist, wenn Sie diese Version verwenden. Um Ihren Code zukunftssicher zu machen (vorausgesetzt, Sie haben sich für Dirty Reads entschieden), können Sie diesen in Ihren gespeicherten Prozeduren verwenden:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

Seibar
quelle
21

Sie können es verwenden, wenn Sie nur Daten lesen, und es ist Ihnen egal, ob Sie möglicherweise Daten zurückerhalten, die noch nicht festgeschrieben sind.

Bei einem Lesevorgang kann es schneller sein, aber ich kann nicht wirklich sagen, um wie viel.

Im Allgemeinen empfehle ich, es nicht zu verwenden - das Lesen nicht festgeschriebener Daten kann bestenfalls etwas verwirrend sein.

marc_s
quelle
1
Es wäre schön, wenn Sie die Tatsache erwähnen würden, dass SQL Server 2005 über eine Zeilenversionierung verfügt, sodass Nolocks nicht einmal mehr benötigt werden.
Jonathan Allen
Nun, das "with (nolock)" hat auch in SQL Server 2005 noch seinen Platz - aber die Vorteile werden immer schlanker, das stimmt.
marc_s
18

Ein anderer Fall, in dem es normalerweise in Ordnung ist, ist eine Berichtsdatenbank, in der Daten möglicherweise bereits gealtert sind und Schreibvorgänge einfach nicht stattfinden. In diesem Fall sollte die Option jedoch vom Administrator auf Datenbank- oder Tabellenebene festgelegt werden, indem die Standardisolationsstufe geändert wird.

Im allgemeinen Fall: Sie können es verwenden, wenn Sie sehr sicher sind , dass das Lesen alter Daten in Ordnung ist. Das Wichtigste ist, dass es sehr leicht ist, das falsch zu verstehen . Sind Sie beispielsweise sicher, dass sich in Zukunft nichts an der Datenbank ändert, auch wenn dies zum Zeitpunkt des Schreibens der Abfrage in Ordnung ist, um diese Aktualisierungen wichtiger zu machen?

Ich werde auch 2. die Vorstellung, dass es wahrscheinlich keine gute Idee in der Banking-App ist. Oder Inventar App. Oder überall dort, wo Sie an Transaktionen denken.

Joel Coehoorn
quelle
4
Als Person, die an Bankanwendungen arbeitet, muss ich sagen, dass No-Locks kein Problem sind. Transaktionsdatensätze, dh Zeilen, die eingefügt, aber nie aktualisiert oder gelöscht werden, sind überraschend widerstandsfähig gegen die Probleme beim Lesen nicht festgeschriebener Daten.
Jonathan Allen
15

Einfache Antwort - wenn Ihr SQL keine Daten ändert und Sie eine Abfrage haben, die andere Aktivitäten beeinträchtigen könnte (über das Sperren).

Es lohnt sich, alle für Berichte verwendeten Abfragen in Betracht zu ziehen, insbesondere wenn die Abfrage länger als beispielsweise 1 Sekunde dauert.

Dies ist besonders nützlich, wenn Sie Berichte vom Typ OLAP haben, die Sie für eine OLTP-Datenbank ausführen.

Die erste Frage lautet jedoch: "Warum mache ich mir darüber Sorgen?" Nach meiner Erfahrung kommt es häufig vor, dass das Standard-Sperrverhalten verfälscht wird, wenn sich jemand im Modus "Alles versuchen" befindet. Dies ist ein Fall, in dem unerwartete Konsequenzen nicht unwahrscheinlich sind. Zu oft handelt es sich um eine vorzeitige Optimierung, die zu leicht "nur für den Fall" in eine Anwendung eingebettet werden kann. Es ist wichtig zu verstehen, warum Sie es tun, welches Problem es löst und ob Sie das Problem tatsächlich haben.

dkretz
quelle
11

Kurze Antwort:

Nur WITH (NOLOCK)in der SELECT-Anweisung für Tabellen mit einem Clustered-Index verwenden.

Lange Antwort:

WITH (NOLOCK) wird oft als magische Methode genutzt, um das Lesen von Datenbanken zu beschleunigen.

Die Ergebnismenge kann Zeilen enthalten, die noch nicht festgeschrieben wurden und häufig später zurückgesetzt werden.

Wenn WITH (NOLOCK) auf eine Tabelle mit einem nicht gruppierten Index angewendet wird, können Zeilenindizes durch andere Transaktionen geändert werden, während die Zeilendaten in die Ergebnistabelle gestreamt werden. Dies bedeutet, dass in der Ergebnismenge möglicherweise Zeilen fehlen oder dieselbe Zeile mehrmals angezeigt wird.

READ COMMITTED fügt ein zusätzliches Problem hinzu, bei dem Daten in einer einzelnen Spalte beschädigt werden, in der mehrere Benutzer dieselbe Zelle gleichzeitig ändern.

WonderWorker
quelle
2
Das Lesen nicht festgeschriebener Daten ist akzeptabel, wenn die endgültige Entscheidung dadurch nicht geändert wird. Wenn Sie beispielsweise versuchen zu prognostizieren, wie viel Geld Ihr Einzelhandelsgeschäft in den nächsten 6 Monaten verdienen wird, ändert es nichts an Ihrer Meinung über die Zukunft, wenn Sie sehen, dass Tammy 2 Rollen Papierhandtücher gekauft hat, als sie wirklich 3 gekauft hat .
Jonathan Allen
1
Wenn Ihr Filter jetzt enthält, sind Ihre Daten in dem Moment, in dem Sie die Abfrage ausführen, ungenau. Wenn Ihr Filter nur historische Daten enthält, wirkt READ UNCOMITTED sich die Verwendung überhaupt nicht darauf aus. Es gibt einen Grund, warum es in den ANSI-Standard aufgenommen wurde.
Jonathan Allen
2
Sag niemals nie. Wenn Sie möchten, dass die Daten 100% genau sind, sollten Sie nolock nicht verwenden. Für mich ist das normalerweise nicht der Fall. Wenn Daten einem Benutzer präsentiert werden, haben sie sich zu dem Zeitpunkt, zu dem sie auf die Daten reagieren, möglicherweise ohnehin bereits geändert, aber höchstwahrscheinlich nicht, und der Sperrenkonflikt ist die Antwortverzögerungen nicht wert.
Perposterer
Bleiben wir bei existenzwürdigen Systemen. Vergessen Sie nicht, dass Tammy ein vollkommen anständiges Gehirn hat. Daher ist es bestenfalls absurd, eine Datenbank zu verwenden, um winzige Papierhandtuchkäufe aufzuzeichnen, von denen niemand Notiz nimmt. Unser Fokus liegt auf Systemen, die tatsächlich wichtig sind, z. B. die pünktliche Bezahlung von Personen, die Reaktion auf Notfälle usw. Es ist von großem Vorteil, dass die Verwendung von WITH (NOLOCK) von den Personen verstanden wird, die ein existierendes System programmieren. Wenn eine Person einen besseren Job als eine Datenbank machen kann, sollten Sie erwägen, diese Ressourcen neu zu nutzen.
WonderWorker
10

Meine 2 Cent - es ist sinnvoll zu verwenden WITH (NOLOCK), wenn Sie Berichte erstellen müssen. Zu diesem Zeitpunkt würden sich die Daten nicht wesentlich ändern und Sie möchten diese Datensätze nicht sperren.

SoftwareGeek
quelle
2
Ich denke, WITH (NoLOCK) ist besser, wenn Sie sich nicht für aktuelle Änderungen interessieren.
Abdul Saboor
9

Wenn Sie Finanztransaktionen abwickeln, werden Sie diese niemals verwenden wollen nolock. nolockwird am besten verwendet, um aus großen Tabellen mit vielen Aktualisierungen auszuwählen, und es ist Ihnen egal, ob der Datensatz, den Sie erhalten, möglicherweise veraltet ist.

Finanzdatensätze (und fast alle anderen Datensätze in den meisten Anwendungen) nolockwürden Chaos anrichten, da Sie möglicherweise Daten aus einem Datensatz zurücklesen könnten, in den geschrieben wurde, und nicht die richtigen Daten erhalten könnten.

Andrew Hare
quelle
5
Überraschenderweise ist dies bei der Arbeit mit Finanzdaten kein Problem. Da Zeilen nie bearbeitet und Konten am Ende des Tages abgeglichen werden, führt das Lesen von vorübergehend gefälschten Daten zu nichts.
Jonathan Allen
8

Ich habe immer einen "nächsten Stapel" für Dinge abgerufen, die zu tun sind. In diesem Fall spielt es keine Rolle, welches Element genau verwendet wird, und ich habe viele Benutzer, die dieselbe Abfrage ausführen.

Otávio Décio
quelle
1
Wir machen etwas Ähnliches, um eine Hintergrundaufgabe mit einer Warteschlange zu präsentieren. Wenn ein bestimmter Datensatz nicht mehr vorhanden ist / den Auswahlkriterien entspricht, geht er einfach zum nächsten über.
TripeHound
7

Verwenden Sie nolock, wenn Sie mit den "schmutzigen" Daten einverstanden sind. Dies bedeutet, dass nolock auch Daten lesen kann, die gerade geändert und / oder nicht festgeschrieben werden.

Es ist im Allgemeinen keine gute Idee, es in einer Umgebung mit hohen Transaktionen zu verwenden, und deshalb ist es keine Standardoption für Abfragen.

Lernen
quelle
3
Sie benötigen es nur in einer Umgebung mit hohen Transaktionen. Wenn Ihre Tische größtenteils im Leerlauf sind, würden Sie dadurch nichts gewinnen.
Jonathan Allen
7

Ich verwende mit (nolock) Hinweis insbesondere in SQLServer 2000-Datenbanken mit hoher Aktivität. Ich bin jedoch nicht sicher, ob es in SQL Server 2005 benötigt wird. Ich habe diesen Hinweis kürzlich in einem SQL Server 2000 auf Anfrage des DBA des Clients hinzugefügt, da er viele SPID-Datensatzsperren bemerkte.

Alles was ich sagen kann ist, dass die Verwendung des Hinweises uns NICHT verletzt hat und das Sperrproblem anscheinend von selbst gelöst hat. Der DBA bei diesem bestimmten Kunden bestand grundsätzlich darauf, dass wir den Hinweis verwenden.

Übrigens sind die Datenbanken, mit denen ich mich befasse, Back-Ends für medizinische Schadensysteme von Unternehmen. Wir sprechen also von Millionen von Datensätzen und mehr als 20 Tabellen in vielen Joins. Normalerweise füge ich für jede Tabelle im Join einen WITH-Hinweis (nolock) hinzu (es sei denn, es handelt sich um eine abgeleitete Tabelle. In diesem Fall können Sie diesen bestimmten Hinweis nicht verwenden.)

user52212
quelle
1
SQL Server 2005 hat eine "Zeilenversionierung" hinzugefügt, die den Bedarf an Nolocks erheblich reduzieren sollte. Wir haben kürzlich ein Upgrade durchgeführt und trainieren unsere Datenbankadministratoren nicht, um sie nicht mehr zu verwenden.
Jonathan Allen
5

Die einfachste Antwort ist eine einfache Frage: Müssen Ihre Ergebnisse wiederholbar sein? Wenn ja, ist NOLOCKS unter keinen Umständen geeignet

Wenn Sie keine Wiederholbarkeit benötigen, können Nolocks hilfreich sein, insbesondere wenn Sie nicht die Kontrolle über alle Prozesse haben, die eine Verbindung zur Zieldatenbank herstellen.

Ed Green
quelle