Kodokon kodokon.com

Transaktionen: BEGIN, COMMIT, ROLLBACK und ACID

Mache deine Schreibvorgänge mit Transaktionen atomar und verstehe, was die ACID-Garantien im Alltag bedeuten.

8 Min. · 3 Fragen

Diese Lektion in Kodokon öffnen

Eine Banküberweisung besteht aus zwei UPDATEs: ein Konto belasten, das andere gutschreiben. Schlägt das zweite fehl, lügt die Datenbank. Die Transaktion macht den Block unteilbar, mit den ACID-Garantien: Atomicity (alles oder nichts), Consistency (die Constraints bleiben gültig), Isolation (gleichzeitige Transaktionen sehen sich nie halbfertig), Durability (ein COMMIT überlebt einen Absturz). Bevorzuge für diese Lektion den echten sqlite3-Client: Manche Web-Sandboxes committen jede Abfrage automatisch.

SQL
CREATE TABLE accounts (
  id INTEGER PRIMARY KEY,
  owner TEXT NOT NULL,
  balance REAL NOT NULL CHECK (balance >= 0)
);

INSERT INTO accounts (owner, balance)
VALUES
  ('alice', 500.0),
  ('bruno', 120.0);
Die CHECK-Bedingung verbietet jeden negativen Kontostand.

Der Normalfall: BEGIN öffnet die Transaktion, die Schreibvorgänge sammeln sich an, COMMIT macht sie alle auf einmal endgültig. Dazwischen sieht keine andere Verbindung den Zwischenzustand (alice belastet, bruno noch nicht gutgeschrieben).

SQL
BEGIN;

UPDATE accounts
SET balance = balance - 200
WHERE owner = 'alice';

UPDATE accounts
SET balance = balance + 200
WHERE owner = 'bruno';

COMMIT;

SELECT owner, balance FROM accounts;
Atomare Überweisung: 300 für alice, 320 für bruno.

Jetzt der Fehlerfall. bruno um 400 zu belasten würde CHECK (balance >= 0) verletzen: Die Anweisung schlägt fehl. Eine SQLite-Feinheit: Standardmäßig bricht ein Fehler die fehlerhafte Anweisung ab, lässt die Transaktion aber offen. Es liegt an deinem Anwendungscode zu entscheiden: ROLLBACK, um alles rückgängig zu machen (der vernünftige Reflex), oder weitermachen, wenn der Fehler behebbar ist.

SQL
BEGIN;

UPDATE accounts
SET balance = balance - 400
WHERE owner = 'bruno';
-- Error: CHECK (balance >= 0) rejects the row.

ROLLBACK;

SELECT owner, balance FROM accounts;
Nach ROLLBACK sind die Kontostände des letzten COMMIT unversehrt.

Wissenscheck

Stelle sicher, dass du die wichtigsten Punkte dieser Lektion behalten hast.

  1. Was garantiert die Atomarität, das A in ACID?
    • Die Abfragen der Transaktion laufen schneller
    • Die Transaktion wird vollständig oder gar nicht angewendet
    • Zwei Transaktionen können niemals dieselbe Tabelle lesen
  2. In welchem Zustand ist die Datenbank nach einem ROLLBACK?
    • In dem des letzten COMMIT, als hätte es das BEGIN nie gegeben
    • Die UPDATEs, die vor dem Fehler erfolgreich waren, bleiben erhalten
    • Die Datenbank bleibt bis zum nächsten BEGIN gesperrt
  3. Warum sind 10.000 INSERTs in einer einzigen SQLite-Transaktion viel schneller?
    • SQLite komprimiert die eingefügten Daten gebündelt
    • Eine einzige Festplattensynchronisierung beim COMMIT statt einer pro Anweisung
    • Die Indizes sind während der Transaktion deaktiviert