Manchmal müssen mehrere Datenbankoperationen als eine Einheit ausgeführt werden:
Beispiel Banküberweisung:
Probleme können entstehen durch:
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;Isolationsebenen bestimmen, wie Transaktionen sich gegenseitig “sehen”:
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 KontostandProbleme:
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:
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:
Höchste Isolationsebene:
-- Transaktion 1
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION;
SELECT * FROM konten;
-- Andere Transaktionen müssen warten
COMMIT;Vorteile:
Nachteile:
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 1Vermeidung 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:
-- Gut: Kurze Transaktion
START TRANSACTION;
UPDATE konten ...
UPDATE buchungen ...
COMMIT;
-- Schlecht: Lange Transaktion
START TRANSACTION;
SELECT ... -- Lange Analyse
UPDATE ... -- Viele Änderungen
-- Lange Verarbeitung
COMMIT;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;-- 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;