🔒Sperren und Deadlocks

MVCC regelt das Lesen. Beim Schreiben (und beim sperrenden Lesen) braucht InnoDB Sperren – und zwar nicht nur auf Datensätzen, sondern auch auf den Lücken dazwischen.

📏Sperren-Labor: Index als Zahlengerade

Tabelle t mit Primärschlüssel id und den Zeilen 10, 20, 30. Wähle eine Sperre von Sitzung A und eine Anweisung von Sitzung B.

Sitzung A hält …

Sitzung B versucht …

INSERT 15102030supremum■ A: Next-Key X (10, 20]✘ B wartet
Insert-Intention auf 20 kollidiert mit gehaltener Next-Key X → Sitzung B wartet.
💡 Record-Lock
Sperrt genau einen Indexeintrag. Andere Datensätze und Lücken bleiben frei.
💡 Gap-Lock
Sperrt nur die Lücke vor einem Eintrag – gegen Einfügungen. Zwei Gap-Locks auf dieselbe Lücke vertragen sich.
💡 Next-Key-Lock
Record + Lücke davor, also (vorheriger, dieser]. Standard unter REPEATABLE READ – verhindert Phantome beim sperrenden Lesen.
💡 Insert-Intention
Ein INSERT kündigt an, in eine Lücke zu schreiben. Mehrere Einfügungen in dieselbe Lücke (an verschiedenen Stellen) warten nicht aufeinander.

🧮Konfliktmatrix

Zeilensperren auf demselben Datensatz – muss die Anforderung warten?
angefordert ↓ / gehalten →Record SRecord XGap SGap XNext-Key SNext-Key XInsert-Intention
Record S✔wartet✔✔✔wartet✔
Record Xwartetwartet✔✔wartetwartet✔
Gap S✔✔✔✔✔✔✔
Gap X✔✔✔✔✔✔✔
Next-Key S✔wartet✔✔✔wartet✔
Next-Key Xwartetwartet✔✔wartetwartet✔
Insert-Intention✔✔wartetwartetwartetwartet✔

Berechnet mit den Regeln aus lock_rec_has_to_wait(): Gap-Sperren blockieren nur Einfügungen (Insert-Intention), nie andere Sperren.

Tabellensperren (Intention Locks)
ISIXSX
IS✔✔✔✘
IX✔✔✘✘
S✔✘✔✘
X✘✘✘✘

Vor jeder Zeilensperre setzt InnoDB auf der Tabelle IS (für S) bzw. IX (für X). So erkennt ein LOCK TABLES … WRITE sofort, dass Zeilen gesperrt sind.

💀Deadlock im Wartegraphen

Zwei Transaktionen sperren dieselben Zeilen in umgekehrter Reihenfolge.
Schritt 1 / 6 · Tasten ← →

Zwei Überweisungen laufen gleichzeitig: A bucht von Konto 1 auf Konto 2, B von Konto 2 auf Konto 1.

ABWartegraph ohne Zyklus
A hält: –
B hält: –
✅ Vermeiden
Zeilen immer in derselben Reihenfolge sperren (z. B. nach id sortiert), Transaktionen kurz halten, passende Indizes – ohne Index sperrt ein UPDATE viel mehr Einträge.
💡 Lock Wait Timeout
Ohne Zyklus wartet eine Anweisung bis innodb_lock_wait_timeout (Standard 50 s) und endet dann mit ERROR 1205. MariaDB kennt zusätzlich SELECT … FOR UPDATE WAIT n und NOWAIT.
💡 Wer wartet gerade?
information_schema.INNODB_LOCK_WAITS, INNODB_TRX und SHOW ENGINE INNODB STATUS\G.