⭐ Laut Dozent: Verklemmungsvermeidung durch Zeitstempel (Wait-Die, Wound-Wait) ist Schwerpunkt. Stammt aus DB-I-Skript 05 Transactions.

Zusammenfassung

Eine Verklemmung (Deadlock) entsteht, wenn zwei oder mehr Transaktionen zyklisch aufeinander warten, weil jede eine Sperre hält, die die andere benötigt. Das DBMS erkennt Deadlocks durch Zyklensuche im Wartegraph und löst sie durch Rollback (Opfer). Vermeidungsstrategien wie Preclaiming (alle Sperren vorab) sowie die Zeitstempel-Verfahren Wait-Die und Wound-Wait verhindern Zyklen bereits im Vorfeld.

Kernkonzepte

Deadlock (Verklemmung)

Ein Deadlock liegt vor, wenn zwei oder mehr Transaktionen zyklisch aufeinander warten. T1 hält eine Sperre auf A und benötigt B, während T2 B hält und A benötigt. Ohne Eingriff wartet beides ewig. Voraussetzung ist typischerweise das strenge 2PL-Protokoll, das Sperren bis EOT hält. Deadlocks sind ein Konsistenzsicherungs-Problem und müssen vom DBMS entdeckt und aufgelöst werden.

Zwei Transaktionen, zwei Sperren, kreuzweise gefordert = Deadlock.

Wait-for-Graph (Wartegraph)

Der Wartegraph ist ein gerichteter Graph mit Knoten für Transaktionen und Kanten Ti -> Tj, wenn Ti auf eine Sperre wartet, die Tj hält. Er wird aus der Lock-Tabelle des DBMS gebildet. Enthält der Graph einen Zyklus, liegt ein Deadlock vor. Zyklenerkennung erfolgt per Tiefensuche. Zur Auflösung wird eine Transaktion aus dem Zyklus ausgewählt, zurückgesetzt (abort + R1-Recovery) und dadurch können beide Zyklen mit einem einzigen Opfer aufgebrochen werden, wenn dieses gemeinsame Knoten liegt.

Zyklus im Wartegraph = Deadlock, Opfer bricht den Kreis.

Preclaiming

Beim Preclaiming muss jede Transaktion vor Ausführung ihrer Operationen ALLE benötigten Sperren auf einmal erwerben. Erst wenn alle Sperren vorhanden sind, startet die eigentliche Arbeit. In Verbindung mit strengem 2PL bedeutet dies, dass die Sperrmenge sofort auf Maximum steht und bis EOT gehalten wird. Dadurch können niemals zwei Transaktionen wechselseitig auf Sperren warten. Nachteil: geringere Parallelität und man muss im Voraus wissen, welche Objekte gebraucht werden.

Alles vorab sperren, dann arbeiten - keine Kreise möglich.

Wound-Wait (Junge warten auf Alte)

Zeitstempel-basierte Vermeidung. Jede Transaktion bekommt beim Start einen eindeutigen Zeitstempel. Ältere TAs haben kleinere Stempel. Fordert T1 eine Sperre an, die T2 hält: Ist T1 älter als T2, wird T2 abgebrochen (wound) und zurückgesetzt, T1 läuft weiter. Ist T1 jünger, wartet T1 regulär. Wound-Wait bevorzugt ältere Transaktionen, indem sie jüngere verdrängen.

Alte darf junge verletzen - junge warten geduldig.

Wait-Die (Alte warten auf Junge)

Zweite Zeitstempel-Strategie. Fordert T1 eine Sperre, die T2 hält: Ist T1 älter als T2, wartet T1 auf die Freigabe. Ist T1 jünger, wird T1 abgebrochen (die) und mit gleichem Zeitstempel neu gestartet. Bei Wait-Die dürfen nur ältere Transaktionen warten, jüngere sterben und werden neu gestartet. Beide Strategien vermeiden Zyklen, weil die Warterichtung immer nur in eine Zeitstempel-Richtung geht.

Alte warten geduldig, junge sterben und starten neu.

Erkennung vs. Vermeidung

Zwei Grundansätze: Deadlock-Erkennung (detection) lässt Deadlocks entstehen und löst sie über den Wartegraph auf. Deadlock-Vermeidung (avoidance/prevention) verhindert Deadlocks strukturell, z.B. durch Preclaiming oder Zeitstempel. Erkennung erlaubt höhere Parallelität, kostet aber Zyklensuche. Vermeidung ist proaktiv, reduziert aber Nebenläufigkeit oder erzeugt unnötige Rollbacks.

Erkennen und auflösen oder vermeiden bevor es passiert.

Strenges 2PL als Voraussetzung

Deadlocks sind ein typisches Problem des strengen Zwei-Phasen-Sperrprotokolls (S2PL). Dort werden alle Sperren bis zum EOT gehalten, damit kaskadierendes Rücksetzen ausgeschlossen ist. Genau dieses lange Halten der Sperren macht aber Zyklen im Wartegraph möglich. Ohne 2PL wären Deadlocks im klassischen Sinn nicht das Hauptproblem, dafür aber Inkonsistenzen wie Dirty Read und Lost Update.

S2PL sichert Konsistenz, öffnet aber Tür für Deadlocks.

Auflösung durch Rollback (Opferwahl)

Wird ein Zyklus erkannt, wählt das DBMS ein Opfer im Zyklus aus (häufig die jüngste, die mit wenigsten Sperren oder die mit geringsten Kosten). Das Opfer erhält abort und wird per R1-Recovery zurückgesetzt. Die freigewordenen Sperren erlauben den anderen TAs, weiterzulaufen. Liegt ein Knoten in mehreren Zyklen, kann sein Rollback mehrere Verklemmungen gleichzeitig lösen.

Ein Opfer, ein Rollback - der Zyklus zerfällt.

Wichtige Details

  • Deadlock-Voraussetzungen: mindestens zwei TAs, mindestens zwei Sperren, wechselseitiges Warten, keine Präemption der Sperren.
  • Der Wartegraph wird aus der Lock-Tabelle konstruiert; Kante Ti -> Tj bedeutet: Ti wartet auf eine Sperre, die Tj hält.
  • Zyklenerkennung erfolgt per Tiefensuche (DFS) im Wartegraphen.
  • Ein Rollback kann gleichzeitig mehrere Zyklen auflösen, wenn das Opfer in allen Zyklen liegt (Beispiel T3 im Foliensatz).
  • Preclaiming garantiert Deadlockfreiheit, senkt aber die Parallelität und erfordert Vorabkenntnis der Zugriffe.
  • Wound-Wait: ältere Transaktion darf jüngere abbrechen - jüngere warten nur.
  • Wait-Die: ältere Transaktion darf warten - jüngere sterben (abort + Neustart mit gleichem TS).
  • Zeitstempel-Verfahren funktionieren ohne zentralen Scheduler, TAs setzen sich selbst zurück.
  • Beim Neustart nach wait-die/wound-wait behält die Transaktion ihren ursprünglichen Zeitstempel, damit sie irgendwann alt genug ist (kein Starvation).
  • MVCC vermeidet Lese-Deadlocks komplett: Writers do not block readers, readers do not block writers.

Beispiele

Klassischer Deadlock mit zwei TAs

T1 hält X-Sperre auf A und will B; T2 hält S-Sperre auf B und will A. Beide warten unendlich.

Schritt 1: T1: BOT Schritt 2: T1: lockX(A) Schritt 3: T2: BOT Schritt 4: T2: lockS(B) Schritt 5: T2: read(B) Schritt 6: T1: read(A) Schritt 7: T1: write(A) Schritt 8: T1: lockX(B) -> muss warten auf T2 Schritt 9: T2: lockS(A) -> muss warten auf T1 => Deadlock (Wartegraph: T1 -> T2 -> T1)

Wartegraph mit zwei Zyklen und einem Opfer

Fünf TAs bilden zwei überlappende Zyklen. T3 liegt in beiden. Rollback von T3 löst beide Verklemmungen gleichzeitig.

Zyklus 1: T1 -> T2 -> T3 -> T4 -> T1 Zyklus 2: T2 -> T3 -> T5 -> T2 Opferwahl: T3 (in beiden Zyklen) Aktion: abort(T3) + R1-Recovery für rollback => Beide Zyklen aufgelöst, T1, T2, T4, T5 können weiterlaufen.

Wound-Wait konkret

T1 (ts=5, alt) will Sperre, die T2 (ts=10, jung) hält. T1 verletzt T2 -> T2 wird abgebrochen.

T1 (ts=5): lockX(A) -> hält A T2 (ts=10): lockX(B) -> hält B T2: lockX(A) -> T2 jünger als T1, T2 wartet (Regel: jung wartet auf alt) T1: lockX(B) -> T1 älter als T2, T2 wird gewound (abort + rollback), T1 bekommt B.

Wait-Die konkret

Gleiche Situation, aber Wait-Die-Strategie.

T1 (ts=5, alt): lockX(A) T2 (ts=10, jung): lockX(B) T1: lockX(B) -> T1 älter als T2, T1 wartet T2: lockX(A) -> T2 jünger als T1, T2 stirbt (abort + Neustart mit ts=10) => T1 bekommt B nach T2-Freigabe.

Grafik: Wartegraph und Zeitstempel-Strategien

1. Klassischer Deadlock: T1 und T2 kreuzweise T1 lockX(A) read(A) write(A) lockX(B) wartet T2 lockS(B) read(B) lockS(A) wartet DEADLOCK Wartegraph 2 TAs T1 T2 Zyklus = Deadlock 2. Wartegraph mit 2 Zyklen - T3 als Opfer T1 T2 T3 Opfer T4 T5 Legende wartet-auf Kante nach Rollback aufgelöst Zyklus 1: T1 -> T2 -> T3 -> T4 -> T1 Zyklus 2: T2 -> T3 -> T5 -> T2 Ein Opfer (T3) löst beide! 3. Wound-Wait vs. Wait-Die Wound-Wait Alte darf junge verletzen T1 ts=5 alt wound T2 ts=10 jung abort Rollback jung: wartet - alt: verdrängt Wait-Die Alte wartet, junge stirbt T1 ts=5 alt wartet T2 ts=10 jung die Neustart ts=10 alt: wartet - jung: abort + restart
Oben: klassischer Deadlock mit zwei TAs und dessen Wartegraph. Mitte: Wartegraph mit zwei überlappenden Zyklen, T3 als gemeinsames Opfer. Unten: Vergleich Wound-Wait und Wait-Die.

FAQ

Warum entstehen Deadlocks überhaupt im strengen 2PL?
Weil S2PL alle Sperren bis EOT hält. Zwei TAs können so kreuzweise Sperren erwerben und dann wechselseitig auf die je andere Sperre warten.
Was ist der Unterschied zwischen Erkennung und Vermeidung?
Erkennung lässt Deadlocks zu und löst sie über den Wartegraph auf. Vermeidung verhindert sie strukturell, z.B. durch Preclaiming oder Zeitstempel.
Wie erkenne ich einen Deadlock im Wartegraph?
Über einen Zyklus. Ein gerichteter Kreis Ti -> ... -> Ti bedeutet, dass alle TAs im Kreis aufeinander warten.
Welche Transaktion wird geopfert?
Meist die jüngste, die mit den wenigsten Sperren oder die mit geringstem Aufwand bis zum Rollback. Idealerweise ein Knoten in mehreren Zyklen, damit ein Opfer mehrere Verklemmungen löst.
Warum vermeidet Preclaiming Deadlocks garantiert?
Weil jede TA entweder ALLE benötigten Sperren gleichzeitig erhält oder gar keine. Es gibt keine Situation, in der eine TA schon Sperren hält und auf eine weitere wartet - also keinen Zyklus.
Wodurch unterscheiden sich Wound-Wait und Wait-Die?
Wound-Wait: ältere darf jüngere abbrechen, jüngere wartet nur. Wait-Die: ältere wartet, jüngere stirbt (abort + Neustart). Beide vermeiden Zyklen, weil die Wartekante immer nur in eine Zeitstempel-Richtung zeigt.
Warum behält eine wieder gestartete TA ihren Zeitstempel?
Damit sie mit jedem Neustart älter wirkt und irgendwann Priorität bekommt. Sonst droht Starvation - sie würde immer wieder als jüngste sterben.
Was ist die Rolle der Lock-Tabelle bei der Deadlock-Erkennung?
Die Lock-Tabelle listet, welche TA welche Sperre hält und welche wartet. Aus diesen Informationen konstruiert das DBMS den Wartegraph und sucht per Tiefensuche nach Zyklen.

Prüfungsfragen

Fortschritt 0 von 12 beantwortet