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?
sql-server
nolock
Andy White
quelle
quelle
Antworten:
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.
quelle
NOLOCK
mit a verwendenSELECT
, 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.Die Frage ist, was schlimmer ist:
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
NOLOCK
erforderlich wurden. Wenn Sie SQL Server 2000 oder früher nicht verwenden, sollten Sie es nicht benötigen.Weiterführende
Literatur Versionierung auf Zeilenebene
quelle
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:
quelle
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.
quelle
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.
quelle
NOLOCK
ist gleichbedeutend mitREAD UNCOMMITTED
, Microsoft sagt jedoch, dass Sie es nicht fürUPDATE
oderDELETE
Anweisungen verwenden sollten:http://msdn.microsoft.com/en-us/library/ms187373.aspx
Dieser Artikel gilt für SQL Server 2005, sodass die Unterstützung für
NOLOCK
vorhanden 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
quelle
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.
quelle
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.
quelle
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.
quelle
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.
quelle
READ UNCOMITTED
sich die Verwendung überhaupt nicht darauf aus. Es gibt einen Grund, warum es in den ANSI-Standard aufgenommen wurde.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.quelle
Wenn Sie Finanztransaktionen abwickeln, werden Sie diese niemals verwenden wollen
nolock
.nolock
wird 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)
nolock
wü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.quelle
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.
quelle
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.
quelle
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.)
quelle
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.
quelle