Ist NOLOCK immer schlecht?

34

Ich bin ein Berichtsentwickler, der meine Abfragen so effizient wie möglich gestalten möchte. Früher habe ich mit einem Datenbankadministrator zusammengearbeitet, der mir gesagt hat, dass ich - glaube ich, weil ich mich immer mit Berichten auf einem Produktionsserver befasst habe - diese NOLOCKin jeder einzelnen Abfrage verwenden soll.

Jetzt arbeite ich mit einem DBA zusammen, der NOLOCKunter allen Umständen gesperrt wurde - auch wenn ein Bericht von mir (aufgrund eines erheblichen Mangels an Indizes für einige Tabellen) die Replikation und Systemaktualisierungen stoppt. Meiner Meinung nach wäre in diesem Fall NOLOCKeine gute Sache.

Da die meisten meiner SQL-Schulungen aus verschiedenen Datenbankadministratoren mit sehr unterschiedlichen Meinungen bestanden, wollte ich dies einer Vielzahl von Datenbankadministratoren mitteilen.

DataGirl
quelle
1
Die andere Seite dieser Diskussion: dba.stackexchange.com/q/2684/2660
Nick Chammas

Antworten:

30

Wenn Ihr Bericht Aktualisierungen blockiert, die bestätigen, dass Ihr DBA richtig ist, sollten Sie auf keinen Fall verwenden NOLOCK. Allein die Tatsache , dass es gibt Konflikte ist ein klarer Hinweis darauf , dass , wenn Sie würde verwenden Dirty Reads Sie falsche Berichte bekommen würde.

Meiner Meinung nach gibt es immer bessere Alternativen als NOLOCK:

  • Sind Ihre Produktionstabellen schreibgeschützt und werden niemals geändert? Markiere die Datenbank als schreibgeschützt!
  • Tabellenscans verursachen Sperrkonflikte? Indizieren Sie die Tabellen entsprechend, die Vorteile sind vielfältig.
  • Kann nicht ändern / nicht wissen, wie man angemessen indiziert? Verwenden Sie SNAPSHOT ISOLATION .
  • Sie können die App nicht ändern, um den Schnappschuss zu verwenden? Aktivieren Sie Read Committed Snapshot !
  • Sie haben die Auswirkungen der Zeilenversionierung gemessen und haben Hinweise darauf, dass sie sich auf die Leistung auswirken? Sie können die Daten nicht indizieren? und Sie sind mit falschen Berichten in Ordnung ? Dann tun Sie sich zumindest einen Gefallen und verwenden Sie SET TRANSACTION ISOLATION LEVELkeinen Abfragetipp. Es ist später einfacher, die Isolationsstufe zu korrigieren, als jede Abfrage zu ändern.
Remus Rusanu
quelle
6
Seien Sie vorsichtig: Durch das Aktivieren von Read Committed Snapshot kann Code beschädigt werden.
AK
33

Es ist nicht immer schlecht.

Natürlich können Sie damit nicht festgeschriebene Werte lesen (die möglicherweise zurückgesetzt werden und daher niemals logisch existieren) sowie Phänomene wie das mehrmalige oder gar keine Werte lesen.

Die einzigen Isolationsstufen, die garantieren, dass solche Anomalien nicht auftreten, sind serialisierbar / Schnappschuss. Unter Repeatable Read können Werte verfehlt werden, wenn eine Zeile verschoben wird (aufgrund einer Schlüsselaktualisierung), bevor der Scan diese Zeile erreicht. Unter Read Committed können Werte zweimal gelesen werden, wenn eine Schlüsselaktualisierung bewirkt, dass eine zuvor gelesene Zeile vorwärts verschoben wird.

Es ist jedoch wahrscheinlicher, dass diese Probleme auftreten, nolockda bei dieser Isolationsstufe standardmäßig ein nach Zuordnung geordneter Scan verwendet wird, wenn geschätzt wird, dass mehr als 64 Seiten gelesen werden müssen . Neben der Kategorie von Problemen, die auftreten, wenn Zeilen aufgrund von Indexschlüsselaktualisierungen zwischen Seiten verschoben werden, sind diese Überprüfungen nach Zuordnungsreihenfolge auch anfällig für Probleme mit Seitenteilen (bei denen Zeilen übersehen werden können, wenn die neu zugewiesene Seite in der Datei früher als der Punkt ist bereits gescannt oder zweimal gelesen, wenn eine bereits gescannte Seite auf eine spätere Seite in der Datei aufgeteilt wird).

Zumindest für einfache (einzelne Tabellen-) Abfragen ist es möglich, die Verwendung dieser Scans zu unterbinden und einen nach Schlüsseln geordneten Scan zu erhalten, nolockindem einfach ein ORDER BY index_keyzu der Abfrage hinzugefügt wird , so dass die OrderedEigenschaft von IndexScanlautet true.

Wenn Ihre Berichtsanwendung jedoch keine absolut genauen Zahlen benötigt und die größere Wahrscheinlichkeit solcher Inkonsistenzen toleriert, ist dies möglicherweise akzeptabel.

Aber Sie sollten es sicherlich nicht bei allen Abfragen ablegen, in der Hoffnung, dass es sich um einen magischen "Turbo" -Knopf handelt. Neben der höheren Wahrscheinlichkeit, dass auf dieser Isolationsstufe anormale Ergebnisse oder gar keine Ergebnisse auftreten (Fehler "Scannen mit NOLOCK konnte aufgrund von Datenverschiebung nicht fortgesetzt werden"), gibt es sogar Fälle, in denen die Leistung mit nolock erheblich schlechter sein kann .

Martin Smith
quelle
3
+1 - Wir verwenden es häufig, weil unsere Produktionstabellen nie geändert werden.
JNK,
@JNK Was meinst du mit wird nie geändert?
Kuberchaun,
4
Martin, ich würde ein wenig andere Worte vorschlagen: "Unter read werden festgeschriebene Werte sowohl verfehlt als auch mehrmals gelesen". In einigen exotischen Fällen kann eine Zeile mehr als zweimal abgerufen werden.
AK
@ StarShip3000 Die Daten, die wir für die Produktion bereitstellen, sind für die Endbenutzer grundsätzlich schreibgeschützt, sodass die meisten ihrer Ansichten NOLOCK-Hinweise enthalten
JNK
11

Dulden Ihre Kunden inkonsistente Ergebnisse in Berichten? Wenn die Antwort nein lautet, sollten Sie NOLOCK nicht verwenden - bei gleichzeitiger Verwendung können falsche Ergebnisse auftreten. Ich habe hier , hier und hier einige Beispiele geschrieben . Diese Beispiele zeigen inkonsistente Ausgaben unter READ COMMITTED und REPEATABLE READ, aber Sie können sie optimieren und auch mit NOLOCK falsche Ergebnisse erzielen.

AK
quelle
Die meisten von mir erstellten Berichte werden nicht mit aktuellen Daten ausgeführt. Die meisten Kundenberichte beziehen sich auf die Daten von gestern. Würde sich Ihre Antwort ändern, wenn dies der Fall wäre?
DataGirl
8

Die meisten von mir erstellten Berichte werden nicht mit aktuellen Daten ausgeführt. Die meisten Kundenberichte beziehen sich auf die Daten von gestern. Würde sich Ihre Antwort ändern, wenn dies der Fall wäre?

Wenn dies der Fall ist, haben Sie eine weitere Möglichkeit:
Anstatt Ihre Abfragen in der Produktionsdatenbank NOLOCKauszuführen und mit Sperren und herumzuspielen , können Sie Ihre Berichte von einer Kopie der Produktionsdatenbank ausführen.

Sie können es so einrichten, dass es jede Nacht automatisch aus einem Backup wiederhergestellt wird .
Anscheinend werden Ihre Berichte auf Servern auf Kundensites ausgeführt, daher weiß ich nicht, ob das Einrichten dieser Option für Sie eine praktikable Lösung wäre.
(aber andererseits ... sollten sie sowieso Backups haben, so dass Sie nur etwas Serverplatz benötigen, um sie wiederherzustellen)

Ich bin ein interner Entwickler, daher ist dies für mich einfacher, da ich die volle Kontrolle über die Server und Datenbanken habe.

Sie können dies zumindest für die Berichte tun, die nur Daten von gestern und älter benötigen. Möglicherweise müssen einige Berichte in der Produktionsdatenbank verbleiben, aber zumindest verlagern Sie einen Teil der Last in eine andere Datenbank (oder noch besser auf einen anderen Server).

Ich habe die gleiche Situation auch bei der Arbeit:
Wir verwenden eine solche Kopie der Produktionsdatenbank für fast alle Berichterstellungsaufgaben, aber es gibt einige Abfragen, für die die heutigen Daten erforderlich sind.

Christian Specht
quelle
Ich mag Ihre Antwort und es würde funktionieren - wenn ich die volle Kontrolle hätte - was ich nicht tat. Oft habe ich nicht die volle Kontrolle und kann keine Indizes erstellen. Ich habe Glück, wenn ich Ausführungspläne ausführen / anzeigen kann.
DataGirl