Was ist der Unterschied zwischen nicht wiederholbarem Lesen und Phantomlesen?


153

Was ist der Unterschied zwischen nicht wiederholbarem Lesen und Phantomlesen?

Ich habe den Artikel über Isolation (Datenbanksysteme) aus Wikipedia gelesen , habe aber einige Zweifel. Was passiert im folgenden Beispiel: das nicht wiederholbare Lesen und das Phantomlesen ?

Transaktion A.
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1
AUSGABE:
1----MIKE------29019892---------5000
Transaktion B.
UPDATE USERS SET amount=amount+5000 where ID=1 AND accountno=29019892;
COMMIT;
Transaktion A.
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1

Ein weiterer Zweifel ist im obigen Beispiel, welche Isolationsstufe verwendet werden sollte. Und warum?


Antworten:


164

Aus Wikipedia (mit großartigen und detaillierten Beispielen dafür):

Ein nicht wiederholbarer Lesevorgang tritt auf, wenn im Verlauf einer Transaktion eine Zeile zweimal abgerufen wird und sich die Werte innerhalb der Zeile zwischen den Lesevorgängen unterscheiden.

und

Ein Phantom-Lesevorgang tritt auf, wenn im Verlauf einer Transaktion zwei identische Abfragen ausgeführt werden und sich die von der zweiten Abfrage zurückgegebene Sammlung von Zeilen von der ersten unterscheidet.

Einfache Beispiele:

  • Benutzer A führt dieselbe Abfrage zweimal aus.
  • Dazwischen führt Benutzer B eine Transaktion aus und schreibt fest.
  • Nicht wiederholbares Lesen: Die A-Zeile, die Benutzer A abgefragt hat, hat beim zweiten Mal einen anderen Wert.
  • Phantom lesen: Alle Zeilen in der Abfrage haben vorher und nachher den gleichen Wert, es werden jedoch unterschiedliche Zeilen ausgewählt (da B einige gelöscht oder eingefügt hat). Beispiel: select sum(x) from table;Gibt ein anderes Ergebnis zurück, auch wenn keine der betroffenen Zeilen selbst aktualisiert wurde, wenn Zeilen hinzugefügt oder gelöscht wurden.

Welche Isolationsstufe soll im obigen Beispiel verwendet werden?

Welche Isolationsstufe Sie benötigen, hängt von Ihrer Anwendung ab. Eine "bessere" Isolationsstufe (z. B. reduzierte Parallelität) ist mit hohen Kosten verbunden.

In Ihrem Beispiel wird kein Phantom gelesen, da Sie nur aus einer einzelnen Zeile auswählen (gekennzeichnet durch den Primärschlüssel). Sie können nicht wiederholbare Lesevorgänge durchführen. Wenn dies ein Problem darstellt, möchten Sie möglicherweise eine Isolationsstufe, die dies verhindert. In Oracle kann Transaktion A auch SELECT FOR UPDATE ausgeben. Dann kann Transaktion B die Zeile erst ändern, wenn A fertig ist.


6
Ich verstehe die Logik einer solchen Syntax nicht wirklich ... Ein NICHT wiederholbarer Lesevorgang tritt auf, wenn der
Lesevorgang

13
@serhio "nicht wiederholbar" bezieht sich auf die Tatsache, dass Sie einen Wert einmal lesen und x als Ergebnis erhalten und dann erneut lesen und y als Ergebnis erhalten können, sodass Sie nicht dieselben Ergebnisse aus zwei wiederholen können (nicht wiederholbar) separate Abfragen derselben Zeile, da dieser Zeilenwert zwischen den Lesevorgängen aktualisiert wurde.
BateTech

@Thilo Gibt es ein Beispiel für einen realen Anwendungsfall, bei dem wiederholbares Lesen Probleme verursachen kann und bei dem dies erforderlich ist?
user104309

Was ist, wenn die PK in einer anderen Transaktion geändert wird? Könnte dies zu einem Phantom-Lesevorgang führen? (Eine seltsame Sache in den meisten Fällen, aber nicht unmöglich.)
jpmc26

1
Beides klingt für mich gleich
sn.anurag

125

Eine einfache Art, wie ich darüber nachdenke, ist:

Sowohl nicht wiederholbare als auch Phantom-Lesevorgänge haben mit Datenänderungsvorgängen aus einer anderen Transaktion zu tun, die nach Beginn Ihrer Transaktion festgeschrieben und dann von Ihrer Transaktion gelesen wurden.

Nicht wiederholbare Lesevorgänge sind, wenn Ihre Transaktion festgeschriebene UPDATES von einer anderen Transaktion liest . Dieselbe Zeile hat jetzt andere Werte als zu Beginn Ihrer Transaktion.

Phantom-Lesevorgänge sind ähnlich, jedoch beim Lesen von festgeschriebenen INSERTS und / oder DELETES von einer anderen Transaktion. Es gibt neue Zeilen oder Zeilen, die seit Beginn der Transaktion verschwunden sind.

Dirty Reads ähneln nicht wiederholbaren und Phantom Reads, beziehen sich jedoch auf das Lesen von UNCOMMITTED-Daten und treten auf, wenn ein UPDATE, INSERT oder DELETE aus einer anderen Transaktion gelesen wird und die andere Transaktion die Daten noch NICHT festgeschrieben hat. Es werden "in Bearbeitung" -Daten gelesen, die möglicherweise nicht vollständig sind und möglicherweise nie festgeschrieben werden.


4
Dies hat mit Transaktionsisolationsstufen und Parallelität zu tun. Wenn Sie die Standardisolationsstufe verwenden, erhalten Sie keine fehlerhaften Lesevorgänge. In den meisten Fällen möchten Sie fehlerhafte Lesevorgänge vermeiden. Es gibt Isolationsstufen oder Abfragehinweise, die fehlerhafte Lesevorgänge ermöglichen. Dies ist in einigen Fällen ein akzeptabler Kompromiss, um eine höhere Parallelität zu erzielen, oder ist aufgrund eines Randfalls erforderlich, z. B. bei der Fehlerbehebung bei einer laufenden Transaktion über eine andere Verbindung. Es ist gut, dass die Idee eines schmutzigen Lesens den "Geruchstest" für Sie nicht besteht, da sie in der Regel vermieden werden sollten, aber einen Zweck haben.
BateTech

1
@PHPAvenger hier ist ein Anwendungsfall für die Isolationsstufe READ UNCOMMITTED: Es besteht immer die Möglichkeit, dass ein Deadlock zwischen einer Auswahl- und einer Aktualisierungsabfrage auftritt ( hier erläutert ). Wenn die Auswahlabfrage zu komplex ist, um einen abdeckenden Index zu erstellen, sollten Sie zur Vermeidung von Deadlocks eine Isolationsstufe READ UNCOMMITED verwenden, bei der das Risiko besteht, dass fehlerhafte Lesevorgänge auftreten. Wie oft werden Sie jedoch zurückgesetzt, um sich über diese fehlerhaften Lesevorgänge Gedanken zu machen dauerhaft sein?!
petrica.martinescu

1
@ petrica.martinescu Bei den Problemen, die durch fehlerhafte Lesevorgänge verursacht werden, geht es NICHT nur darum, ob eine Transaktion zurückgesetzt wird oder nicht. Schmutzige Lesevorgänge können sehr ungenaue Ergebnisse liefern, je nachdem, wie Daten in ausstehenden Transaktionen geändert wurden. Stellen Sie sich eine Transaktion vor, die eine Reihe mehrerer Löschvorgänge, Aktualisierungen und / oder Einfügungen ausführt. Wenn Sie die Daten in der Mitte dieser Transaktion mit "Nicht festgeschrieben lesen" lesen, sind sie unvollständig. Die Snapshot-Isolationsstufe (in SQL Server) ist eine viel bessere Alternative zum Lesen ohne Festschreiben. Ein gültiger Anwendungsfall für das Lesen der nicht festgeschriebenen Isolationsstufe in einem Produktionssystem ist IMO selten.
BateTech

2
@ DiponRoy tolle Frage. Die Sperre, die implementiert wird, wenn die RR-Isolation (Repeatable Read) verwendet wird, sollte verhindern, dass Löschvorgänge in ausgewählten Zeilen auftreten. Ich habe im Laufe der Jahre unterschiedliche Definitionen der 2 ISO-Ebenen gesehen, hauptsächlich gesagt, dass Phantom eine Änderung in den zurückgegebenen Sammlungs- / # Zeilen ist und RR dieselbe Zeile ist, die geändert wird. Ich habe gerade in der aktualisierten MS SQL-Dokumentation überprüft, dass Löschvorgänge Nicht-RR verursachen können ( docs.microsoft.com/en-us/sql/odbc/reference/develop-app/… ), sodass ich denke, dass das Löschen in Gruppen sicher ist die RR-Kategorie auch
BateTech

2
@anir yes Einfügungen und Löschungen sind in Dirty Reads enthalten. Beispiel: Starten Sie eine Transaktion, fügen Sie 2 von 100 Rechnungszeilen in Verbindung a ein, jetzt liest Verbindung b diese 2 Zeilen, bevor der trx festgeschrieben wird und bevor die anderen 98 Zeilen hinzugefügt werden, und enthält daher nicht alle Informationen für die Rechnung. Dies wäre ein schmutziger Lesevorgang mit einer Einfügung.
BateTech

28

Wie in diesem Artikel erläutert , sieht die nicht wiederholbare Leseanomalie wie folgt aus:

Geben Sie hier die Bildbeschreibung ein

  1. Alice und Bob starten zwei Datenbanktransaktionen.
  2. Bob liest den Post-Datensatz und der Titelspaltenwert ist Transaktionen.
  3. Alice ändert den Titel eines bestimmten Post-Datensatzes auf den Wert von ACID.
  4. Alice schreibt ihre Datenbanktransaktion fest.
  5. Wenn Bob den Post-Datensatz erneut liest, beobachtet er eine andere Version dieser Tabellenzeile.

In diesem Artikel über Phantom Read können Sie sehen, dass diese Anomalie wie folgt auftreten kann:

Geben Sie hier die Bildbeschreibung ein

  1. Alice und Bob starten zwei Datenbanktransaktionen.
  2. Bob's liest alle mit der Post-Zeile verknüpften post_comment-Datensätze mit dem Bezeichnerwert 1.
  3. Alice fügt einen neuen post_comment-Datensatz hinzu, der der Post-Zeile mit dem Bezeichnerwert 1 zugeordnet ist.
  4. Alice schreibt ihre Datenbanktransaktion fest.
  5. Wenn Bob die post_comment-Datensätze mit dem Spaltenwert post_id gleich 1 erneut liest, beobachtet er eine andere Version dieser Ergebnismenge.

Während der nicht wiederholbare Lesevorgang für eine einzelne Zeile gilt, handelt es sich beim Phantom-Lesevorgang um einen Bereich von Datensätzen, die bestimmte Filterkriterien für Abfragen erfüllen.


3
hervorragende Visualisierung @Vlad
Dextermini

23

Phänomene lesen

  • Dirty Reads: Lesen Sie UNCOMMITED-Daten aus einer anderen Transaktion
  • Nicht wiederholbare Lesevorgänge : Lesen Sie COMMITTED-Daten aus einerUPDATEAbfrage einer anderen Transaktion
  • Phantom liest : Lesen Sie COMMITTED-Daten aus einerINSERToder eineDELETEAbfrage aus einer anderen Transaktion

Hinweis : DELETE-Anweisungen aus einer anderen Transaktion haben in bestimmten Fällen auch eine sehr geringe Wahrscheinlichkeit, nicht wiederholbare Lesevorgänge zu verursachen. Es passiert, wenn die DELETE-Anweisung leider dieselbe Zeile entfernt, die Ihre aktuelle Transaktion abgefragt hat. Dies ist jedoch ein seltener Fall und in einer Datenbank mit Millionen von Zeilen in jeder Tabelle weitaus unwahrscheinlicher. Tabellen mit Transaktionsdaten weisen normalerweise in jeder Produktionsumgebung ein hohes Datenvolumen auf.

Wir können auch beobachten, dass UPDATES in den meisten Anwendungsfällen häufiger auftreten als das tatsächliche INSERT oder DELETES (in solchen Fällen besteht nur die Gefahr nicht wiederholbarer Lesevorgänge - Phantom-Lesevorgänge sind in diesen Fällen nicht möglich). Aus diesem Grund werden UPDATES anders behandelt als INSERT-DELETE, und die resultierende Anomalie wird auch anders benannt.

Mit der Verarbeitung von INSERT-DELETEs sind zusätzliche Verarbeitungskosten verbunden, anstatt nur die UPDATES zu verarbeiten.


Vorteile unterschiedlicher Isolationsstufen

  • READ_UNCOMMITTED verhindert nichts. Es ist die Isolationsstufe Null
  • READ_COMMITTED verhindert nur einen, dh schmutzige Lesevorgänge
  • REPEATABLE_READ verhindert zwei Anomalien: fehlerhafte Lesevorgänge und nicht wiederholbare Lesevorgänge
  • SERIALIZABLE verhindert alle drei Anomalien: Dirty Reads, Non-Repeatable Reads und Phantom Reads

Warum setzen Sie dann nicht einfach die Transaktion SERIALIZABLE jederzeit? Nun, die Antwort auf die obige Frage lautet: Die Einstellung SERIALIZABLE macht Transaktionen sehr langsam , was wir wiederum nicht wollen.

Tatsächlich beträgt der Transaktionszeitverbrauch die folgende Rate:

SERIALIZABLE > REPEATABLE_READ > READ_COMMITTED > READ_UNCOMMITTED

Die Einstellung READ_UNCOMMITTED ist also die schnellste .


Zusammenfassung

Tatsächlich müssen wir den Anwendungsfall analysieren und eine Isolationsstufe festlegen , um die Transaktionszeit zu optimieren und die meisten Anomalien zu vermeiden.

Beachten Sie, dass Datenbanken standardmäßig die Einstellung REPEATABLE_READ haben.


1
UPDATE oder DELETE können beide für nicht wiederholbare Lesevorgänge stattfinden oder es ist nur UPDATE?
Dipon Roy

1
UPDATE oder DELETE können beide für nicht wiederholbare Lesevorgänge stattfinden
Niket Patel

Tatsächlich können wir zusammenfassen, dass eine zufällige DELETE-Anweisung, die von einer anderen Transaktion in derselben Datenbank ausgeführt wird, im Durchschnitt eine sehr geringe Wahrscheinlichkeit hat, nicht wiederholbare Lesevorgänge für die aktuelle Transaktion zu verursachen. Dieselbe Löschanweisung hat jedoch eine 100% ige Chance, einen Phantom-Lesevorgang für die aktuelle Transaktion zu verursachen. Wenn ich es so sehe, ist mein Schreiben ein bisschen falsch, wenn man es Wort für Wort nimmt. Aber hey, ich habe es absichtlich so geschrieben, um dem Leser die Dinge klarer zu machen.
Subhadeep Ray

+1 für eine einfache und leicht verständliche Erklärung. Ich denke jedoch, dass die meisten Datenbanken (oracle, mysql) eine Standardisolationsstufe von Read Committed haben und Postgress wahrscheinlich die Standardeinstellung von repeatable_read verwendet
akila

7

Es gibt einen Unterschied in der Implementierung zwischen diesen beiden Arten von Isolationsstufen.
Für "nicht wiederholbares Lesen" ist eine Zeilensperrung erforderlich.
Für "Phantom Read" , ist eine Bereichsschließung erforderlich, sogar eine Tabellensperre.
Wir können diese beiden Ebenen mithilfe des Zwei-Phasen-Verriegelungsprotokolls implementieren .


Um wiederholbares Lesen oder Serialisieren zu implementieren, muss keine Zeilensperre verwendet werden.
a_horse_with_no_name

5

In einem System mit nicht wiederholbaren Lesevorgängen spiegelt das Ergebnis der zweiten Abfrage von Transaktion A die Aktualisierung in Transaktion B wider - es wird der neue Betrag angezeigt.

In einem System , das ermöglicht phantom liest, wenn Transaktion B waren einzufügen eine neue Zeile mit ID = 1, A Transaktion sieht die neue Zeile , wenn die zweite Abfrage ausgeführt wird ; dh Phantom-Lesevorgänge sind ein Sonderfall des nicht wiederholbaren Lesens.


Ich denke nicht, dass die Erklärung eines Phantomlesens richtig ist. Sie können Phantom-Lesevorgänge erhalten, auch wenn nicht festgeschriebene Daten niemals sichtbar sind. Siehe das Beispiel auf Wikipedia (verlinkt in den Kommentaren oben).
Thilo

1

Die akzeptierte Antwort zeigt vor allem, dass die sogenannte Unterscheidung zwischen den beiden tatsächlich überhaupt nicht signifikant ist.

Wenn "eine Zeile zweimal abgerufen wird und sich die Werte in der Zeile zwischen den Lesevorgängen unterscheiden", dann sind sie nicht dieselbe Zeile (nicht dasselbe Tupel in korrekter RDB-Sprache), und es ist dann per Definition auch der Fall, dass "die Sammlung von Von der zweiten Abfrage zurückgegebene Zeilen unterscheiden sich von der ersten ".

In Bezug auf die Frage "Welche Isolationsstufe sollte verwendet werden" gilt: Je wichtiger Ihre Daten für jemanden von entscheidender Bedeutung sind, desto mehr ist Serializable Ihre einzig vernünftige Option.


0

Ich denke, es gibt einen Unterschied zwischen nicht wiederholbarem Lesen und Phantomlesen.

Das nicht wiederholbare Mittel bedeutet, dass zwei Transaktionen A und B vorliegen. Wenn B die Änderung von A bemerken kann, kann dies zu einem Dirty-Read führen, sodass B die Änderung von A nach dem Festschreiben von A bemerkt.

Es gibt ein neues Problem: Wir lassen B die Änderung von A nach dem Festschreiben von A bemerken. Dies bedeutet, dass A einen Wert der Zeile ändert, die B hält. Manchmal liest B die Zeile erneut, sodass B beim ersten Mal einen neuen Wert erhält get, wir nennen es nicht wiederholbar, um das Problem zu lösen, lassen wir das B sich an etwas erinnern (weil ich noch nicht weiß, woran man sich erinnern wird), wenn B anfängt.

Lassen Sie uns über die neue Lösung nachdenken. Wir können feststellen, dass es auch ein neues Problem gibt, da wir B an etwas erinnern lassen. Was auch immer in A passiert ist, das B kann nicht beeinflusst werden, aber wenn B einige Daten in Tabelle und B einfügen möchte Überprüfen Sie die Tabelle, um sicherzustellen, dass kein Datensatz vorhanden ist. Diese Daten wurden jedoch von A eingefügt. Daher kann möglicherweise ein Fehler auftreten. Wir nennen es Phantom-Read.


0

Das nicht wiederholbare Lesen ist eine Isolationsstufe, und das Phantomlesen (Lesen des festgeschriebenen Werts durch andere Transaktionen) ist ein Konzept (Art des Lesens, z. B. Dirty Read oder Snapshot Read). Die nicht wiederholbare Leseisolationsstufe ermöglicht Phantom-Lesevorgänge, jedoch keine Dirty-Reads oder Snapshot-Reads.

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.