System Design · Modul 3: Daten speichern

Lektion 2 von 7Übung 15 Min.

Transaktionen und Isolation

Lernziele
  • das ACID-Prinzip von Transaktionen erklären
  • typische Anomalien bei gleichzeitigen Transaktionen kennen
  • Isolationsstufen und ihre Abwägungen einordnen
  • Transaktionen im Anwendungscode richtig einsetzen und Migrationen sicher durchführen

Im vorigen Modul haben Sie gesehen, wie zwei gleichzeitige Buchungen einen Kurs überbuchen können. Die Lösung lag in der Datenbank. Diese Lektion schaut genauer hin: Was garantiert eine Transaktion eigentlich, welche Fehler können trotzdem auftreten, und wie wählt man die richtige Isolationsstufe? Das klingt nach Datenbanktheorie, entscheidet aber im Alltag darüber, ob ein Onlineshop zu viel verkauft, ob Kontostände stimmen und ob Nutzer doppelte Rechnungen bekommen.

1. Was eine Transaktion garantiert

Definition 2.1
ACID
Die vier Eigenschaften klassischer Datenbanktransaktionen: Atomarität (alles oder nichts), Konsistenz (Regeln der Datenbank bleiben erfüllt), Isolation (gleichzeitige Transaktionen stören sich nicht oder nur in definiertem Umfang) und Dauerhaftigkeit (bestätigte Änderungen überstehen Abstürze).

Die Atomarität ist die bekannteste Eigenschaft: Wenn eine Bestellung angelegt, der Lagerbestand verringert und eine Zahlung vermerkt werden soll, geschieht entweder alles oder nichts. Bricht der Vorgang in der Mitte ab, rollt die Datenbank alle Änderungen zurück. Die Dauerhaftigkeit garantiert, dass eine bestätigte Transaktion auch einen Stromausfall übersteht, weil die Datenbank sie vor der Bestätigung in ein Protokoll schreibt. Die Konsistenz bedeutet, dass die definierten Regeln – eindeutige Werte, Fremdschlüssel, Prüfbedingungen – nach jeder Transaktion erfüllt sind. Die schwierigste Eigenschaft ist die Isolation.

2. Die Anomalien

Vollständige Isolation würde bedeuten, dass sich gleichzeitige Transaktionen so verhalten, als liefen sie strikt nacheinander. Das ist teuer, deshalb bieten Datenbanken abgestufte Isolationsstufen an, die bestimmte Anomalien zulassen. Man sollte sie kennen, um zu wissen, wogegen man sich schützen muss.

Tab. 2.1Typische Anomalien
AnomalieWas passiertBeispiel
Dirty ReadLesen unbestätigter Änderungen einer anderen TransaktionAnzeige eines Preises, der wieder zurückgenommen wird
Nicht wiederholbares Lesenderselbe Wert wird zweimal gelesen und ist verschiedenRechnung und Summe weichen ab
Phantomeine Abfrage liefert beim zweiten Mal neue ZeilenZählung freier Plätze ändert sich während der Buchung
Lost Updatezwei Transaktionen überschreiben sichletzter Kursplatz zweimal vergeben
Write Skewzwei Transaktionen prüfen dieselbe Bedingung und ändern verschiedene Zeilenzwei Ärzte tragen sich gleichzeitig aus dem Bereitschaftsdienst aus – keiner bleibt

Wählen Sie eine Isolationsstufe und sehen Sie, wogegen sie schützt:

ÜbersichtWelche Anomalien verhindert welche Isolationsstufe?
verhindertDirty Read
möglichNicht wiederholbares Lesen
möglichPhantom
möglichLost Update
möglichWrite Skew

Verhalten von PostgreSQL. Andere Datenbanken setzen dieselben Stufen teils anders um.

Standard in PostgreSQL. Man sieht nur bestätigte Daten, aber innerhalb einer Transaktion können sich gelesene Werte ändern.
Klick-GrafikEine Buchung als Transaktion
BEGINPlatz prüfenPlatz reservierenZahlung notierenCOMMIT
Schritt 1/5 · Beginn: Alles ab hier gehört zusammen – entweder ganz oder gar nicht.

3. Die richtige Stufe wählen

PostgreSQL nutzt standardmäßig Read Committed. Diese Stufe ist schnell und für viele Anwendungsfälle ausreichend, schützt aber nicht vor Lost Updates und Write Skew. Das ist kein Grund, alles auf Serializable umzustellen, denn die stärkste Stufe führt unter Last zu mehr Abbrüchen, die die Anwendung wiederholen muss. Der bessere Weg ist meist, die kritischen Stellen gezielt abzusichern.

Tab. 2.2Kritische Stellen gezielt absichern
MusterUmsetzungWofür
Atomare AktualisierungUPDATE … SET frei = frei - 1 WHERE id = … AND frei > 0Zähler, Bestände, Plätze
ZeilensperreSELECT … FOR UPDATE innerhalb der TransaktionLesen, prüfen, ändern derselben Zeile
Eindeutige RegelUNIQUE (mitarbeiter_id, zeitfenster)Doppelbuchungen, doppelte Zahlungen
Optimistische SperreVersionsnummer prüfen: UPDATE … WHERE version = 7Bearbeitung von Formularen durch mehrere Personen
Serializable gezieltnur für einzelne, komplexe TransaktionenWrite-Skew-Fälle
Transaktionen sind kurz, fokussiert und enthalten keine externen Aufrufe. Wer innerhalb einer Transaktion auf einen Zahlungsdienst oder ein KI-Modell wartet, hält Sperren und Verbindungen fest – und legt unter Last das ganze System lahm.

4. Transaktionen im Anwendungscode

In der Praxis entstehen die meisten Probleme nicht durch falsche Isolationsstufen, sondern durch falsch gezogene Transaktionsgrenzen. Ein häufiges Muster: Die Anwendung liest einen Wert, entscheidet im Code, schreibt dann – aber in drei getrennten Datenbankaufrufen ohne gemeinsame Transaktion. Unter Last entsteht genau das Lost Update aus dem vorigen Modul. Ebenso häufig ist das Gegenteil: eine Transaktion, die viel zu viel umfasst, etwa das Hochladen einer Datei, das Erzeugen einer Vorschau und das Versenden einer E-Mail. Sie blockiert Verbindungen und Sperren über Sekunden.

Die Regel lautet: In die Transaktion gehört genau das, was gemeinsam gelingen oder scheitern muss, und nichts, was lange dauert oder außerhalb der Datenbank passiert. Für Seiteneffekte wie E-Mails oder Aufrufe externer Dienste gibt es das bereits erwähnte Outbox-Muster: Die Transaktion speichert zusätzlich einen Auftrag in einer Tabelle, und ein Hintergrundprozess führt ihn nach dem erfolgreichen Abschluss aus. So wird keine E-Mail für eine Bestellung verschickt, die nie gespeichert wurde.

5. Migrationen sicher durchführen

Zum Umgang mit Transaktionen gehört auch die Frage, wie man das Datenbankschema im laufenden Betrieb ändert. Eine neue Spalte, ein neuer Index oder eine umbenannte Tabelle kann bei großen Tabellen lange dauern und Sperren halten, die den Betrieb blockieren. Bewährt hat sich das Vorgehen in kleinen, rückwärtskompatiblen Schritten, oft „Expand and Contract“ genannt: Zuerst wird das Neue ergänzt, etwa eine neue Spalte, ohne das Alte zu entfernen. Dann schreibt die Anwendung in beide, alte Daten werden im Hintergrund übertragen. Erst wenn alles auf das Neue umgestellt ist, wird das Alte entfernt.

Einige PostgreSQL-spezifische Regeln helfen zusätzlich: Indizes auf großen Tabellen werden mit CREATE INDEX CONCURRENTLY angelegt, damit Schreibzugriffe nicht blockiert werden. Neue Spalten mit Standardwerten sind in modernen Versionen schnell, das nachträgliche Setzen von NOT NULL auf großen Tabellen dagegen nicht. Und jede Migration sollte vorab auf einer Kopie der Produktivdaten getestet werden, um ihre Dauer abzuschätzen. Wer diese Regeln beachtet, kann das Schema auch bei großen Datenmengen ohne Ausfallzeit weiterentwickeln.

Transaktionen sind damit eines der mächtigsten Werkzeuge im System Design. Sie verlagern die schwierigste Frage der Nebenläufigkeit – wer darf wann was ändern? – in eine Komponente, die seit Jahrzehnten darauf optimiert ist. Wer sie gezielt einsetzt, braucht deutlich weniger komplizierte Logik im Anwendungscode und vermeidet eine ganze Klasse schwer auffindbarer Fehler.

6. Idempotenz und Transaktionen

Eng mit Transaktionen verbunden ist die Frage, was passiert, wenn eine Anfrage wiederholt wird. Ein Nutzer klickt zweimal auf „Bezahlen“, das Netzwerk bricht nach dem Absenden ab und die App versucht es erneut, oder ein Hintergrundjob läuft nach einem Absturz ein zweites Mal. Ohne Vorkehrung entstehen doppelte Bestellungen oder Zahlungen. Die Lösung ist ein Idempotenzschlüssel: Der Client erzeugt für jeden Vorgang eine eindeutige ID und schickt sie mit. Die Datenbank speichert diese ID mit einer eindeutigen Regel zusammen mit dem Ergebnis. Kommt dieselbe ID erneut, wird kein zweiter Vorgang ausgelöst, sondern das gespeicherte Ergebnis zurückgegeben.

Das funktioniert nur zuverlässig, wenn das Speichern der ID und der eigentliche Vorgang in derselben Transaktion geschehen. Genau hier zeigt sich wieder die Stärke der Datenbank: Eine eindeutige Regel und eine Transaktion garantieren, dass derselbe Vorgang höchstens einmal wirksam wird, auch wenn tausend Anfragen gleichzeitig eintreffen. Das Modul Skalierung greift Idempotenz im Zusammenhang mit Wiederholungen und Zeitlimits noch einmal auf, denn sie ist die Voraussetzung dafür, dass automatische Wiederholungen keinen Schaden anrichten.

Zusammengefasst: Transaktionen sichern ab, dass zusammengehörige Änderungen gemeinsam gelingen, Isolationsstufen und gezielte Sperren schützen vor gleichzeitigen Zugriffen, und Idempotenzschlüssel sorgen dafür, dass Wiederholungen keinen Schaden anrichten. Wer diese drei Werkzeuge beherrscht, hat die häufigsten Datenfehler in Webanwendungen im Griff.

Testen Sie diese Fälle bewusst. Automatisierte Tests, die zwei gleichzeitige Buchungen oder eine doppelt gesendete Zahlung simulieren, decken Fehler auf, die im normalen Klicktest nie auffallen würden. Solche Tests sind mit wenig Aufwand geschrieben und bewahren vor Fehlern, die sonst erst unter echter Last im Betrieb sichtbar werden – dann, wenn sie am teuersten sind.

Quellen und weiterführende Literatur
  1. [1]PostgreSQL Global Development Group (2026): Documentation – Transaction Isolation; Explicit Locking.
  2. [2]Berenson, H. et al. (1995): A Critique of ANSI SQL Isolation Levels. Proceedings of ACM SIGMOD, 1–10.
  3. [3]Kleppmann, M. (2017): Designing Data-Intensive Applications. Sebastopol: O'Reilly, Kap. 7.
  4. [4]Ports, D. R. K.; Grittner, K. (2012): Serializable Snapshot Isolation in PostgreSQL. Proceedings of the VLDB Endowment 5(12), 1850–1861.

Stand: September 2026. Kursmaterial der Klarwerk Akademie. Zahlen zu Latenzen und Kosten sind Größenordnungen zur Orientierung, keine Messwerte.

Abschlussquiz

Drei Fragen – dann ist die Lektion geschafft.

Frage 1 von 3

Was bedeutet Atomarität?