Unterschied zwischen "Lesen festgeschrieben" und "wiederholbares Lesen"

245

Ich denke, die oben genannten Isolationsstufen sind so ähnlich. Könnte jemand bitte mit ein paar schönen Beispielen beschreiben, was der Hauptunterschied ist?

Vordergrund
quelle
3
Sie sollten die Frage erweitern und Tags für die "Isolationsstufe" hinzufügen, auf die Sie sich beziehen (Java usw.). "Isolationsstufe" ist ein etwas mehrdeutiger Begriff, und Sie fragen offensichtlich nach einer Antwort für eine bestimmte Umgebung.
Jesus

Antworten:

564

Read Commit ist eine Isolationsstufe, die garantiert, dass alle zum Zeitpunkt des Lesens festgeschriebenen gelesenen Daten gelesen werden. Es hindert den Leser lediglich daran, zwischenzeitliche, nicht festgeschriebene, "schmutzige" Lesevorgänge zu sehen. Es wird keinerlei Zusage gemacht, dass Daten nach dem Lesen geändert werden können, wenn die Transaktion den Lesevorgang erneut ausgibt und dieselben Daten findet.

Wiederholbares Lesen ist eine höhere Isolationsstufe, die zusätzlich zu den Garantien der Lese-Festschreibungsstufe auch garantiert, dass sich das Lesen von Daten nicht ändern kann. Wenn die Transaktion dieselben Daten erneut liest, werden die zuvor gelesenen Daten unverändert an Ort und Stelle gefunden und zum Lesen verfügbar.

Die nächste Isolationsstufe, serialisierbar, bietet eine noch stärkere Garantie: Zusätzlich zu allen wiederholbaren Lesegarantien wird auch garantiert, dass bei einem nachfolgenden Lesevorgang keine neuen Daten sichtbar werden.

Angenommen, Sie haben eine Tabelle T mit einer Spalte C mit einer Zeile darin. Angenommen, sie hat den Wert '1'. Und denken Sie daran, dass Sie eine einfache Aufgabe wie die folgende haben:

BEGIN TRANSACTION;
SELECT * FROM T;
WAITFOR DELAY '00:01:00'
SELECT * FROM T;
COMMIT;

Dies ist eine einfache Aufgabe, bei der zwei Lesevorgänge aus Tabelle T mit einer Verzögerung von 1 Minute ausgeführt werden.

  • Unter READ COMMITTED kann das zweite SELECT beliebige Daten zurückgeben. Eine gleichzeitige Transaktion kann den Datensatz aktualisieren, löschen und neue Datensätze einfügen. Bei der zweiten Auswahl werden immer die neuen Daten angezeigt.
  • Unter REPEATABLE READ werden beim zweiten SELECT garantiert mindestens die Zeilen angezeigt, die vom ersten SELECT unverändert zurückgegeben wurden . Neue Zeilen können durch eine gleichzeitige Transaktion in dieser einen Minute hinzugefügt werden, aber die vorhandenen Zeilen können nicht gelöscht oder geändert werden.
  • Unter SERIALIZABLE liest die zweite Auswahl garantiert genau die gleichen Zeilen wie die erste. Keine Zeile kann geändert oder gelöscht werden, noch können neue Zeilen durch eine gleichzeitige Transaktion eingefügt werden.

Wenn Sie der obigen Logik folgen, können Sie schnell erkennen, dass SERIALIZABLE-Transaktionen, obwohl sie Ihnen das Leben erleichtern, jede mögliche gleichzeitige Operation immer vollständig blockieren , da sie erfordern, dass niemand eine Zeile ändern, löschen oder einfügen kann. Die Standard-Transaktionsisolationsstufe des .Net- System.TransactionsBereichs ist serialisierbar. Dies erklärt normalerweise die daraus resultierende miserable Leistung.

Und schließlich gibt es noch die SNAPSHOT-Isolationsstufe. Die SNAPSHOT-Isolationsstufe bietet die gleichen Garantien wie die Serialisierbarkeit, erfordert jedoch nicht, dass keine gleichzeitige Transaktion die Daten ändern kann. Stattdessen zwingt es jeden Leser, seine eigene Version der Welt zu sehen (es ist ein eigener "Schnappschuss"). Dies macht es sehr einfach zu programmieren und sehr skalierbar, da es keine gleichzeitigen Updates blockiert. Dieser Vorteil ist jedoch mit einem Preis verbunden: zusätzlicher Verbrauch an Serverressourcen.

Ergänzende Lesungen:

Remus Rusanu
quelle
24
Ich denke, es gibt oben einen Fehler für REPEATABLE READ: Sie sagen, vorhandene Zeilen können nicht gelöscht oder geändert werden, aber ich denke, sie können gelöscht oder geändert werden, weil wiederholbares Lesen einfach einen "Schnappschuss" liest, nicht die tatsächlichen Daten. Aus den Dokumenten dev.mysql.com/doc/refman/5.0/en/… : "Alle konsistenten Lesevorgänge innerhalb derselben Transaktion lesen den beim ersten Lesevorgang erstellten Snapshot."
Derek Litz
2
@Derek Litz Habe ich Recht damit, dass Sie sagen: Die Daten KÖNNEN / KÖNNEN von einem Dritten geändert werden, während die Transaktion stattfindet, aber die Lesevorgänge sehen immer noch die 'alten' Originaldaten, als ob die Änderung nicht vorgenommen worden wäre Ort (der Schnappschuss).
Programster
5
@ Cornstalks. Ja, Phantom-Lesevorgänge können beim Löschen (oder Einfügen) auftreten. Ja, Phantom-Lesevorgänge können in wiederholbarer Leseisolation auftreten (nur von Einfügungen). Nein, Phantom-Lesevorgänge aus Löschvorgängen können bei wiederholbarer Leseisolation nicht auftreten. Probier es aus. Was ich sage, wird durch die von Ihnen zitierte Dokumentation nicht widerlegt.
AndyBrown
4
@ Cornstalks NP. Ich habe es nur erwähnt, weil ich mir selbst nicht 100% sicher war und tief tauchen musste, um sicher zu sein, wer Recht hatte! Und ich wollte nicht, dass zukünftige Leser irregeführt werden. Behalten Sie die Kommentare bei, wahrscheinlich am besten, wie vorgeschlagen. Ich bin sicher, dass jeder andere, der sich für diese Detailgenauigkeit interessiert, genau genug ist, um alle Kommentare zu lesen !!
AndyBrown
12
Vielen Dank, dass Sie Ihre Kommentare nicht gelöscht haben. Die Diskussion hilft, mehr Punkte zu verbinden.
Josh
68

Wiederholbares Lesen

Der Status der Datenbank wird ab dem Start der Transaktion beibehalten. Wenn Sie einen Wert in Sitzung1 abrufen, aktualisieren Sie diesen Wert in Sitzung2. Wenn Sie ihn in Sitzung1 erneut abrufen, werden dieselben Ergebnisse zurückgegeben. Lesevorgänge sind wiederholbar.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Aaron

Lesen Sie Committed

Im Kontext einer Transaktion rufen Sie immer den zuletzt festgeschriebenen Wert ab. Wenn Sie einen Wert in Sitzung1 abrufen, ihn in Sitzung2 aktualisieren und dann wieder in Sitzung1 abrufen, erhalten Sie den in Sitzung2 geänderten Wert. Es liest die letzte festgeschriebene Zeile.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Bob

Macht Sinn?

Hazel_arun
quelle
Ich habe Repeatable Read in SQL Server 2008 mit "Set Isolation Level Repetable Read" versucht. Erstellt zwei SQL-Abfragefenster. Hat aber nicht funktioniert. Warum?
Aditya Bokade
1
Warum sollte die zweite Sitzung1 Aaron noch vorlesen? Ist die Transaktion von session2 nicht abgeschlossen und festgeschrieben? Ich kenne das alt, aber vielleicht kann jemand etwas Licht ins Dunkel bringen.
Sonny Childs
9
Ich denke, das wiederholbare Lesen blockiert die zweite Sitzung bis zur ersten festgeschriebenen Sitzung. Das Beispiel ist also falsch.
Nighon
4
Im Fall von wiederholbarem Lesen wird beim Lesen der Zeile durch Sitzung 1 eine gemeinsame Sperre gesetzt, die keine exklusive Sperre (für Sitzung 2) zur Aktualisierung zulässt. Daher können die Daten nicht aktualisiert werden.
Taher
Ich denke, SQL Server und MySQL verhalten sich unterschiedlich, wenn es darum geht, gemeinsam genutzte Zeilen zwischen zwei Transaktionen zu aktualisieren
user2488286
23

Einfach die Antwort nach meinem Lesen und Verstehen auf diesen Thread und die Antwort von @ remus-rusanu basiert auf diesem einfachen Szenario:

Es gibt zwei Prozesse A und B. Prozess B liest Tabelle X Prozess A schreibt in Tabelle X Prozess B liest erneut Tabelle X.

  • ReadUncommitted : Prozess B kann nicht festgeschriebene Daten aus Prozess A lesen und es können unterschiedliche Zeilen basierend auf dem Schreiben von B angezeigt werden. Überhaupt kein Schloss
  • ReadCommitted : Prozess B kann NUR festgeschriebene Daten von Prozess A lesen und es können verschiedene Zeilen angezeigt werden, die auf dem Schreiben von COMMITTED only B basieren. könnten wir es Simple Lock nennen?
  • RepeatableRead : Prozess B liest dieselben Daten (Zeilen), unabhängig davon, was Prozess A tut. Prozess A kann jedoch andere Zeilen ändern. Zeilenpegelblock
  • Serialisable : Prozess B liest dieselben Zeilen wie zuvor und Prozess A kann die Tabelle nicht lesen oder schreiben. Block auf Tabellenebene
  • Schnappschuss : Jeder Prozess hat eine eigene Kopie und sie arbeiten daran. Jeder hat seine eigene Sichtweise
Mo Zaatar
quelle
15

Alte Frage, die bereits eine akzeptierte Antwort hat, aber ich denke gerne an diese beiden Isolationsstufen, wie sie das Sperrverhalten in SQL Server ändern. Dies könnte für diejenigen hilfreich sein, die Deadlocks wie ich debuggen.

READ COMMITTED (Standard)

Freigegebene Sperren werden in SELECT übernommen und dann freigegeben, wenn die SELECT-Anweisung abgeschlossen ist . Auf diese Weise kann das System sicherstellen, dass nicht festgeschriebene Daten nicht fehlerhaft gelesen werden. Andere Transaktionen können die zugrunde liegenden Zeilen nach Abschluss von SELECT und vor Abschluss Ihrer Transaktion noch ändern.

WIEDERHOLBAR LESEN

Freigegebene Sperren werden in SELECT übernommen und erst nach Abschluss der Transaktion freigegeben . Auf diese Weise kann das System sicherstellen, dass sich die von Ihnen gelesenen Werte während der Transaktion nicht ändern (da sie bis zum Abschluss der Transaktion gesperrt bleiben).

Chris Gillum
quelle
13

Der Versuch, diesen Zweifel mit einfachen Diagrammen zu erklären.

Festgeschrieben lesen: Hier in dieser Isolationsstufe liest Transaktion T1 den aktualisierten Wert des von Transaktion T2 festgeschriebenen X.

Lesen Sie Committed

Wiederholbares Lesen: In dieser Isolationsstufe berücksichtigt die Transaktion T1 nicht die von der Transaktion T2 festgeschriebenen Änderungen.

Geben Sie hier die Bildbeschreibung ein

vkrishna17
quelle
1

Ich denke, dieses Bild kann auch nützlich sein, es hilft mir als Referenz, wenn ich mich schnell an die Unterschiede zwischen den Isolationsstufen erinnern möchte (dank kudvenkat auf youtube)

Geben Sie hier die Bildbeschreibung ein

Ivan Pavičić
quelle
0

Bitte beachten Sie, dass sich das Wiederholbare in Wiederholbarem auf ein Tupel bezieht, jedoch nicht auf die gesamte Tabelle. In ANSC-Isolationsstufen kann es zu einer Phantom- Leseanomalie kommen. Dies bedeutet, dass eine Tabelle mit derselben where-Klausel zweimal unterschiedliche Rückgabewerte und unterschiedliche Ergebnismengen zurückgeben kann. Es ist buchstäblich nicht wiederholbar .

不辞 长 做 岭南 人
quelle
-1

Meine Beobachtung zur ursprünglich akzeptierten Lösung.

Unter RR (Standard-MySQL) - Wenn ein TX geöffnet ist und ein SELECT ausgelöst wurde, kann ein anderer TX KEINE Zeile löschen, die zur vorherigen READ-Ergebnismenge gehört, bis der vorherige TX festgeschrieben wurde (tatsächlich bleibt die Löschanweisung im neuen TX einfach hängen). Der nächste TX kann jedoch problemlos alle Zeilen aus der Tabelle löschen . Übrigens werden beim nächsten LESEN im vorherigen Text die alten Daten weiterhin angezeigt, bis sie festgeschrieben werden.

Sanjeev Dhiman
quelle
2
Möglicherweise möchten Sie es in den Kommentarbereich einfügen, damit der Antwortende benachrichtigt wird. Auf diese Weise kann er auf Ihre Beobachtungen reagieren und bei Bedarf Korrekturen vornehmen.
RBT