Vorteile von SET TRANSACTION ISOLATION LEVEL UNBEGRENZT LESEN

12

Ich benutze SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDin den meisten meiner allgemeinen SQL-Abfragen, hauptsächlich, weil dies mir beim ursprünglichen Erlernen der Sprache eingeflößt wurde.

Nach meinem Verständnis verhält sich diese Isolationsstufe genauso, WITH (NO LOCK)wie ich sie jedoch immer nur benutze SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.

  • Gibt es überhaupt eine Zeit , die ich verwenden soll WITH (NO LOCK)über SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
  • Verhindert es, SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDdass andere Benutzer aus den von mir gelesenen Tabellen ausgeschlossen werden?
  • Wenn SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDzum Stoppen von Sperren verwendet wird, ich aber nur Daten lese, wozu dient es dann? Sind es nur systemintensive Abfragen, die Sperren erzeugen würden? Lohnt es sich, sie zu verwenden, wenn Abfragen ausgeführt werden, die in etwa 5-10 Sekunden zurückkehren würden?
  • Mir wurde gesagt, SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDdass ich beim Lesen von Daten, die für Aktualisierungen verwendet werden, keine Daten verwenden soll, vermutlich, um die Aktualisierung schmutziger Daten zu vermeiden. Wäre das der einzige Grund?
  • Mit der Art der Datenbank, an der ich arbeite, gibt es eine Produktions- und Testumgebung. Wir werden sehr selten die Produktionsumgebung abfragen, aber wenn ich muss, werde ich in der Regel SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDin meiner Abfrage verwenden. Ich verstehe, dass Dirty Reads damit möglich sind. Abgesehen davon, dass Sie Daten zurückerhalten, die möglicherweise nicht in der Datenbank gespeichert werden (und daher meine Ergebnisse verwerfen), welche anderen Arten von "Dirty Reads" könnten möglich sein?

Entschuldigung für die Massenfragen.

Geld
quelle
2
Sie könnten die gleichen Daten zweimal lesen, dies ist ein weiterer Fall. Die Verwendung von RU oder NO LOCK als Standard ist eine schlechte Idee.
James Anderson
9
Ich würde nicht verwenden READ UNCOMMITTEDüberall, in genau der gleichen Art und Weise , wie ich nicht verwenden würde WITH (NOLOCK)überall (sie sind im Wesentlichen die gleiche Sache) blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere
Mark Sinkinson
1
Schauen Sie sich die SNAPSHOT-Isolationsmodelle an. Sie sind sehr viel stärker als RCU und blockieren oder verursachen auch keine Blockierung. Sie klingen wie ein gutes Standardmodell für Sie (anstatt standardmäßig RCU!).
usr

Antworten:

26

Es ist schrecklich, dass du es so gelernt hast (sorry!).

READ UNCOMMITTEDLass uns jede Zeile lesen, ja. Selbst diejenigen , die derzeit verwendet werden , in einem INSERT, UPDATE, DELETEBetrieb. Dies ist sehr nützlich, wenn Sie sich einige Daten oder unternehmenskritische SELECTAnweisungen ansehen möchten, bei denen ein Block sehr schädlich wäre.

In der Tat riskieren Sie Ihre Integrität. Es kann vorkommen, dass Sie eine Zeile gelesen haben, die gerade zum Löschen oder Ändern verwendet wird. Es kann auch vorkommen, dass Sie einen falschen Wert gelesen haben. Das mag wirklich ungewöhnlich sein, aber es kann passieren. Was meine ich damit nvarcharStellen Sie sich eine Zeile vor, die sehr breit ist (sie enthält viele Spalten mit vielen langen Spalten). In dieser Zeile wird eine Aktualisierung durchgeführt und neue Werte festgelegt. In seltenen Fällen kann es vorkommen, dass Sie nur eine halbe Zeile lesen. Eine andere Sache kann zum Beispiel passieren, wenn ein Benutzer seine Login-Werte ändert. Er ändert seine Mail + Passwort. Die Mail ist bereits festgelegt, das Passwort jedoch nicht. Auf diese Weise haben Sie einen inkonsistenten Zustand.

Ich würde vorschlagen, zu vergessen READ UNCOMMITTED. Verwenden Sie es einfach dort, wo es wirklich gebraucht wird.

Eine andere Alternative für Sie kann darin bestehen, die READ_COMMITTED_SNAPSHOTDatenbankoption zu aktivieren, die Sie READ COMMITTED SNAPSHOTaufgrund der aktivierten Zeilenversionierung in Ihrer Tempdb verwenden können. Auf diese Weise lesen Sie einfach eine andere (ältere) Version einer Zeile. Dadurch werden Ihre Abfragen nicht blockiert. Es kann jedoch vorkommen, dass Sie auch einen alten Wert lesen, aber einen konsistenten alten Wert.

Eine andere Idee kann WITH(READPAST)statt WITH(NOLOCK). Sie werden den alten Zustand der Tabelle lesen (ein bisschen wie in der SNAPSHOT ISOLATION), aber Sie werden stattdessen alle derzeit gesperrten Zeilen überspringen.

Ionic
quelle
@Ionic, vielen Dank für die Antwort! Ich bin sehr dankbar für die Hilfe dabei.
Geld
@HingeSight, es klingt wie es, aber es besteht eine sehr gute Chance, dass es meine Interpretation der Aussage war, danke für Ihre Eingabe.
Geld
1
SNAPSHOT ISOLATIONmuss zum Einschalten nicht aktiviert sein READ COMMITTED SNAPSHOT. Es muss nur die READ COMMITTED SNAPSHOTDatenbankoption aktiviert werden, damit die Zeilenversionierung anstelle der Sperrung für die Lesekonsistenz aktiviert wird und keine fehlerhaften Lesevorgänge erforderlich sind.
Dan Guzman
Ja ich meinte das @DanGuzman. Leider war die Antwort in diesem Punkt etwas unklar. Ich habe es bearbeitet. :-)
Ionic
Mit READPAST überspringen Sie gesperrte Datensätze, und Sie erhalten nicht die alten Werte. Der einzige Ort, an dem ich herausgefunden habe, dass er verwendet werden kann, ist die Warteschlangenbearbeitung
James Z
2

Wie in der akzeptierten Antwort angegeben, vergessen Sie die Verwendung der Isolationsstufe READ UNCOMMITTED (außer wenn dies wirklich erforderlich ist), da Sie das Risiko eingehen, falsche Daten zu lesen. Aber um den dritten Punkt in Ihrer Frage zu beantworten, gibt es zwei Situationen, die ich für nützlich halte:

  1. Wenn Sie SQL Server SSIS-Pakete schreiben und testen, werden die Schritte des Pakets möglicherweise in eine Transaktion eingeschlossen. Wenn Sie ein Paket testen, indem Sie es Schritt für Schritt im SSIS-Debugger ausführen, möchten Sie möglicherweise Tabellen untersuchen, während die Tabelle gesperrt ist. Mit SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED können Sie mit SQL Server Manager Studio die Tabellen untersuchen, während das Paket debuggt wird.

  2. In SQL Server Manager Studio möchten Sie möglicherweise T-SQL-Code testen, indem Sie ihn in eine Transaktion einschließen, damit Sie die Änderungen rückgängig machen können. Beispielsweise möchten Sie in einer Testdatenbank möglicherweise im Rahmen Ihres Tests den ursprünglichen Status der Daten wiederherstellen. Wenn Sie transaktionsumhüllten Code testen und gesperrte Tabellen überprüfen möchten, während die Transaktion ausgeführt wird, können Sie mit SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED die Werte in einem anderen Fenster überprüfen.

Ich akzeptiere, dass dies ziemlich unklare Verwendungen für READ UNCOMMITTED sind, aber ich fand sie in einer Testumgebung nützlich.

Ubercoder
quelle
1

In den meisten Datenbanken liegt der überwiegende Teil der Aktivitäten, auch das Einfügen, Löschen und Aktualisieren, außerhalb expliziter Transaktionen.

Sicher, READ UNCOMMITTED(Dirty Reads) können in diesen Fällen falsche Informationen liefern, aber diese Informationen waren 5 Sekunden früher korrekt.

Die Zeiten, in denen fehlerhafte Lesevorgänge zu wirklich schlechten Ergebnissen führen, sind, wenn eine Transaktion fehlschlägt und zurückgesetzt werden muss oder wenn eine Abfrage für zwei Tabellen ausgeführt wird, die normalerweise mithilfe einer expliziten Transaktion zusammen aktualisiert werden.

In einer großen, ausgelasteten Datenbank mit einem Verhältnis von Lesen zu Schreiben von 100 (oder mehr) zu 1 verlangsamt JEDE einzelne (Lese-) Abfrage, die keine fehlerhaften Lesevorgänge verwendet, das System, da sie Daten abrufen und überprüfen muss Bei Sperren UND ist es viel wahrscheinlicher, dass Transaktionen fehlschlagen (normalerweise aufgrund von Deadlocks), was schwerwiegendere Probleme mit der Datenbankintegrität verursachen kann.

Stattdessen macht die Verwendung von Dirty Reads das System VIEL schneller und zuverlässiger (teilweise aufgrund der verbesserten Leistung, die Inkonsistenzen weniger wahrscheinlich macht).

Klar, es gibt Zeiten, in denen sie nicht verwendet werden sollten. Ich mag es nicht, die Datenbank standardmäßig auf die READ UNCOMMITTEDIsolationsstufe oder sogar auf die explizite SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDAnweisung zu Beginn von SQL-Skripten und SPs einzustellen - es besteht eine zu hohe Wahrscheinlichkeit, dass ein Dirty Read ausgeführt wird, wenn dies nicht der Fall ist. Stattdessen sind die (NOLOCK)Hinweise ein viel besserer Ansatz, da sie ausdrücklich darauf hinweisen, dass der Programmierer darüber nachgedacht hat, was sie tun, und entschieden, dass Dirty Reads für diese bestimmte Tabelle in dieser bestimmten Abfrage sicher sind.

Wenn Sie eine Anwendung programmieren, um Geld von einem Bankkonto auf ein anderes zu überweisen, sollten Sie Dirty Reads nicht verwenden. Für die meisten Anwendungen ist diese Paranoia jedoch nicht erforderlich.

Simon Holzman
quelle