Transaktion
Eine Transaktion ist eine Folge von Datenbankoperationen, die als eine logische Einheit betrachtet und ausgefuehrt werden. Entweder werden alle Operationen der Transaktion erfolgreich abgeschlossen, oder keine einzige. Dieses Alles-oder-Nichts-Prinzip ist fundamental fuer die Datenintegritaet in relationalen Datenbanken.
Ein klassisches Beispiel ist eine Bankueberweisung: Das Abbuchen vom Senderkonto und das Gutschreiben auf dem Empfaengerkonto muessen beide erfolgen oder beide fehlschlagen. Wuerde nur eine Operation ausgefuehrt, waere der Datenbestand inkonsistent.
Die ACID-Eigenschaften
Transaktionen in Datenbankmanagementsystemen (DBMS) muessen vier grundlegende Eigenschaften erfuellen, die unter dem Akronym ACID zusammengefasst werden. Diese Eigenschaften garantieren die Zuverlaessigkeit und Konsistenz der Daten, selbst bei Systemausfaellen oder gleichzeitigen Zugriffen mehrerer Benutzer.
Atomicity (Atomaritaet)
Atomaritaet bedeutet, dass eine Transaktion als unteilbare Einheit behandelt wird. Entweder werden alle enthaltenen Operationen vollstaendig ausgefuehrt (Commit), oder bei einem Fehler werden alle Aenderungen rueckgaengig gemacht (Rollback). Es gibt keinen Zwischenzustand.
-- Beispiel: Atomare Bankueberweisung
START TRANSACTION;
UPDATE konten SET saldo = saldo - 100 WHERE konto_id = 1;
UPDATE konten SET saldo = saldo + 100 WHERE konto_id = 2;
-- Entweder beide oder keine Aenderung
COMMIT;
Consistency (Konsistenz)
Konsistenz stellt sicher, dass eine Transaktion die Datenbank von einem gueltigen Zustand in einen anderen gueltigen Zustand ueberfuehrt. Alle definierten Regeln und Constraints wie Primaerschluessel, Fremdschluessel oder CHECK-Constraints muessen vor und nach der Transaktion erfuellt sein.
Verletzt eine Transaktion eine dieser Regeln, wird sie abgebrochen und zurueckgerollt. So kann beispielsweise kein negativer Kontostand entstehen, wenn ein entsprechender Constraint definiert ist.
Isolation
Isolation garantiert, dass parallel laufende Transaktionen sich nicht gegenseitig beeinflussen. Jede Transaktion arbeitet so, als waere sie die einzige im System. Die Aenderungen einer Transaktion werden erst nach dem Commit fuer andere Transaktionen sichtbar.
Es gibt verschiedene Isolationslevel, die einen Kompromiss zwischen Datenkonsistenz und Performance ermoglichen:
| Isolationslevel | Dirty Read | Non-Repeatable Read | Phantom Read |
|---|---|---|---|
| Read Uncommitted | Moeglich | Moeglich | Moeglich |
| Read Committed | Verhindert | Moeglich | Moeglich |
| Repeatable Read | Verhindert | Verhindert | Moeglich |
| Serializable | Verhindert | Verhindert | Verhindert |
Je hoeher das Isolationslevel, desto sicherer sind die Daten vor Anomalien geschuetzt, aber desto mehr wird die parallele Verarbeitung eingeschraenkt. In der Praxis waehlt man das passende Level je nach Anwendungsfall.
Durability (Dauerhaftigkeit)
Dauerhaftigkeit garantiert, dass erfolgreich abgeschlossene Transaktionen permanent in der Datenbank gespeichert bleiben. Selbst bei einem Systemabsturz, Stromausfall oder anderen Stoerungen gehen die Daten nicht verloren. Das DBMS schreibt die Aenderungen in ein Transaction Log, bevor es den Commit bestaetigt.
Transaktionssteuerung in SQL
In SQL steuert man Transaktionen mit speziellen Befehlen. Die genaue Syntax kann je nach Datenbanksystem leicht variieren, aber die Grundprinzipien sind ueberall gleich.
-- Transaktion starten
START TRANSACTION; -- oder BEGIN in manchen DBMS
-- Datenbankoperationen ausfuehren
INSERT INTO bestellungen (kunde_id, datum) VALUES (42, NOW());
UPDATE lagerbestand SET menge = menge - 1 WHERE artikel_id = 123;
-- Bei Erfolg: Aenderungen dauerhaft speichern
COMMIT;
-- Bei Fehler: Alle Aenderungen zuruecknehmen
ROLLBACK;
Savepoints
Mit Savepoints kannst du innerhalb einer Transaktion Zwischenpunkte setzen, zu denen du bei Bedarf zurueckspringen kannst, ohne die gesamte Transaktion abzubrechen.
START TRANSACTION;
INSERT INTO protokoll (aktion) VALUES ('Schritt 1');
SAVEPOINT nach_schritt_1;
INSERT INTO protokoll (aktion) VALUES ('Schritt 2');
-- Fehler erkannt: Nur Schritt 2 zuruecknehmen
ROLLBACK TO nach_schritt_1;
-- Schritt 1 bleibt erhalten
COMMIT;
Concurrency-Probleme und Locking
Wenn mehrere Transaktionen gleichzeitig auf dieselben Daten zugreifen, koennen ohne geeignete Schutzmechanismen verschiedene Probleme auftreten. Das DBMS verwendet Sperrmechanismen (Locking), um diese zu verhindern.
Typische Anomalien
Diese drei Anomalien koennen bei unzureichender Isolation auftreten:
- Dirty Read: Eine Transaktion liest Daten, die von einer anderen Transaktion geaendert, aber noch nicht committed wurden. Wird die andere Transaktion zurueckgerollt, hat man ungueltige Daten gelesen.
- Non-Repeatable Read: Dieselbe Abfrage liefert innerhalb einer Transaktion unterschiedliche Ergebnisse, weil eine andere Transaktion dazwischen Daten geaendert hat.
- Phantom Read: Bei wiederholten Abfragen erscheinen ploetzlich neue Zeilen, weil eine andere Transaktion Datensaetze eingefuegt hat.
Sperrmechanismen
Datenbanken verwenden verschiedene Arten von Sperren, um den gleichzeitigen Zugriff zu koordinieren:
- Shared Lock (S-Lock): Erlaubt anderen Transaktionen das Lesen, aber nicht das Schreiben
- Exclusive Lock (X-Lock): Blockiert sowohl Lesen als auch Schreiben durch andere Transaktionen
- Row-Level Locking: Sperrt nur einzelne Zeilen, ermoeglicht hohe Parallelitaet
- Table-Level Locking: Sperrt ganze Tabellen, einfacher aber weniger performant
Deadlocks
Ein Deadlock entsteht, wenn zwei oder mehr Transaktionen gegenseitig auf die Freigabe von Sperren warten. Transaktion A haelt eine Sperre und wartet auf eine Ressource von B, waehrend B auf eine Ressource von A wartet. Das DBMS erkennt solche Situationen und bricht eine der Transaktionen ab, um den Deadlock aufzuloesen.
Transaktionen in der Anwendungsentwicklung
In der Softwareentwicklung arbeitest du oft nicht direkt mit SQL-Befehlen, sondern verwendest Frameworks und ORMs, die die Transaktionsverwaltung abstrahieren. Das Grundprinzip bleibt jedoch dasselbe.
// Beispiel in Java mit JDBC
Connection conn = dataSource.getConnection();
try {
conn.setAutoCommit(false); // Transaktion starten
// Datenbankoperationen
stmt.executeUpdate("UPDATE konten SET saldo = saldo - 100 WHERE id = 1");
stmt.executeUpdate("UPDATE konten SET saldo = saldo + 100 WHERE id = 2");
conn.commit(); // Bei Erfolg
} catch (SQLException e) {
conn.rollback(); // Bei Fehler
throw e;
}
Moderne Frameworks wie Spring bieten deklarative Transaktionsverwaltung mit Annotationen, was den Code uebersichtlicher macht und Fehler reduziert.
Transaktionen in der Praxis
Das Verstaendnis von Transaktionen ist fuer Fachinformatiker fuer Anwendungsentwicklung essenziell. Du begegnest ihnen bei der Entwicklung von Webanwendungen, Enterprise-Software und ueberall dort, wo Datenintegritaet wichtig ist.
Typische Anwendungsfaelle sind Finanztransaktionen, Bestellprozesse in Online-Shops, Buchungssysteme und alle Szenarien, in denen mehrere zusammenhaengende Datenaenderungen atomar ausgefuehrt werden muessen.