Non-Repeatable Read (nicht wiederholbares Lesen) ist eine Anomalie von Datenbanktransaktionen: Eine Transaktion liest dieselbe Zeile zweimal — und erhält dabei unterschiedliche Werte, weil eine andere Transaktion zwischen den beiden Lesevorgängen die Zeile geändert und committet hat.
Das Problem im Beispiel
Ein Lagerverwaltungssystem prüft den Bestand eines Artikels, um eine Bestellung freizugeben. Die erste Abfrage liefert 100 Stück. Parallel bucht eine andere Transaktion 30 Stück ab und committet. Die zweite Abfrage derselben Transaktion liefert nun 70 Stück — obwohl die Transaktion selbst nichts geändert hat. Der Kontostand in einem Finanzsystem wäre das analoge Beispiel: Zwischen zwei Abfragen verschiebt eine fremde Transaktion Geld, und die eigene Transaktion sieht zwei verschiedene Stände.
Das Problem ist nicht der geänderte Wert an sich, sondern die Inkonsistenz innerhalb einer Transaktion: Die zweite Lesung widerspricht der ersten, obwohl aus Sicht der Transaktion ein stabiler Zustand erwartet wird. Auswertungen, Validierungen und Folgeoperationen, die auf dem ersten Wert aufbauen, arbeiten dann mit veralteten oder widersprüchlichen Daten.
Einordnung nach ANSI SQL-92
Der SQL-Standard (ISO/IEC 9075:1992) definiert die Non-Repeatable Read als zweite der drei klassischen Anomalien, die die Isolationsebene einer Transaktion regeln. Berenson, Bernstein, Gray, Melton und O'Neil präzisierten die Definitionen 1995 in ihrer Kritik am Standard („A Critique of ANSI SQL Isolation Levels", SIGMOD): Für die Anomalie existieren zwei formalisierte Varianten — P2 (phenomenon-basiert) und die strengere A2, die zwei Lesevorgänge verlangt und bei der beide beteiligten Transaktionen committen. In der Standard-Matrix erlaubt Read Uncommitted die Anomalie, Read Committed ebenfalls; erst Repeatable Read verhindert sie, Serializable natürlich auch.
Abgrenzung zu den anderen Anomalien
- Beim Dirty Read liest eine Transaktion Daten, die eine andere noch nicht committet hat — die gelesenen Werte können durch ein Rollback vollständig verschwinden.
- Beim Non-Repeatable Read ändert sich der Wert einer vorhandenen Zeile (ein committetes UPDATE einer anderen Transaktion).
- Beim Phantom Read ändert sich die Menge der Zeilen (committete INSERTs oder DELETEs passen neu ins Abfrageprädikat), während die vorhandenen Werte unverändert bleiben.
Wann tritt die Anomalie auf, wann nicht?
Bei Read Uncommitted und Read Committed ist der Non-Repeatable Read möglich, sobald eine andere Transaktion die gelesene Zeile ändert und committet. In MVCC-Systemen wie PostgreSQL entsteht er dadurch, dass Read Committed pro Anweisung einen neuen Snapshot erstellt: Jede SELECT- Anweisung sieht den jeweils aktuellen Stand, die Transaktion als Ganzes aber keinen festen.
Verhindert wird die Anomalie ab der Isolationsebene Repeatable Read. Mechanisch auf zwei Wegen: Bei MVCC arbeitet die Transaktion auf einem festen Transaktions-Snapshot (wie bei der Snapshot Isolation); bei sperrbasierten Verfahren hält sie lange Lese-Sperren, bis das Two-Phase Locking sie am Transaktionsende freigibt. Die höchste Ebene Serializable verhindert die Anomalie ebenfalls, verbietet darüber hinaus aber auch Phantome.
Gegenmaßnahmen in der Praxis
- Isolationsebene anheben: Für Abfragen, deren Ergebnisse innerhalb einer Transaktion konsistent bleiben müssen, eignet sich Repeatable Read — mit dem Preis von längeren Sperren beziehungsweise Snapshot-Speicher.
- Transaktionen kurz halten: Je weniger Zeit zwischen den Lesevorgängen liegt, desto kleiner das Fenster, in dem eine fremde Änderung dazwischenfunken kann.
- Anwendungsseite absichern: Werte, auf denen Folgeentscheidungen aufbauen, unmittelbar vor der Entscheidung erneut lesen oder im selben Schritt mit einer Schreiboperation verbinden (Transaktion als atomare Einheit).
Der Non-Repeatable Read ist neben dem Lost Update und dem Write Skew eine der Anomalien, die selbst gut abgesicherte Systeme beobachten müssen, wenn sie die Isolationsebene absenken — die ACID-Eigenschaften einer Datenbank garantieren Konsistenz nur auf der Stufe, die man tatsächlich konfiguriert.
Verwandte Grundlagen: Die Isolationsebene, Dirty Read, Phantom Read, Read Committed, Repeatable Read, Serializable, Snapshot Isolation, MVCC, Deadlock.