Lost Update (verlorenes Update) ist eine klassische Anomalie nebenläufiger Datenbankzugriffe. Eine Transaktion liest einen Wert, verändert ihn und schreibt zurück — parallel dazu macht eine zweite Transaktion dasselbe auf Basis des noch unveränderten Stands. Die Änderung der ersten geht verloren, weil die zweite vom veralteten Wert ausgegangen ist.
Das Muster: read-modify-write
Die Ursache ist der read-modify-write-Zyklus, den Martin Kleppmann in Designing Data-Intensive Applications (Kapitel 7) als Grundmuster beschreibt. Ein klassisches Beispiel:
-- Transaktion A und B laufen gleichzeitig
UPDATE konten SET saldo = saldo - 50 WHERE id = 7; -- A: liest 100, schreibt 50
UPDATE konten SET saldo = saldo - 80 WHERE id = 7; -- B: liest 100, schreibt 20
-- Erwartet: -30 (100-50-80). Tatsächlich: 20 → die 50er-Buchung fehlt
Beide Transaktionen haben den Wert 100 gelesen; die zweite überschreibt den Zwischenstand der ersten. Das erste Update ist verloren, ohne dass es eine Fehlermeldung gäbe.
Wann tritt Lost Update auf?
Lost Updates sind typisch für schwache Isolationsebenen: Unter Read Committed ohne Sperren ist jede Transaktion frei, über einen alten Stand zu schreiben. Repeatable Read und Serializable verhindern die Anomalie, wenn sie Schreibsperren oder Konflikterkennung einsetzen — bei reinen Snapshot-Verfahren wie MVCC hängt es von der Konfliktbehandlung ab: Snapshot Isolation wendet First-Commiter-Wins an und bricht die zweite Transaktion ab, wenn sie dieselbe Zeile geschrieben hat.
Abgrenzung zum Write Skew: Beim Lost Update schreiben beide Transaktionen dieselbe Zeile; beim Write Skew schreiben sie disjunkte Zeilen und verletzen gemeinsam eine Invariante. Deshalb erkennt First-Commiter-Wins das Lost Update, aber nicht den Write Skew.
Gegenmittel
- Atomare UPDATE-Statements:
saldo = saldo - 50statt Lesen-Rechnen-Schreiben im Anwendungscode — die Datenbank führt die Änderung unteilbar aus. - Explizites Sperren:
SELECT ... FOR UPDATEmit Two-Phase Locking — die zweite Transaktion wartet, bis die erste committet hat. - Optimistisches Sperren: Versionsspalte oder Compare-and-Set — der Client schickt die gelesene Version mit; stimmt sie nicht mehr, schlägt das Update fehl und der Anwendungsfall wird wiederholt.
- Automatische Erkennung: Manche Systeme (z. B. PostgreSQL bei Concurrent Updates) verwerfen die spätere Änderung und melden einen Konflikt statt sie still zu überschreiben.
Auch ACID-konforme Systeme schützen nicht automatisch davor: Die Isolationsebene muss das Lost Update aktiv unterbinden, sonst bleibt die Anomalie trotz korrekt begonnener Transaktion bestehen.
Verwandte Grundlagen: Transaktion, Read Committed, Snapshot Isolation, Deadlock.