7.2 Commit-Behandlung
1. Bei Transaktionsende sendet der Koordinator eine PREPARE-Nachricht gleichzeitig an alle Agenten, um deren lokales Commit-Ergebnis in Erfahrung zu bringen.
2. Nach Empfang der PREPARE-Nachricht sichert der Agent einer erfolgreich zu Ende gekommene Sub-Transaktion deren Wiederholbarkeit durch das Ausschreiben von möglicherweise noch ungesicherten Log-Daten sowie eines Prepared-Satzes auf die lokale Log-Datei. Anschließend sendet der Agent eine READY-Nachricht an den Koordinator zurück. Danach wartet der Agent bis der Koordinator den Ausgang der globalen Transaktion (Commit oder Abort) mitteilt.
Für eine gescheiterte Sub-Transaktion werden ein Abort-Satz auf die lokale Log-Datei geschrieben und eine FAILED-Nachricht zum Koordinator geschickt. Der Agent setzt die Sub-Transaktion zurück, wobei auch von ihr gehaltene Sperren freigegeben werden[26]. Da das Scheitern der globalen Transaktion damit feststeht, wird die Sub-Transaktion daraufhin bereits beendet.
3. Nach Eintreffen aller Antwortnachrichten der Agenten beim Koordinator ist Phase 1 beendet. Haben alle Agenten mit READY geantwortet (und war das lokale Commit-Ergebnis am Koordinator-Knoten auch positiv), schreibt der Koordinator einen Commit-Satz in die lokale Log-Datei, woraufhin die globale Transaktion als erfolgreich beendet gilt. Danach wird eine COMMIT-Nachricht gleichzeitig an alle Agenten gesendet.
Stimmte mindestens ein Agent mit FAILED, so ist damit auch die globale Transaktion zum Scheitern verurteilt. Der Koordinator schreibt daher einen Abort-Satz auf seinen Log und sendet eine ABORT-Nachricht an alle Agenten, die mit READY gestimmt haben.
4. Ein Agent schreibt nach Eintreffen einer COMMIT-Nachricht ebenfalls einen Commit-Satz auf die Log-Datei und gibt anschließend die Sperren der Sub-Transaktion frei. Bei einer ABORT-Nachricht werden ein Abort-Satz geschrieben und die Sub-Transaktion zurückgesetzt, wobei gehaltene Sperren ebenfalls freigegeben werden.
Der Agent sendet danach zur Bestätigung noch eine Quittung (ACK-Nachricht) an den Koordinator. Nach Eintreffen aller ACK-Nachrichten beim Koordinator ist die globale Transaktion beendet, was durch einen Ende-Satz in der Log-Datei des Koordinators vermerkt wird.
Das Basisprotokoll erfordert pro Agent 4 Nachrichten, so daß bei einer über N Knoten verteilten globalen Transaktion insgesamt 4*(N-1) Nachrichten zur Commit-Behandlung anfallen. Weiterhin sind für den Koordinator sowie jeden Agenten zwei Schreibvorgänge auf die Log-Datei erforderlich. Bis auf den Ende-Satz sind diese Schreibvorgänge synchron, das heißt, die weitere Verarbeitung wird durch die E/A-Dauer verzögert. Es fallen somit insgesamt 2N-1 solcher synchronen Log-Vorgänge an.
Jeder an einer globalen Transaktion beteiligte Agent hat bis zur lokalen Commit-Entscheidung in Phase 1 das Recht des "unilateral abort", d.h. des einseitigen Transaktionsabbruchs. Dieses Recht wird jedoch nach Senden der READY-Nachricht aufgegeben; stattdessen wird die Verpflichtung übernommen, das globale Commit-Ergebnis des Koordinators zu akzeptieren. Die damit eingeführte Abhängigkeit zum Koordinator ist ein Hauptproblem des 2PC-Protokolls. Denn ein Koordinatorausfall kann dazu führen, daß andere Knoten lange Zeit auf das globale Commit-Ergebnis warten müssen (i.a. bis der Koordinator-Knoten wieder funktionsfähig ist). Da jedoch Sperren für die betroffenen Sub-Transaktionen bis zur globalen Entscheidung zu halten sind, kann dies zu erheblichen Leistungsproblemen ("Blockierungen") für andere Transaktionen führen.
Die Korrektheit des Protokolls im Normalbetrieb ist offensichtlich. Es bleibt also noch zu zeigen, wie unterschiedliche Fehlersituationen korrekt behandelt werden können. Hierzu ist die Betrachtung von Zustandsübergängen während der Commit-Bearbeitung hilfreich, wie sie in Abb. 7-4 für den Koordinator sowie die Agenten gezeigt sind. Die Knoten entsprechen dabei den einzelnen Zuständen, die Verbindungen zwischen ihnen den Zustandsübergängen. Zustandsübergänge sind durch zwei Angaben gekennzeichnet, die den Übergang auslösende Aktion (oben) sowie die dadurch veranlaßten Aktionen (unten).
Die Diagramme repräsentieren eine andere Darstellung des oben beschriebenen 2PC-Protokolls. Neu hinzugekommen sind vor allem die Berücksichtigung von Timeout-Ereignissen, über die Rechnerausfälle sowie Kommunikationsfehler abgefangen werden. Der Koordinator (Abb. 7-4a) befindet sich zunächst in einem Initialzustand (INITIAL). Nach Eingang der EOT-Operation wird für die betreffende Transaktion das Commit-Protokoll durch Verschicken der PREPARE-Nachrichten gestartet. Der Koordinator geht daraufhin in einen Wartezustand (WAIT). Nachdem alle Agenten mit READY gestimmt haben, wird das positive Commit-Ergebnis protokolliert und mitgeteilt; der Koordinator befindet sich jetzt im Zustand COMMITTING. Nach Eintreffen aller ACK-Nachrichten wird ein Ende-Satz auf den Log geschrieben, der den Endzustand TERMINATED kennzeichnet. Der Koordinator veranlaßt den Abbruch einer Transaktion, wenn einer der Agenten mit FAILED stimmt oder nicht innerhalb eines spezifizierten Timeout-Intervalls antwortet (Zustand ABORTING). Nach Eingang aller vom Abbruch informierten Agenten wird auch im Fehlerfall ein Ende-Satz auf den Log geschrieben. Wenn für die ACK-Nachrichten eine Timeout-Bedingung eintritt, dann protokolliert der Koordinator anstelle des Ende-Satzes in der Log-Datei, welche Agenten noch nicht geantwortet haben (in Abb. 7-4a nicht gezeigt).
Wir diskutieren jetzt, wie die Recovery für globale Transaktionen nach einem Rechnerausfall aussieht. Wesentlich hierzu ist, daß mit dem Log-Inhalt festgestellt werden kann, welcher Commit-Zustand vor dem Rechnerausfall erreicht wurde. Bei der Crash-Recovery für einen Agenten-Knoten sind folgende Fälle möglich:
Der Ausfall einer Kommunikationsverbindung wird wie beschrieben über Timeout-Bedingungen behandelt. Für nicht mehr erreichbare Knoten, auch im Rahmen von Netzwerk-Partitionierungen, ergibt sich somit die gleiche Behandlung wie für ausgefallene Rechner. Netzwerk-Partitionierungen bleiben nur dann ohne Auswirkungen, wenn Koordinator und alle Agenten in einer Partition verbleiben.