Wirtschaftsinformatik: Komplexe Datenbank-Anwendungen

Sie sind hier: StartseiteWirtschaftsinformatikKomplexe Datenbank-Anwendungen (Transaktionen)

IC / CM, Kurs vom 01.10.2005 - 31.03.2006

Komplexe Datenbank-Anwendungen (Transaktionen): Transaktionen (ACID-Eigenschaften, Kontrollfluss zwischen Datenbanksystem und Anwendungsprogramm, Transaktionssysteme, Anomalien, Sperren, Konsistenzstufen, Protokollierung, Gesamtsicherung und Wiederherstellung, Ersetzungs-/Ausschreibungsstrategien), Verteilte Transaktionen (Beteiligte bei verteilten Transaktionen, Zwei-Phasen-Commit-Protokoll, Spezifikationen, Zustandsübergänge, Praxis), Transaktionen in Java (Unterscheidungen in Java, Lokale Transaktionen, Globale Transaktionen)

  1. Transaktionen
  2. Verteilte Transaktionen
  3. Transaktionen in Java

Transaktionen

ACID-Eigenschaften

Transaktionen sind eine Folge von Datenbankaktionen, die als Einheit betrachtet werden (z.B. Geld von einem Unterkonto auf ein anderes überweisen), mit begin starten und mit commit oder rollback enden.

Bei Transaktionen erwünscht sind folgende ACID-Eigenschaften:

Es gibt verschiedene Mechanismen zur Sicherstellung von ACID:

Die Einbettung von Transaktionen in Anwendungsprogramme wird realisiert über BOT (Beginn der Transaktion), COMMIT (erfolgreiches Ende) und ROLLBACK (Abbruch).

Kontrollfluss zwischen Datenbanksystem und Anwendungsprogramm

Es erfolgt ein Kontrollfluss zwischen Datenbanksystem und Anwendungsprogramm. Startpunkt ist der Transaktionsbeginn im Anwendungsprogramm. Im Datenbanksystem wird parallel die Rücksetzbarkeit von Änderungsoperationen sichergestellt. Anschließend erfolgt im Anwendungsprogramm der Aufruf einer Datenbankoperation, womit im Datenbanksystem Änderungen ausgeführt und unverzögerte Integritätsbedingungen überprüft werden. Daraufhin folgt im Anwendungsprogramm das Transaktionsende, woraufhin es im Datenbanksystem erneut zum Überprüfen der verzögerten Integritätsbedingungen sowie zum Sicherstellen der Wiederholbarkeit aller Änderungen kommt. Danach erfolgt von Seite des Datenbanksystems ein Sichtbarmachen von Änderungen und eine Bestätigung über das erfolgreiche Ende. Nun kann das Anwendungsprogramm weiterarbeiten.

Transaktionssysteme

Transaktionssysteme bestehen aus Anwendungsprogramm, Transaktionsmanager und Ressourcenmanager. Aufbau und Zusammensetzung variieren.

Eine Variante ist der Transaction Processing Monitor, ein Betriebssystem für die Transaktionsverarbeitung, welches die Komplexität der Anwendungsentwicklung reduziert, eine effiziente Ressourcen-Nutzung sicherstellt und einen hohen Durchsatz ermöglicht.

Die Steuerung der Nebenläufigkeit erfolgt über Anomalien, Sperren und Konsistenzstufen. Anomalien (Lost Update, Dirty Read, Non-repeatable Read) sind Nebeneffekte, die durch den verzahnten Ablauf von Transaktionen entstehen.

Anomalien

Lost Update entsteht beispielsweise bei Buchungsaktionen. Ausgangspunkt sind 80 freie Plätze. Mit Transaktion 1 wird beispielsweise die Buchung von fünf Plätzen vorgenommen, das Ergebnis (75 freie Plätze) jedoch noch nicht in die Datenbank geschrieben. Tritt jetzt Transaktion 2 ein, beispielsweise das Stornieren von vier Plätzen, so arbeitet Transaktion 2 mit den ursprünglich vorhandenen 80 Plätzen und erhöht diese auf 84. In diesem Moment speichert Transaktion 1 zufällig seine 75. Doch fataler Weise weiß Transaktion 2 doch gar nichts davon, da sie noch mit der Ursprungszahl (80) arbeitet. Ein Speichern führt nun zu der falschen Platzzahl 84 und die Buchung aus Transaktion 1 ist nicht im System.

Dirty Read geht noch einen Schritt weiter. Zurück zum Buchungsbeispiel. Ein Platz ist noch frei. Transaktion 1 nimmt diesen in Anspruch und speichert auch den neuen Wert (0). Transaktion 2 bekommt bei Anfrage die Rückmeldung, dass kein Platz mehr verfügbar ist. Doch jetzt tritt der Problemfall ein, Transaktion 1 bestätigt ihre Aktion nicht, der Platz ist also weiterhin verfügbar. Transaktion 2 hätte demnach buchen können, hat aber einen nicht bestätigten Wert gelesen.

Bei (Achtung, jetzt kommt eine wirklich sehr unglücklich gewählte und dadurch verwirrende Bezeichnung!) Non-repeatable Read liest Transaktion 1 den Wert einer Variable. Dann ändert Transaktion 2 diesen und aktualisiert die Variable. Jetzt liest Transaktion 1 erneut und erhält einen anderen Wert als zuvor. Das mag bei lesenden Transaktionen nicht weiter verwerflich sein, kann bei ändernden Transaktionen jedoch zum Verlust der inneren Konsistenz führen.

Ein Sonderfall des Non-repeatable Read sind Phantome. Transaktion 1 liest Daten über eine Suchanfrage (where...). Transaktion 2 fügt einen Datensatz hinzu. Der bei erneuter Abfrage durch Transaktion 1 auftauchende (neue) Datensatz wird als Phantom bezeichnet.

Sperren

Mit dem Setzen von Sperren wird durch Kontrolle der Nebenläufigkeit die Isolation erreicht: Lesen und Schreiben von Daten (read/write entspricht select/update von SQL), Sperren auf Daten, die von mehreren Transaktionen gemeinsam gesetzt werden können (slock, shared lock), exklusive Sperre, die nur von einer Transaktion gesetzt werden kann (xlock, exclusive lock), Aufheben von Sperren (unlock) sowie Starten einer Transaktion und erfolgreiches Abschließen/Verwerfen der durchgeführten Operationen (bot, commit, rollback).

Transaktionen können vereinfacht und mit Sperrfreigaben versehen werden. Zuerst einmal wird bot weggelassen. Endet eine Transaktion mit commit, wird dieses durch eine Liste von unlock-Operationen ersetzt. Für jedes slock oder xlock wird ein unlock erzeugt. Endet eine Transaktion mit rollback, wird dieses durch eine Liste von write und unlock-Operationen ersetzt. Die unlock-Operationen werden wie im commit-Fall erzeugt. Die write-Operationen schreiben wieder die alten Werte zurück und bewirken damit ein Rückgängigmachen der ausgeführten Operationen.

Zum Thema Sperrprotokolle: Es gibt verschiedene Varianten für das Setzen von Sperren: keine Sperren, Setzen von slock vor dem Lesen von Daten und Setzen von xlock vor dem Schreiben von Daten. Bei der Sperrdauer gibt es kurze Sperren, die direkt nach dem Benutzen wieder freigegeben werden (vor Transaktionsende) und lange Sperren, die erst am Transaktionsende wieder freigegeben werden. Das Setzen eines xlock ist die Lösung für die Lost Update-Anomalie. Hat Transaktion 1 eine Variable zu Änderungszwecken gesperrt, kann Transaktion 2 erst nach Freigabe (unlock) auf den Wert zugreifen, solange keine Änderungen durchführen und somit keine Änderung verloren gehen.

Weiterhin sei auf hierarchische Sperren hingewiesen. Durch die Möglichkeit einer Sperrgranularität/-hierarchie können Sperren sehr spezifisch gesetzt werden (Spalte, Datensatz, Seite, Tabelle, Datei, Datenbank). Erweiterte Sperrmodi sind intend share (Vorhaben eine gemeinsame Sperre auf einer niedrigeren Ebene zu setzen. Ist bereits ein IS gesetzt, kann anderen Transaktionen noch IS, IX, S, SIX erteilt werden), intend exclusive (Vorhaben eine gemeinsame oder exklusive Sperre auf einer niedrigeren Ebene zu setzen. Ist bereits ein IX gesetzt, kann anderen Transaktionen noch IS, IX erteilt werden) und shared and intend exclusive (Setzen einer gemeinsamen Sperre auf höherer Ebene und Vorhaben eine exklusive Sperre auf einer niedrigeren Ebene zu setzen. Ist bereits ein SIX gesetzt, kann anderen Transaktionen nur noch IS erteilt werden).

Konsistenzstufen

Mit Konsistenzstufen wird die Isolation in SQL umgesetzt. Nachfolgend werden die vier möglichen Stufen beschrieben und in Relation zu möglichen Anomalien gesetzt.

In der Stufe Read Uncommitted (jeder liest einfach immer) können die Anomalien Dirty Read, Non-repeatable Read und Phantome auftreten. Dies ist die schwächste Konsistenzstufe. Sie darf nur für Lese-Transaktionen spezifiziert werden. Eine derartige Transaktion hat Zugriff auf noch nicht festgeschriebene Daten. Beispiel: Transaktion 1 macht update FLUG set FREI = FREI - 5 where FLUGNR = 'LH2456'. Transaktion 2 selektiert alle Inhalte der Tabelle mit select * from FLUG. Transaktion 2 läuft durch und berücksichtigt aufgrund der Konsistenzstufe Read Uncommitted die Sperren nicht. Damit wird das Lesen nicht bestätigter Änderungen zugelassen.

In der Stufe Read Committed (nur gespeichertes ist lesbar) können die Anomalien Non-repeatable Read und Phantome auftreten. Diese Transaktionen lesen nur festgeschriebene Werte. Allerdings können sie unterschiedliche Zustände der Datenbasis-Objekte zu sehen bekommen. Transaktion 1 sagt beispielsweise update FLUG set FREI = FREI - 5 where FLUGNR = 'LH2456'. Transaktion 2 kann jetzt nicht sagen select * from FLUG. Diese Transaktion bleibt stehen, da Transaktion 1 eine Sperre auf die eine Zeile gesetzt hat. Damit wird das Lesen nicht bestätigter Änderungen verhindert. Ein anderes Beispiel: Transaktion 1 macht ein select * from FLUG. Transaktion 2 folgt mit update FLUG set FREI = FREI - 5 where FLUGNR = 'LH2456'. Transaktion 2 kann durchlaufen, da sie ihre Sperren trotz des Lesens von Transaktion 1 setzen kann. Und noch ein drittes Beispiel: Transaktion 1 macht update FLUG set FREI = FREI - 5 where FLUGNR = 'LH2456'. Transaktion 2 selektiert eine andere Zeile mit update FLUG set FREI = FREI - 3 where FLUGNR = 'BA9876'. Beide Transaktionen laufen durch, da die Sperren auf verschiedene Zeilen gesetzt werden.

In der Stufe Repeatable Read (immer wieder lesen) kann die Anomalie von Phantomen auftreten. Das passiert z.B., wenn durch eine parallele Änderungstransaktion Tupel ein Selektionsprädikat erfüllen, das sie zuvor nicht erfüllten. Beispiel: Transaktion 1 möchte alle Daten aus Tabelle Flug (select * from FLUG). Transaktion 2 möchte einen bestimmten Datensatz ändern (update FLUG set FREI = FREI - 5 where FLUGNR = 'LH2456'). Transaktion 2 bleibt stehen. So wird verhindert, das Transaktion 1 beim nochmaligen Lesen der Daten durch Transaktion 2 geänderte Werte erhält. Ein zweites Beispiel: Transaktion 1 macht select * from FLUG. Transaktion 2 macht insert into FLUG values ('KL5486','26.10.2003',10). Transaktion 2 läuft durch, da Repeatable Read Phantome zulässt. Ein nochmaliges Lesen innerhalb der noch offenen Transaktion 1 würde die eingefügte Zeile anzeigen.

In der Stufe Serializable können keine Anomalien auftreten. Diese Konsistenzstufe fordert die Serialisierbarkeit. Beispiel: Transaktion 1 macht ein select * from FLUG. Transaktion 2 macht ein insert into FLUG values ('KL5486','26.10.2003',10). Transaktion 2 bleibt stehen, da Serializable keine Phantome zulässt. Um dieses Verhalten zu erreichen, wird eine Sperre auf die gesamte Flug-Tabelle gesetzt.

Protokollierung

Bei der Wiederherstellung können folgende Fehlerarten auftreten: Transaktionsfehler, Systemfehler und Gerätefehler. Die Protokollierung (Logging) funktioniert nach dem Do-Redo-Undo-Prinzip. Aufgaben sind einerseits die Sammlung redundanter Daten bei Änderungen im Normalbetrieb (Do) als Voraussetzung für Recovery und andererseits der Einsatz im Fehlerfall (Undo-, Redo-Recovery, Undo-Information beschreibt, wie die Änderung rückgängig gemacht werden kann, Redo-Information gibt an, wie die Änderung nachvollzogen werden kann).

Zu beachten sind folgende Protokollierungsregeln: Write-Ahead-Log-Prinzip (erst Undo-Informationen in Log schreiben, auf Festplatte sichern, dann "schmutzige" Änderungen in die Datenbank einbringen), Commit-Regel (erst Redo-Informationen in Log schreiben, auf Festplatte sichern, dann Commit durchführen) und Wiederherstellung nach Systemfehler (Undo aller Änderungen ohne Commit im Log, Redo aller Änderungen mit Commit Log).

Gesamtsicherung und Wiederherstellung

Für eine Gesamtsicherung und Wiederherstellung (Backup) ist die Speicherung der gesamten Datenbank sowie der Log-Dateien auf einem externen Medium (z.B. Band) empfehlenswert. Die gesamte Datenbank wird eher selten gesichert, da dies sehr lange dauert und kein normaler Betrieb herrschen darf. Im Gegensatz dazu sollten die Log-Dateien jedoch häufig gesichert werden.

Bei einem Recovery muss die gesamte Datenbank eingespielt und das Log (Redo aller Transaktionen mit Commit) abgearbeitet werden. Systemkomponenten sind also das Datenbankmanagementsystem, der Datenbank-Puffer (Archiv-Kopie der Datenbank + Datenbank) und der Log-Puffer (Archiv-Log + Log-Datei).

Ersetzungs-/Ausschreibungsstrategien

Ersetzungs-/Ausschreibungsstrategien unterscheiden Änderungen vor Commit (nosteal und steal) und Änderungen beim Commit (force und noforce).

Mit nosteal sind keine Ausschreibungen "schmutziger" Änderungen möglich. Bei dieser Strategie wird die Ersetzung von Seiten, die von einer noch aktiven Transaktion modifiziert wurden, ausgeschlossen. Das führt bei langen Änderungstransaktionen zu Problemen.

steal ermöglicht die Ausschreibung "schmutziger" Änderungen. Jede nicht fixierte Seite ist prinzipiell ein Kandidat für die Ersetzung, falls neue Seiten eingelagert werden müssen. Einbringen von Änderungen abgeschlossener Transaktionen. Erfordert Einhaltung des Write-Ahead-Log-Prinzips: vor dem Einbringen einer schmutzigen Änderung müssen zugehörige Undo-Informationen (z.B. Before-Images) in die Log-Datei geschrieben werden.

force beschreibt die Ausschreibung von Änderungen vor Abschluss Commit. Änderungen werden zum Transaktionsende auf den Hintergrundspeicher geschrieben.

Mit noforce besteht kein Zwang zur Ausschreibung von Änderungen vor Abschluss Commit. Geänderte Seiten können im Puffer verbleiben.

Wie wirken sich Ersetzungs- und Ausschreibungsstrategie jetzt auf die Recovery-Maßnahmen aus? Das Log-Granulat muss kleiner oder gleich dem Sperrgranulat sein (force/steal: Undo-Recovery, kein Redo-Recovery; force/nosteal: nicht möglich; noforce/steal: Undo-Recovery, Redo-Recovery; noforce/nosteal: kein Undo-Recovery, Redo-Recovery).

Zum Menü Wirtschaftsinformatik | Zum Seitenanfang

Verteilte Transaktionen

Beteiligte bei verteilten Transaktionen

Verteilte Transaktionen sind Transaktionen, die mehr als eine Ressource umfassen. Beteiligte sind das Anwendungsprogramm, der Transaktionsmanager und der Ressource-Manager.

Das Anwendungsprogramm nutzt die Ressourcen vom Ressource-Manager und legt die Transaktionsgrenzen mittels TX-Schnittstelle fest. Transaktionsmanager und Ressource-Manager tauschen Informationen über die XA-Schnittstelle aus. Typische Ressource-Manager sind Datenbank- oder Messaging-Systeme.

Zwei-Phasen-Commit-Protokoll

Das ACID-Prinzip muss wie bei nicht verteilten Transaktionen gewahrt werden. Insbesondere müssen für die Atomarität alle Ressource-Manager entweder die Transaktion erfolgreich beenden oder alle ihre Änderungen rückgängig machen. Dafür ist ein spezielles Protokoll erforderlich, das sogenannte Zwei-Phasen-Commit-Protokoll, das die beteiligten Ressource-Manager steuert.

Dieses Protokoll muss insbesondere mit Systemfehlern umgehen: Kommunikationsfehler, wenn die beteiligten Ressource-Manager auf verschiedenen Servern laufen, die über ein Netzwerk miteinander verbunden sind. Transaktionsmanager stürzt ab, Ressource-Manager stürzt ab. Der Wiederherstellungsprozess muss die notwendigen Aktionen zur Sicherstellung der Atomarität durchführen.

Spezifikationen

Grundlage bildet das Distributed-Transaction-Processing-Modell. Die TX-Spezifikation beschreibt die Schnittstelle zwischen dem Anwendungsprogramm und dem Transaktionsmanager. Das Anwendungsprogramm steuert die Transaktion durch Anweisungen zum Starten (bot), erfolgreichen Beenden (commit) und Abbruch (rollback). Die XA-Spezifikation beschreibt die Schnittstelle zwischen dem Transaktionsmanager und den Ressource-Manager und stellt Funktionen zur Abbildung des Zwei-Phasen-Commit-Protokolls bereit. Mit Funktionen dieser Schnittstelle können Operationen im Ressource-Manager mit einer Transaktion assoziiert werden.

Das Zwei-Phasen-Commit-Protokoll funktioniert nach dem Alles-oder-Nichts-Prinzip. Entweder alle Beteiligte bestätigen oder alles wird abgebrochen. Ein Beispiel: Der Transaktionsmanager fragt den Ressource-Manager, ob er bereit ist. Dieser bejaht. Daraufhin fragt der Transaktionsmanager auch den zweiten Ressource-Manager. Dieser sendet jedoch eine Negativ-Bestätigung, er ist nicht bereit. Also sagt der Transaktionsmanager dem ersten Ressource-Manager, dass die Transaktion abgebrochen werden muss und dieser alles wegschmeißen soll, was er bisher erhalten hat.

Zustandsübergänge

Im Ressource-Manager gibt es folgende Zustandsübergänge. executing: Ressource-Manager führt Operationen durch, z.B. Änderungen an Daten. Bei Fehler kann sofort in den aborting/aborted-Zustand gewechselt werden. Nach der prepare-Aufforderung durch den Transaktionsmanager wird bei positivem Ergebnis in den prepared-Zustand gewechselt. Der Ressource-Manager muss auf die Entscheidung durch den Transaktionsmanager warten. prepared: Abhängig von der Entscheidung des Transaktionsmanager wird die Transaktion erfolgreich beendet (commit-Aufforderung) oder es findet ein Rückgängigmachen aller Operationen statt (abort-Aufforderung). aborting/aborted: Transaktion wurde abgebrochen. committing/committed: Transaktion wurde erfolgreich beendet.

Nachfolgend nun die Zustandsübergänge des Transaktionsmanagers. Mit executing startet der Transaktionsmanager die commit-Bearbeitung, sendet eine prepare-Meldung an alle Transaktionsmanager, kann aber die Transaktion auch abbrechen. Dann folgt der Zustand prepared. Der Transaktionsmanager wartet auf Ergebnisse von den Ressource-Managern. Antworten alle Ressource-Manager positiv, geht er in den Zustand committing über. Antwortet nur ein Ressource-Manager negativ, geht er in den aborting-Zustand über. Im aborting / committing-Zustand wartet der Transaktionsmanager auf Bestätigungen. Anschließend wird im aborted / committed-Zustand die Information zur Transaktion in den Programmstrukturen des Transaktionsmanagers gelöscht, da sie komplett abgeschlossen ist.

Praxis

Zum Schluss noch etwas zu der Praxis: Heuristische Entscheidungen. Ressource-Manager haben dem prepare-Aufruf mit vote yes geantwortet und danach stürzt der Transaktionsmanager ab oder kann aus anderen Gründen nicht das Ende der Transaktion einleiten. Alle Sperren müssen im Ressource-Manager gehalten werden. Andere Transaktionen auf diesem Ressource-Manager werden möglicherweise blockiert.

Eine pragmatische Lösung für diesen Fall: Ressource-Manager können von sich aus, d.h. heuristisch, eine Entscheidung zum Ausgang der Transaktion treffen, entweder commit oder abort. Dadurch wird die Atomarität der Transaktion durchbrochen, da der Transaktionsmanager möglicherweise eine andere Entscheidung zum Ausgang getroffen hat. In diesem Fall muss ggf. manuell wieder ein konsistenter Gesamtzustand des Systems hergestellt werden.

Zum Menü Wirtschaftsinformatik | Zum Seitenanfang

Transaktionen in Java

Unterscheidungen in Java

Java unterscheidet lokale und globale Transaktionen. Lokale Transaktionen behandeln den nicht verteilten Fall und werden in JDBC komplett über die Schnittstelle Connection abgebildet. Globale Transaktionen entsprechen verteilten Transaktionen und werden über das Java Transaction API gesteuert. Dieses stellt Schnittstellen und Klassen zur Verfügung, die das Zwei-Phasen-Commit-Protokoll realisieren. JDBC-Verbindungen können sowohl innerhalb lokaler als auch globaler Transaktionen verwendet werden, allerdings immer nur in einer der beiden Transaktionsarten.

Lokale Transaktionen

Lokale Transaktionen arbeiten mit den Methoden zur Transaktionssteuerung der Schnittstelle Connection. Diese stellt Variablen für die verschiedenen Isolationslevel zur Verfügung. Bei Transaktionsstart muss eines dieser Level mit der Methode setTransactionIsolation gesetzt werden. Standardmäßig arbeiten Verbindungen im AutoCommit-Modus, d.h. jede einzelne SQL-Anweisung wird als eigenständige Transaktion betrachtet ohne commit() bzw. rollback() aufzurufen. Transaktionen werden nicht explizit gestartet. Der Start erfolgt implizit durch die erste SQL-Anweisung bzw. durch die erste SQL-Anweisung nach Aufruf von commit() bzw. rollback().

Ausführung einer lokalen Transaktion: Als erstes der Versuch (try). Dazu AutoCommit ausschalten, damit mehrere SQL-Anweisungen zu einer Transaktion zusammengefasst werden können (connection.setAutoCommit(false);). Ggf. SQL-Konsistenzstufe setzen (connection. setTransactionIsolation(...);). Datenbankoperationen ausführen (Statement statement = connection.createStatement(); statement.executeUpdate(...); ... statement.executeUpdate(...); ...) und Transaktion erfolgreich beenden (connection.commit();). Alles andere abfangen mit Ausnahmeregelungen (catch). Verbindung zurückrollen. Und abschließend Ressourcen freigeben.

Savepoints sind eine Markierung von Arbeitszuständen in einer Transaktion auf die zurückgesetzt werden kann, ohne die Transaktion zu beenden. Bei längeren Transaktionen wirklich empfehlenswert.

Globale Transaktionen

In den folgenden Abschnitten werden die für globale Transaktionen relevanten Schnittstellen vorgestellt. Pro Thread kann immer nur eine Transaktion existieren bzw. aktiv sein (Thread-Bindung von Transaktionen). Transaktionen werden in ThreadLocal-Variablen gespeichert. Der Transaktionsmanager bezieht seine Transaktion über den Thread, in dem er aufgerufen wird.

Die Schnittstelle TransactionManager dient zur programmtechnischen Steuerung von Transaktionen und verwaltet alle Transaktionen. void begin() erzeugt eine neue Transaktion und verbindet sie mit dem aktuellen Thread. void commit() schließt die mit dem Thread verbundene Transaktion positiv ab und löst die Verbindung zu diesem. rollback() schließt die mit dem Thread verbundene Transaktion negativ ab und löst die Verbindung zu diesem. Transaction getTransaction() liefert das Transaktionsobjekt, das mit dem aktuellen Thread verbunden ist. Die Schnittstelle UserTransaction ist eine vereinfachte Form von TransactionManager, die z.B. durch Applikations-Server für die programmtechnische Steuerung von Transaktionen bereitgestellt wird.

Die Schnittstelle Transaction beschreibt das Transaktionsobjekt, das pro Thread nur einmal existieren kann. boolean enlistResource(XAResource xaRes) registriert die Ressource in der Transaktion. Damit arbeitet die Ressource im Kontext der Transaktion. boolean delistResource(XAResource xaRes, int flag) entfernt die Registrierung der Ressource aus der Transaktion. void commit() schreibt Änderungen fest und schließt die Transaktion ab. void rollback() macht Änderungen rückgängig und schließt die Transaktion ab. void registerSynchronization(Synchronization sync) registriert ein Synchronisationsobjekt, das vor und nach der Abschlussphase der Transaktion informiert wird (callback). Damit können Aktionen wie z.B. Zurückschreiben eines Objektzustandes in die Datenbank (flushing) vor Abschluss der Transaktion angestoßen werden.

Die Schnittstelle XADataSource ist eine DataSource, die die XA-Spezifikation unterstützt und damit in verteilten Transaktionen verwendet werden kann. Sie ist eine Fabrik für XAConnection-Objekte. XAConnection getXAConnection(String user, String password) liefert eine XAConnection. Objekte zu Klassen, die diese XAConnection-Schnittstelle implementieren, nehmen an verteilten Transaktionen teil. Zu jeder XAConnection gehört eine XAResource, die das Zwei-Phasen-Commit-Protokoll steuert. XAResource getXAResource() liefert die XAResource zur Transaktionensteuerung. void addConnectionEventListener(ConnectionEventListener listener) registriert ein Callback-Objekt, das bei Schließen der Verbindung die Zuordnung der Ressource zur Transaktion aufhebt. Damit arbeitet diese Verbindung nicht mehr im Kontext einer Transaktion und kann in den Connection-Pool zurückgegeben werden. void removeConnectionEventListener(ConnectionEventListener listener) hebt die Registrierung des Callback-Objekts auf.

Objekte zu Klassen, die die Schnittstelle Xid implementieren, sind Transaktions-Identifizierer. Damit werden Datenbankaktionen im Datenbankprotokoll gekennzeichnet um die Wiederherstellung (undo / redo) zu ermöglichen. Xids sind strukturiert aufgebaut. byte[ ] getGlobalTransactionId() ist der globale Anteil des Transaktions-Identifizierers, der für alle beteiligten Ressourcen in einer verteilten Transaktion gleich ist. byte[ ] getBranchQualifier() ist der lokale Anteil des Transaktions-Identifizierers, der innerhalb einer Ressource eindeutig sein muss. int getFormatId() ist die Kennzeichnung des Transaktionsmanagers, damit Transaktions-Identifizierer verschiedener Transaktionsmanager nicht zufälligerweise als gleich betrachtet werden.

Die Schnittstelle XAResource ist die Java-Abstraktion einer XA-Ressource entsprechend der XA-Spezifikation. Nach Aufruf der Methode void start(Xid xid, int flags) arbeitet die Ressource im Kontext der mit xid gekennzeichneten Transaktion. Mit der Methode void end(Xid xid, int flags) wird der Bezug zur Transaktion aufgehoben. Mit der Methode int prepare(Xid xid) wird die Ressource im Rahmen des Zwei-Phasen-Commit-Protokolls aufgefordert, sich auf den Abschluss der Transaktion vorzubereiten. Das Festschreiben der Änderungen erfolgt über void commit(Xid xid, boolean onePhase). Ein Rückgängigmachen der Änderungen ist mit void rollback(Xid xid) möglich.

Objekte zu Klassen, die die Schnittstelle Synchronization implementieren, dienen als Callback, um notwendige Aktionen vor Transaktionsabschluss durchführen zu können. void beforeCompletion() wird vor prepare aufgerufen. Ausnahmen und Fehler in dieser Methode führen zum Abbruch (rollback) der Transaktion. void afterCompletion(int status) wird nach kompletter Durchführung der Transaktion aufgerufen, hat keinen Einfluss mehr auf das Transaktionsergebnis und kann z.B. dazu genutzt werden, die programminternen Datenstrukturen mit der Datenbank abzugleichen.