Ist der NOLOCK (SQL Server-Hinweis) eine schlechte Praxis?


125

Ich beschäftige mich mit der Erstellung von Websites und Anwendungen, die nicht geschäftskritisch sind -> z. Bankensoftware, Raumfahrt, Intensivpflege-Überwachungsanwendung usw. Sie haben die Idee.

Ist es angesichts dieses massiven Haftungsausschlusses schlecht, den NOLOCK-Hinweis in einer SQL-Anweisung zu verwenden? Vor einigen Jahren wurde von einem anderen SQL-Administrator vorgeschlagen, NOLOCK zu verwenden, wenn ich mit einem "Dirty Read" zufrieden bin, der mir ein bisschen mehr Leistung aus meinem System bringt, da jeder Lesevorgang das nicht sperrt Tabelle / Zeile / was auch immer.

Mir wurde auch gesagt, dass es eine großartige Lösung ist, wenn ich Deadlocks habe. Also folgte ich diesem Gedanken einige Jahre lang, bis mir ein SQL-Guru mit einem zufälligen Code half und alle NOLOCKS in meinem SQL-Code bemerkte. Ich wurde höflich gescholten und er versuchte es mir zu erklären (warum es keine gute Sache ist) und ich ging irgendwie verloren. Ich hatte das Gefühl, dass der Kern seiner Erklärung darin bestand, dass es sich um eine Pflasterlösung für ein ernsthafteres Problem handelt. Besonders, wenn Sie in einer Sackgasse stecken. Beheben Sie daher die Wurzel des Problems.

Ich habe kürzlich ein bisschen gegoogelt und bin auf diesen Beitrag gestoßen .

Kann mich ein SQL-DB-Guru Sensei bitte aufklären?


Ich verstehe es nicht, Sam, du sagst, benutze die Snapshot-Isolation, wenn es sich um eine stark gelesene Website handelt. Aber dann sagst du, SO hat das getan, und es ist schlecht? oder nur ihre Verwendung von NOLOCK?
Pure.Krome

Antworten:


67

Mit dem NOLOCK-Hinweis lautet die Transaktionsisolationsstufe für die SELECTAnweisung READ UNCOMMITTED. Dies bedeutet, dass die Abfrage möglicherweise fehlerhafte und inkonsistente Daten enthält.

Dies ist in der Regel keine gute Idee. Selbst wenn dieses fehlerhafte Leseverhalten für Ihre geschäftskritische webbasierte Anwendung in Ordnung ist, kann ein NOLOCK-Scan einen 601-Fehler verursachen, der die Abfrage aufgrund von Datenverschiebungen aufgrund fehlenden Sperrschutzes beendet.

Ich empfehle zu lesen, wann die Snapshot-Isolierung hilft und wann es weh tut - der MSDN empfiehlt unter den meisten Umständen die Verwendung von READ COMMITTED SNAPSHOT anstelle von SNAPSHOT.


1
Rex, bitte zögern Sie nicht, einen Hinweis zur Snapshot-Isolation hinzuzufügen.
Sam Saffron

2
Ja, Sam sagt Snapshot-Isolation und Sie schlagen Read Committed Snapshot vor. Ich bin so verwirrt: P (und ich muss mich noch mit den Artikeln
befassen

2
Es ist gelegentlich nützlich, aber normalerweise nicht für die Produktion. Ich verwende es häufig, um eine Stichprobe von Daten zum Testen herauszuholen oder um Berichte zu erstellen, bei denen es mir hauptsächlich um grobe Größenordnungen geht, bei denen ein schmutziger Lesevorgang keine Rolle spielt.
TimothyAWiseman

NOLOCK == Es ist mir egal, ob festgeschriebene Zeilen übersehen werden, nicht festgeschriebene Zeilen enthalten sind, in seltenen Fällen dieselbe Zeile mehr als einmal zurückgegeben wird und in sehr seltenen Fällen Zeilen zurückgegeben werden, die nicht meiner Abfrage entsprechen. (Siehe blogs.msdn.com/b/sqlcat/archive/2007/02/01/… , gefunden von einem anderen SO q'n zu diesem Thema)
Andrew Hill

106

Vor Beginn der Arbeit auf Stack - Überlauf, ich war gegen NOLOCKauf dem Prinzip , dass Sie möglicherweise eine ausführen könnte SELECTmit NOLOCKund die Ergebnisse mit Daten zurück , die veraltet oder inkonsistent geführt werden. Ein zu berücksichtigender Faktor ist, wie viele Datensätze gleichzeitig eingefügt / aktualisiert werden können, wenn ein anderer Prozess Daten aus derselben Tabelle auswählt. Wenn dies häufig vorkommt, besteht eine hohe Wahrscheinlichkeit von Deadlocks, es sei denn, Sie verwenden einen Datenbankmodus wie z READ COMMITED SNAPSHOT.

Seitdem habe ich meine Sichtweise auf die Verwendung von geändert, NOLOCKnachdem ich gesehen habe, wie dies die SELECTLeistung verbessern und Deadlocks auf einem massiv geladenen SQL Server beseitigen kann. Es gibt Zeiten, in denen es Ihnen möglicherweise egal ist, dass Ihre Daten nicht zu 100% festgeschrieben sind und Sie Ergebnisse schnell zurückerhalten müssen, auch wenn sie möglicherweise veraltet sind.

Stellen Sie sich eine Frage, wenn Sie daran denken, Folgendes zu verwenden NOLOCK:

Enthält meine Abfrage eine Tabelle mit einer hohen Anzahl von INSERT/ UPDATEBefehlen, und ist es mir wichtig, ob in den von einer Abfrage zurückgegebenen Daten diese Änderungen zu einem bestimmten Zeitpunkt fehlen?

Wenn die Antwort Nein lautet, können Sie NOLOCKdie Leistung verbessern.


Ich habe gerade eine schnelle Suche nach dem NOLOCKSchlüsselwort in der Codebasis für Stack Overflow durchgeführt und 138 Instanzen gefunden, sodass wir es an einigen Stellen verwenden.


7
IMO, das ist ein bisschen simpel. Deadlocks können mithilfe von Abdeckungsindizes entfernt werden, wodurch der Clustered-Index entlastet wird.
Mitch Wheat

8
Ich möchte die Bedeutung einer guten Indexabdeckung nicht mindern. Es gibt Zeiten, in denen Abfragen mit NOLOCK zusätzlich zu den durch Indizes für Tabellen mit einer hohen Anzahl von Einfügungen / Aktualisierungen erzielten Gewinnen zusätzliche Leistung bringen können. Die Abfragegeschwindigkeit beim Stapelüberlauf ist selbst auf Kosten ungenauer oder fehlender Daten von größter Bedeutung.
Geoff Dalgas

9
Anscheinend kann man doppelte Zeilen mit bekommen NOLOCK. Das heißt, ich muss Ihre Antwort ablehnen. Es tut uns leid.
ErikE

1
@MitchWheat A SELECT, das nur aus einem Abdeckungsindex liest, kann einen Deadlock verursachen. SPID 1) Starten Sie a SELECTvom Deckungsindex. SPID 2) Starten Sie eine UPDATEder Tabellen. Update aktualisiert dann den Deckungsindex. UPDATEerreicht einen durch den SELECTgesperrten Indexbereich und wird blockiert. SPID 1) sucht immer noch durch den Deckungsindex, findet einen durch den UPDATEgesperrten Bereich und wird blockiert. DEADLOCK . Nichts kann diesen Deadlock lösen (außer SQL Server-Fehler 1205 abzufangen und automatisch zu versuchen oder zu verwenden NOLOCK)
Ian Boyd

2
Ich denke, das Wichtigste an dieser Antwort ist, dass sie für das vorliegende Problem angemessen war . Abhängig von Ihrer Anwendung ist das Risiko veralteter / nicht festgeschriebener / doppelter / fehlender Daten möglicherweise nicht den Kompromiss wert.
Ganzheitlicher Entwickler

20

Wenn Sie sich nicht für schmutzige Lesevorgänge interessieren (dh in einer Situation mit überwiegend LESEN), NOLOCKist dies in Ordnung.

ABER beachten Sie, dass die meisten Sperrprobleme darauf zurückzuführen sind, dass nicht die 'richtigen' Indizes für Ihre Abfrage-Workload vorhanden sind (vorausgesetzt, die Hardware ist der Aufgabe gewachsen).

Und die Erklärung des Gurus war richtig. Es ist normalerweise eine Pflasterlösung für ein ernsthafteres Problem.

Bearbeiten : Ich schlage definitiv nicht vor, dass NOLOCK verwendet werden sollte. Ich denke, ich hätte das offensichtlich klarstellen sollen. (Ich würde es immer nur unter extremen Umständen verwenden, unter denen ich analysiert hatte, dass es in Ordnung ist). Als Beispiel habe ich vor einiger Zeit an TSQL gearbeitet, das mit NOLOCK bestreut wurde, um zu versuchen, Sperrprobleme zu lindern. Ich habe sie alle entfernt, die richtigen Indizes implementiert und ALLE Deadlocks sind verschwunden.


3
Hmm .. ich verstehe es immer noch nicht. Also ist es in Ordnung, aber es ist auch eine schlechte Form. Ist es das, was du sagst?
Pure.Krome

Unter der Annahme, dass Sie sich NIEMALS für schmutzige Lesungen interessieren, wird es nicht schaden. ABER es ist normalerweise ein Fall der Behandlung des Symptoms und nicht der Ursache ...
Mitch Wheat

2
Nun, ich glaube nicht, dass das faire Rexem nur herabgestimmt wurde. Ich denke, Sie haben die willkürlichen Fehler, die bei der Verwendung von Nolock auftreten, nicht angesprochen. Es ist nicht in Ordnung, ab und zu eine leere Fehlerseite auf Ihrer Website zu erhalten. Es ist eine wirklich schlechte Form. Ich mag die Behauptung nicht, dass "wenn Sie sich nicht für schmutzige Lesungen interessieren, ist es in Ordnung" ... es ist nicht in Ordnung, auch wenn Sie sich nicht für schmutzige Lesungen interessieren
Sam Saffron

Die leere Seite, die Sie erhalten, wenn eine Abfrage eine Ausnahme generiert, für die Sie keine Wiederholungslogik implementiert haben. Was passiert auf Ihren Websites, wenn die Ausführung von Abfragen mit einer Ausnahme erfolgt? Haben Sie überall eine Wiederholungslogik?
Sam Saffron

Nehmen Sie eine sehr gut optimierte Abfrage, von der Sie wissen, dass sie die richtigen Indizes erreicht. Fügen Sie dann Nolock-Hinweise hinzu und beobachten Sie, wie es schneller wird. Wenn Sie sich nicht für schmutzige Lesungen interessieren, werden Sie sich niemals mit Nolock verletzen.
Hardwareguy

13

Zweifel, es war ein "Guru", der Erfahrung mit starkem Verkehr hatte ...

Websites sind normalerweise "schmutzig", wenn die Person die vollständig geladene Seite anzeigt. Stellen Sie sich ein Formular vor, das aus der Datenbank geladen und dann die bearbeiteten Daten gespeichert wird. Es ist idiotisch, wie die Leute darüber reden, dass schmutzige Lesungen so ein Nein Nein sind.

Wenn Sie jedoch mehrere Ebenen auf Ihrer Auswahl haben, kann dies zu einer gefährlichen Redundanz führen. Wenn Sie mit Geld- oder Statusszenarien zu tun haben, benötigen Sie nicht nur Lese- / Schreibvorgänge für Transaktionsdaten, sondern auch eine geeignete Parallelitätslösung (etwas, mit dem sich die meisten "Gurus" nicht befassen).

Auf der anderen Seite, wenn Sie eine erweiterte Produktsuche für eine Website haben (dh etwas, das wahrscheinlich nicht zwischengespeichert wird und ein wenig intensiv ist) und Sie jemals eine Website mit mehr als ein paar gleichzeitigen Benutzern erstellt haben (phänomenal wie viele "Experten" haben es nicht), es ist lächerlich, jeden anderen Prozess dahinter mit dem Flaschenhals zu füllen.

Wissen Sie, was es bedeutet, und verwenden Sie es gegebenenfalls. Ihre Datenbank wird heutzutage fast immer Ihr Hauptflaschenhals sein, und wenn Sie mit NOLOCK klug umgehen, können Sie Tausende an Infrastruktur sparen.

EDIT: Es sind nicht nur Deadlocks, bei denen es hilft, sondern auch, wie viel Sie alle anderen warten lassen, bis Sie fertig sind, oder umgekehrt.

Verwenden Sie NOLOCK Hint in EF4?


10

Keine der Antworten ist falsch, aber vielleicht etwas verwirrend.

  • Wenn Sie einzelne Werte / Zeilen abfragen, ist es immer eine schlechte Praxis, NOLOCK zu verwenden - Sie möchten wahrscheinlich nie falsche Informationen anzeigen oder sogar Maßnahmen für falsche Daten ergreifen.
  • Bei der Anzeige grober statistischer Informationen kann NOLOCK sehr nützlich sein. Nehmen Sie SO als Beispiel: Es wäre Unsinn, Sperren zu verwenden, um die genaue Anzahl der Ansichten einer Frage oder die genaue Anzahl der Fragen für ein Tag zu lesen . Es interessiert niemanden, ob Sie 3360 Fragen, die jetzt mit "sql-server" gekennzeichnet sind, falsch angeben, und aufgrund eines Transaktions-Rollbacks 3359 Fragen eine Sekunde später.

Ich stimme Ihrem ersten Punkt überhaupt nicht zu. Wenn Sie einzelne Werte / Zeilen abfragen und eine eindeutige ID für diese Zeile angeben und wissen, dass kein anderer Prozess darauf zugreifen wird, ist die Verwendung von nolock durchaus akzeptabel und reduziert das Blockieren in einer gleichzeitigen Anwendung.
Tuseau

1
Nein, ist es nicht. Die Zeile kann sich aus anderen Gründen ändern, z. B. durch Einfügen einer weiteren Zeile wird die Seite geteilt. Die richtige Indizierung, Read Committed Snapshot und Snapshot Isolation sind fast immer bessere Ideen.
Mark Sowul

1
@tuseau Wenn Sie "wissen", dass kein anderer Prozess auf die Zeile zugreifen wird, blockiert der Vorgang des Sperrens nichts und kostet Sie (praktisch) nichts.
Andrew Hill

2

Als professioneller Entwickler würde ich sagen, dass es darauf ankommt. Aber ich folge definitiv den Ratschlägen von GATS und OMG Ponies. Wissen, was Sie tun, wissen, wann es hilft und wann es weh tut und

Lesen Sie Hinweise und andere schlechte Ideen

Was könnte Sie dazu bringen, den SQL Server besser zu verstehen? Ich folge im Allgemeinen der Regel, dass SQL-Hinweise BÖSE sind, aber leider verwende ich sie ab und zu, wenn ich es satt habe, SQL Server zu zwingen, Dinge zu tun ... Aber dies sind seltene Fälle.

Luke


2

Als der App-Support Ad-Hock-Anfragen vom Produktionsserver mithilfe von SSMS beantworten wollte (die nicht über die Berichterstellung berücksichtigt wurden), bat ich um die Verwendung von Nolock. Auf diese Weise wird das Hauptgeschäft nicht beeinflusst.


2

Ich stimme einigen Kommentaren zum NOLOCK-Hinweis zu und insbesondere denen, die sagen "benutze es, wenn es angebracht ist". Wenn die Anwendung schlecht geschrieben ist und eine unangemessene Parallelität verwendet, kann dies zu einer Eskalation der Sperre führen. Hochtransaktionstabellen werden aufgrund ihrer Beschaffenheit auch ständig gesperrt. Eine gute Indexabdeckung hilft nicht beim Abrufen der Daten, aber wenn Sie ISOLATION LEVEL auf READ UNCOMMITTED setzen, ist dies der Fall. Ich glaube auch, dass die Verwendung des NOLOCK-Hinweises in vielen Fällen sicher ist, wenn die Art der Änderungen vorhersehbar ist. Beispiel: In der Fertigung, wenn Jobs mit Reisenden unterschiedliche Prozesse mit vielen Einfügungen von Messungen durchlaufen, können Sie die Abfrage für den fertigen Job mit dem NOLOCK-Hinweis sicher ausführen und auf diese Weise Kollisionen mit anderen Sitzungen vermeiden, die PROMOTED- oder EXCLUSIVE-Sperren auf den Tisch setzen /Seite. Die Daten, auf die Sie in diesem Fall zugreifen, sind statisch, befinden sich jedoch möglicherweise in einer sehr transaktionalen Tabelle mit Hunderten von Millionen Datensätzen und Tausenden von Aktualisierungen / Einfügungen pro Minute. Prost


2

Ich glaube, dass es praktisch nie richtig ist, Nolock zu verwenden.

Wenn Sie eine einzelne Zeile lesen, bedeutet der richtige Index, dass Sie NOLOCK nicht benötigen, da einzelne Zeilenaktionen schnell abgeschlossen werden.

Wenn Sie viele Zeilen für etwas anderes als die temporäre Anzeige lesen und daran interessiert sind, das Ergebnis zu wiederholen oder durch die erzeugte Zahl zu verteidigen, ist NOLOCK nicht geeignet.

NOLOCK ist ein Ersatz-Tag für "Es ist mir egal, ob diese Antwort doppelte Zeilen, gelöschte Zeilen oder Zeilen enthält, die aufgrund eines Rollbacks zunächst nie eingefügt wurden."

Fehler, die unter NOLOCK möglich sind:

  • Übereinstimmende Zeilen werden überhaupt nicht zurückgegeben.
  • Einzelne Zeilen werden mehrmals zurückgegeben (einschließlich mehrerer Instanzen desselben Primärschlüssels)
  • Nicht übereinstimmende Zeilen werden zurückgegeben.

Jede Aktion, die dazu führen kann, dass eine Seite geteilt wird, während die noLock-Auswahl ausgeführt wird, kann dazu führen, dass diese Dinge auftreten. Fast jede Aktion (auch ein Löschen) kann zu einem Seitensplit führen.

Deshalb: Wenn Sie "wissen", dass die Zeile während der Ausführung nicht geändert wird, verwenden Sie nolock nicht, da ein Index ein effizientes Abrufen ermöglicht.

Wenn Sie den Verdacht haben, dass sich die Zeile ändern kann, während die Abfrage ausgeführt wird, und Sie Wert auf Genauigkeit legen, verwenden Sie nolock nicht.

Wenn Sie NOLOCK aufgrund von Deadlocks in Betracht ziehen, überprüfen Sie die Abfrageplanstruktur auf unerwartete Tabellenscans, verfolgen Sie die Deadlocks und stellen Sie fest, warum sie auftreten. NOLOCK um Schreibvorgänge kann bedeuten, dass Abfragen, die zuvor blockiert waren, möglicherweise beide die falsche Antwort schreiben.


2

Die besseren Lösungen sind, wenn möglich:

  • Replizieren Sie Ihre Daten (mithilfe der Protokollreplikation) in eine Berichtsdatenbank.
  • Verwenden Sie SAN-Snapshots und stellen Sie eine konsistente Version der Datenbank bereit
  • Verwenden Sie eine Datenbank mit einer besseren grundlegenden Transaktionsisolationsstufe

Die SNAPSHOT-Transaktionsisolationsstufe wurde erstellt, weil MS Verkäufe an Oracle verlor. Oracle verwendet Rückgängig- / Wiederherstellungsprotokolle, um dieses Problem zu vermeiden. Postgres verwendet MVCC. In Zukunft wird Heckaton von MS MVCC verwenden, aber das ist noch Jahre von der Produktionsreife entfernt.


Es gibt einen Tippfehler oben. Ich möchte sagen "besserer grundlegender Transaktionsisolationsmechanismus".
pwy

1
Die SNAPSHOT-Transaktionsisolationsstufe ist die Erfindung von MS. Grundsätzlich werden die Daten in einer temporären Tabelle in TEMPDB abgelegt. Diese Datenbank wird von allen DBs auf der Box gemeinsam genutzt. Wenn möglich, sollten Sie SSDs für TEMPDB verwenden. Das ist wahrscheinlich weniger Aufwand als die anderen Optionen.
pwy

1

NOLOCK wird oft als magische Methode genutzt, um das Lesen von Datenbanken zu beschleunigen, aber ich versuche, es möglichst nicht zu verwenden.

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

Ein Fehler oder eine Ergebnismenge kann leer sein, Zeilen fehlen oder dieselbe Zeile mehrmals anzeigen.

Dies liegt daran, dass andere Transaktionen Daten gleichzeitig mit dem Lesen verschieben.

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.


-2

In der Praxis, in der Sie auf bereits geschriebene Systeme stoßen und Indizes zu Tabellen hinzufügen und dann das Laden von Daten einer 14-Gigabyte-Datentabelle drastisch verlangsamen, müssen Sie manchmal WITH NOLOCK für Ihre Berichte und die Verarbeitung zum Monatsende verwenden, damit die Gesamtfunktionen (Summe) funktionieren , zählen usw.) Sperren Sie keine Zeilen, Seiten oder Tabellen und beeinträchtigen Sie nicht die Gesamtleistung. Einfach zu sagen, in einem neuen System niemals WITH NOLOCK verwenden und Indizes verwenden - aber das Hinzufügen von Indizes führt zu einer erheblichen Herabstufung des Datenladens. Wenn mir dann gesagt wird, ändern Sie die Codebasis, um Indizes zu löschen, und laden Sie dann die Indizes in großen Mengen neu ist alles schön und gut, wenn Sie ein neues System entwickeln. Aber nicht, wenn Sie bereits ein System installiert haben.


1
Was sagst du
Max Alexander Hanna
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.