Wirtschaftsinformatik: Komplexe Datenbank-Anwendungen
Sie sind hier: Startseite › Wirtschaftsinformatik › Komplexe Datenbank-Anwendungen (Transaktionen)
IC / CM, Kurs vom 01.10.2005 - 31.03.2006
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:
- Atomarität (atomicity: Ausführung aller Aktionen oder keiner),
- Konsistenz (consistency: Überführung der Datenbank von einem konsistenten in einen anderen konsistenten Zustand),
- Isolation (isolation: keine Beeinflussung parallel ablaufender Transaktionen) und
- Dauerhaftigkeit (durability: bestätigte Veränderungen dürfen nicht verloren gehen).
Es gibt verschiedene Mechanismen zur Sicherstellung von ACID:
- die Einbettung von Transaktionen in Anwendungsprogramme (programmtechnische Transaktionssteuerung, Schnittstelle zwischen Anwendungsprogramm und Transaktionsmanager),
- Transaktionssysteme (Transaktionsmanager, Transaktionsmonitore),
- die Steuerung der Nebenläufigkeit (concurrency control, Synchronisation von Zugriffen auf gemeinsame Daten) und
- die Wiederherstellung (recovery, Herstellung eines konsistenten Zustands nach Fehlern)
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).
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.
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.