17 Transaktion

17.1 Das Problem

Manchmal müssen mehrere Datenbankoperationen als eine Einheit ausgeführt werden:

Beispiel Banküberweisung:

  1. Geld vom Quellkonto abbuchen
  2. Geld auf Zielkonto gutschreiben

Probleme können entstehen durch:

17.2 Was ist eine Transaktion?

Eine Transaktion ist eine Folge von Datenbankoperationen, die als eine logische Einheit behandelt werden. Sie erfüllt die ACID-Eigenschaften:

-- Einfache Transaktion
START TRANSACTION;
    UPDATE konten SET kontostand = kontostand - 100 
    WHERE konto_id = 123;
    
    UPDATE konten SET kontostand = kontostand + 100 
    WHERE konto_id = 456;
COMMIT;

-- Bei Fehler: Rollback
START TRANSACTION;
    UPDATE konten SET kontostand = kontostand - 100 
    WHERE konto_id = 123;
    
    -- Wenn etwas schief geht:
    ROLLBACK;

17.3 Isolationsebenen

Isolationsebenen bestimmen, wie Transaktionen sich gegenseitig “sehen”:

17.3.1 READ UNCOMMITTED

Niedrigste Isolationsebene - andere Transaktionen sehen nicht committete Änderungen:

-- Transaktion 1
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
START TRANSACTION;
    UPDATE konten SET kontostand = kontostand - 100;
    -- Noch kein COMMIT

-- Transaktion 2 sieht die Änderung bereits
SELECT * FROM konten;  -- Zeigt neuen Kontostand

Probleme:

17.3.2 READ COMMITTED

Standard in vielen Datenbanken:

-- Transaktion 1
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
    SELECT * FROM konten WHERE konto_id = 123;  -- 1000€
    -- Zwischenzeitlich ändert eine andere Transaktion den Wert
    SELECT * FROM konten WHERE konto_id = 123;  -- Könnte jetzt 900€ sein
COMMIT;

Probleme:

17.3.3 REPEATABLE READ

Standard in MySQL/InnoDB:

-- Transaktion 1
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
    SELECT * FROM konten WHERE konto_id = 123;  -- 1000€
    -- Zwischenzeitlich ändert eine andere Transaktion den Wert
    SELECT * FROM konten WHERE konto_id = 123;  -- Immer noch 1000€
COMMIT;

Problem:

17.3.4 SERIALIZABLE

Höchste Isolationsebene:

-- Transaktion 1
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION;
    SELECT * FROM konten;
    -- Andere Transaktionen müssen warten
COMMIT;

Vorteile:

Nachteile:

17.4 Deadlock

Ein Deadlock entsteht, wenn sich Transaktionen gegenseitig blockieren:

-- Transaktion 1
START TRANSACTION;
UPDATE tabelleA SET spalte = 1 WHERE id = 1;
UPDATE tabelleB SET spalte = 1 WHERE id = 1;  -- Wartet auf Transaktion 2

-- Transaktion 2
START TRANSACTION;
UPDATE tabelleB SET spalte = 2 WHERE id = 1;
UPDATE tabelleA SET spalte = 2 WHERE id = 1;  -- Wartet auf Transaktion 1

Vermeidung von Deadlocks:

-- Immer gleiche Reihenfolge bei Sperren
START TRANSACTION;
UPDATE tabelleA SET spalte = 1 WHERE id = 1;  -- Immer erst A
UPDATE tabelleB SET spalte = 1 WHERE id = 1;  -- Dann B
COMMIT;

-- Timeout setzen
SET innodb_lock_wait_timeout = 50;

-- Deadlocks erkennen
SHOW ENGINE INNODB STATUS;

Praktische Tipps:

  1. Transaktionen kurz halten:
-- Gut: Kurze Transaktion
START TRANSACTION;
    UPDATE konten ...
    UPDATE buchungen ...
COMMIT;

-- Schlecht: Lange Transaktion
START TRANSACTION;
    SELECT ...  -- Lange Analyse
    UPDATE ...  -- Viele Änderungen
    -- Lange Verarbeitung
COMMIT;
  1. Fehlerbehandlung einbauen:
START TRANSACTION;
    UPDATE konten SET kontostand = kontostand - 100 
    WHERE konto_id = 123;
    
    IF ROW_COUNT() = 0 THEN
        ROLLBACK;
        SIGNAL SQLSTATE '45000' 
        SET MESSAGE_TEXT = 'Konto nicht gefunden';
    END IF;
    
    -- Weitere Operationen...
COMMIT;
  1. Isolationsebene bewusst wählen:
-- Für reine Lesezugriffe
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

-- Für wichtige Änderungen
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

-- Für kritische Finanztransaktionen
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;