Back

Datenbank-Transaktionen verstehen

Datenbank-Transaktionen verstehen

Wenn ein Benutzer auf Ihrer Plattform eine Bestellung aufgibt, passieren mehrere Dinge gleichzeitig: Der Lagerbestand wird reduziert, ein Zahlungsdatensatz wird erstellt und ein Bestelleintrag wird gespeichert. Wenn der Server mittendrin abstürzt, könnte es passieren, dass ein Kunde belastet wurde, aber keine Bestellung existiert. Datenbank-Transaktionen existieren genau dafür, um diese Art von teilweisen Ausfällen zu verhindern.

Dieser Artikel behandelt, was Datenbank-Transaktionen sind, wie ACID-Eigenschaften Zuverlässigkeit gewährleisten, wie Transaktions-Isolationsstufen den gleichzeitigen Zugriff steuern und wie moderne Datenbanken MVCC einsetzen, um all dies effizient zu realisieren.

Wichtigste Erkenntnisse

  • Eine Datenbank-Transaktion gruppiert mehrere Operationen zu einer einzigen Arbeitseinheit — entweder alle sind erfolgreich oder alle werden zurückgerollt.
  • ACID-Eigenschaften (Atomicity, Consistency, Isolation, Durability) definieren die Zuverlässigkeitsgarantien, die Transaktionen bieten.
  • SQL definiert vier Isolationsstufen, aber das tatsächliche Verhalten variiert erheblich zwischen Datenbank-Engines wie PostgreSQL, MySQL und SQLite.
  • MVCC ermöglicht es modernen Datenbanken, gleichzeitige Lese- und Schreibvorgänge effizient zu handhaben, indem mehrere Zeilenversionen verwaltet werden, anstatt sich auf umfangreiches Locking zu verlassen.

Was ist eine Datenbank-Transaktion?

Eine Datenbank-Transaktion ist eine Sequenz von Operationen, die als einzelne Arbeitseinheit behandelt wird. Entweder sind alle Operationen erfolgreich und die Änderungen werden committed, oder etwas schlägt fehl und alles wird auf den vorherigen Zustand zurückgerollt.

In SQL sieht eine grundlegende Transaktion so aus:

BEGIN;

UPDATE accounts SET balance = balance - 500 WHERE id = 1;
UPDATE accounts SET balance = balance + 500 WHERE id = 2;

COMMIT;

Wenn zwischen BEGIN und COMMIT etwas fehlschlägt, stellt ein ROLLBACK die Datenbank auf ihren Zustand vor Beginn der Transaktion wieder her. Die meisten Datenbanken unterstützen auch SAVEPOINT für partielle Rollbacks innerhalb einer Transaktion.

ACID-Eigenschaften: Was sie tatsächlich bedeuten

ACID ist die Menge von Garantien, die Transaktionen zuverlässig machen:

  • Atomicity (Atomarität) — Alle Schritte sind erfolgreich, oder keiner. Keine partiellen Updates.
  • Consistency (Konsistenz) — Die Datenbank wechselt von einem gültigen Zustand in einen anderen. Constraints und Regeln werden durchgesetzt.
  • Isolation (Isolierung) — Gleichzeitige Transaktionen beeinflussen sich nicht gegenseitig.
  • Durability (Dauerhaftigkeit) — Einmal committed, überleben Änderungen Abstürze. Dies wird typischerweise über Write-Ahead Logging (WAL) implementiert.

ACID-Konformität hat einen Performance-Preis. Einige Systeme erlauben es Ihnen, strikte Garantien gegen Geschwindigkeit einzutauschen, weshalb das Verständnis dieser Eigenschaften beim Design Ihrer Datenschicht wichtig ist.

Transaktions-Isolationsstufen erklärt

Isolation ist die nuancierteste der vier ACID-Eigenschaften. SQL definiert vier Standard-Transaktions-Isolationsstufen, die jeweils unterschiedliche Trade-offs zwischen Konsistenz und Parallelität ermöglichen:

IsolationsstufeDirty ReadsNon-Repeatable ReadsPhantom Reads
READ UNCOMMITTEDMöglichMöglichMöglich
READ COMMITTEDVerhindertMöglichMöglich
REPEATABLE READVerhindertVerhindertMöglich
SERIALIZABLEVerhindertVerhindertVerhindert

Wichtig: Das tatsächliche Verhalten variiert je nach Datenbank-Engine.

  • PostgreSQL implementiert READ UNCOMMITTED nicht — es wird stillschweigend auf READ COMMITTED hochgestuft. Der Standard ist READ COMMITTED, wie in der offiziellen Dokumentation zu Isolationsstufen dokumentiert.
  • MySQL (InnoDB) verwendet standardmäßig REPEATABLE READ. Es nutzt in bestimmten Fällen Gap Locks, um Phantom Reads zu reduzieren, aber das Verhalten hängt von der Isolationsstufe und dem Query-Muster ab, wie in der InnoDB-Isolationsdokumentation beschrieben.
  • SQLite verwendet ein Single-Writer-Modell, was bedeutet, dass nur eine Schreib-Transaktion gleichzeitig laufen kann. Es unterstützt DEFERRED, IMMEDIATE und EXCLUSIVE Transaktionsmodi anstelle der Standard-Isolationsstufen, wie in der SQLite-Transaktionsdokumentation dargelegt.

Gehen Sie nicht von identischem Verhalten über Datenbanken hinweg aus. Prüfen Sie immer die Dokumentation für Ihre spezifische Engine.

Wie MVCC Isolation praktikabel macht

Die meisten modernen relationalen Datenbanken — einschließlich PostgreSQL und MySQL (InnoDB) — implementieren Isolation durch Multi-Version Concurrency Control (MVCC) anstelle von einfachem Locking.

Mit MVCC sehen Abfragen einen konsistenten Snapshot der Daten, aber ob dieser Snapshot pro Statement oder pro Transaktion erstellt wird, hängt von der Isolationsstufe und der Datenbank-Engine ab. Schreibvorgänge erstellen neue Versionen von Zeilen, anstatt sie zu überschreiben. Lesevorgänge blockieren keine Schreibvorgänge, und Schreibvorgänge blockieren keine Lesevorgänge.

Deshalb kann PostgreSQL leseintensive Workloads bedienen, ohne dass Leser ständig auf Locks warten. Der Trade-off ist, dass sich alte Zeilenversionen ansammeln und aufgeräumt werden müssen — in PostgreSQL wird dies durch den VACUUM-Prozess erledigt.

MVCC ist das, was REPEATABLE READ und Snapshot-Isolation in großem Maßstab praktikabel macht.

Transaktionen in verschiedenen Systemen

Nicht alle Datenbanken handhaben Transaktionen auf die gleiche Weise:

  • MySQL (InnoDB) unterstützt vollständige ACID-Transaktionen. Die ältere MyISAM-Engine tut dies nicht.
  • PostgreSQL hat robustes MVCC und unterstützt SERIALIZABLE-Isolation mit echten Serialisierbarkeitsgarantien.
  • SQLite ist vollständig ACID-konform, serialisiert aber alle Schreibvorgänge, was es für Workloads mit hoher Schreibkonkurrenz ungeeignet macht.
  • MongoDB hat Multi-Dokument-Transaktionen in Version 4.0 hinzugefügt, aber diese haben mehr Overhead als in traditionellen relationalen Datenbanken und sollten selektiv eingesetzt werden.

Praktische Richtlinien für die Verwendung von Transaktionen

  • Halten Sie Transaktionen kurz. Langlebige Transaktionen halten Locks oder behalten alte MVCC-Snapshots bei, was die Performance verschlechtert.
  • Wrappen Sie schreibgeschützte Abfragen nicht unnötig in Transaktionen — besonders in APIs mit hohem Traffic.
  • Behandeln Sie Fehler explizit. Stellen Sie immer sicher, dass ein ROLLBACK bei Fehlern erfolgt, egal ob Sie rohes SQL schreiben oder ein ORM verwenden.
  • Wählen Sie Ihre Isolationsstufe bewusst. READ COMMITTED ist ein vernünftiger Standard für die meisten Webanwendungen. Verwenden Sie SERIALIZABLE nur, wenn Korrektheit es erfordert, und testen Sie die Performance-Auswirkungen.

Fazit

Datenbank-Transaktionen geben Ihnen eine zuverlässige Möglichkeit, Daten über mehrere Operationen hinweg konsistent zu halten. Das Verständnis der ACID-Eigenschaften zeigt Ihnen, mit welchen Garantien Sie arbeiten. Die Kenntnis Ihrer Isolationsstufen und wie Ihre spezifische Datenbank MVCC implementiert, zeigt Ihnen, was diese Garantien tatsächlich kosten — und wo die Grenzfälle liegen. Dieses Wissen unterscheidet Entwickler, die Transaktionen verwenden, von Entwicklern, die sie gut verwenden.

FAQs

Verwenden Sie SERIALIZABLE, wenn Ihre Anwendung strikte Korrektheitsgarantien erfordert, wie z.B. bei Finanzberechnungen oder Lagerverwaltung, wo gleichzeitige Transaktionen keine widersprüchlichen Ergebnisse produzieren dürfen. Für die meisten Webanwendungen bietet READ COMMITTED eine gute Balance zwischen Konsistenz und Performance. Benchmarken Sie SERIALIZABLE immer in Ihrer Umgebung, da es die Parallelität reduzieren und je nach Datenbank-Engine zu Transaktions-Wiederholungen führen kann.

Die meisten Datenbanken wrappen jedes einzelne SQL-Statement automatisch in eine implizite Transaktion, sodass ein einzelnes INSERT oder UPDATE bereits atomar ist. Explizite Transaktionen werden notwendig, wenn Sie mehrere Statements zu einer Arbeitseinheit gruppieren müssen, um sicherzustellen, dass sie alle erfolgreich sind oder alle zusammen fehlschlagen. Das Wrappen eines einzelnen Statements in BEGIN und COMMIT fügt Overhead hinzu, ohne nennenswerten Nutzen.

Verwenden Sie immer try-catch oder äquivalente Error-Handling-Blöcke um Ihre Transaktionslogik. Wenn eine Operation innerhalb der Transaktion einen Fehler wirft, führen Sie ein ROLLBACK aus, um alle Änderungen rückgängig zu machen. Viele ORMs und Datenbank-Bibliotheken bieten eingebaute Transaktions-Helfer, die automatisch bei Exceptions zurückrollen. Vermeiden Sie es, Fehler stillschweigend zu unterdrücken, da dies Ihre Daten in einem inkonsistenten Zustand belassen kann.

Traditionelles Locking kann dazu führen, dass sich Leser und Schreiber häufiger gegenseitig blockieren, was die Parallelität einschränkt. MVCC vermeidet dies, indem mehrere Versionen jeder Zeile vorgehalten werden, sodass Leser auf einen konsistenten Snapshot zugreifen, ohne auf Schreiber zu warten. Der Trade-off ist, dass alte Zeilenversionen periodisch aufgeräumt werden müssen, wie PostgreSQL es mit seinem VACUUM-Prozess tut. MVCC bietet generell einen besseren Durchsatz für leseintensive Workloads.

Gain control over your UX

See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay