Transaktionen verwalten

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Verbindungen zu Datenbanken einrichten - Index


Eine Transaktion besteht aus einer Gruppe von Aktionen, die in einer oder mehreren Datenbanktabellen erfolgreich ausgeführt werden müssen, bevor sie endgültig festgeschrieben (gespeichert) werden. Schlägt eine der Aktionen in der Gruppe fehl, werden alle anderen Aktionen ebenfalls rückgängig gemacht (rolled back). Transaktionen verhindern also, dass die Datenbank in einen inkonsistenten Zustand gerät, wenn ein Problem bei der Durchführung einer der Aktionen auftritt, aus denen sich die Transaktion zusammensetzt.

In einer Finanzanwendung beispielsweise schützen Transaktionen die Überweisung von Geld von einem Konto auf ein anderes. Falls nach der Abbuchung des Betrags von einem Konto ein Fehler auftritt, bevor der Betrag auf dem anderen Konto gutgeschrieben werden konnte, wird die Transaktion rückgängig gemacht, sodass die Datenbank weiterhin die korrekten Kontenstände anzeigt.

Transaktionen können immer direkt verwaltet werden, indem SQL-Befehle direkt an die Datenbank gesendet werden. Die meisten Datenbanken stellen ihre eigenen Transaktionsverwaltungsmodelle bereit. Einige Datenbanken unterstützen jedoch keine Transaktionen. Für Server, die sie unterstützen, sollten Sie Ihre eigene Transaktionsverwaltung direkt programmieren und dazu die Vorteile der komplexen Transaktionsverwaltung auf den jeweiligen Datenbankservern nutzen, wie beispielsweise das Zwischenspeichern von Schemas.

Falls Sie keine der komplexen Transaktionsverwaltungsfunktionen benötigen, bieten Verbindungskomponenten mehrere Methoden und Eigenschaften, die Sie zur Verwaltung von Transaktionen nutzen können, ohne explizit SQL-Befehle zu senden. Diese Eigenschaften und Methoden verschaffen Ihnen den Vorteil, dass Sie Ihre Anwendung nicht für jeden verwendeten Datenbankservertyp anpassen müssen, so lange dieser Server Transaktionen unterstützt. (Die BDE bietet ebenfalls eine begrenzte Transaktionsunterstützung für lokale Tabellen ohne Server-Transaktionsunterstützung. Wenn Sie die BDE nicht verwenden, aber versuchen, Transaktionen für eine Datenbank auszuführen, die diese nicht unterstützt, lösen Verbindungskomponenten eine Exception aus.)

Warnung: Wenn eine Datenmengen-Provider-Komponente Aktualisierungen vornimmt, erzeugt sie für diese implizit Transaktionen. Beachten Sie, dass Transaktionen, die Sie explizit starten, keinen Konflikt mit den vom Provider erzeugten Transaktionen verursachen.

Eine Transaktion starten

Wenn Sie eine Transaktion starten, werden alle nachfolgenden Anweisungen, die lesend oder schreibend auf die Datenbank zugreifen, im Kontext dieser Transaktion ausgeführt, bis diese explizit beendet oder (wie es bei überlappenden Transaktionen der Fall ist) eine neue Transaktion gestartet wird. Die einzelnen Anweisungen werden als Teil einer Gruppe betrachtet. Die Änderungen müssen erfolgreich in der Datenbank festgeschrieben werden oder alle innerhalb der Gruppe vorgenommenen Änderungen müssen rückgängig gemacht werden.

Während einer Transaktion ist Ihre Sicht auf die Daten in der Datenbanktabelle von Ihrer Transaktions-Isolationsstufe abhängig.

Für TADOConnection starten Sie eine Transaktion, indem Sie die Methode BeginTrans aufrufen:

 Level := ADOConnection1.BeginTrans;

BeginTrans gibt die Verschachtelungsebene für die gestartete Transaktion zurück. Eine verschachtelte Transaktion ist Teil einer anderen, übergeordneten Transaktion. Nachdem der Server die Transaktion gestartet hat, empfängt die ADO-Verbindung das Ereignis OnBeginTransComplete.

Für TDatabase verwenden Sie stattdessen die Methode StartTransaction. TDataBase unterstützt keine verschachtelten oder überlappenden Transaktionen: Wenn Sie die Methode StartTransaction einer TDatabase-Komponente aufrufen, während eine andere Transaktion läuft, löst sie eine Exception aus. Um zu vermeiden, dass die Methode StartTransaction aufgerufen wird, aktivieren Sie die Eigenschaft InTransaction:

 if not Database1.InTransaction then
   Database1.StartTransaction;

TSQLConnection verwendet ebenfalls die Methode StartTransaction, aber in einer Version, die eine bessere Kontrolle gewährt. Insbesondere verwendet StartTransaction einen Transaktionsdeskriptor, der Ihnen ermöglicht, mehrere gleichzeitig stattfindende Transaktionen zu verwalten und die Transaktions-Isolationsstufe für einzelne Transaktionen anzugeben. Um mehrere gleichzeitig stattfindende Transaktionen verwalten zu können, setzen Sie das TransactionID-Feld des Transaktionsdeskriptors auf einen eindeutigen Wert. TransactionID kann einen beliebigen von Ihnen gewählten Wert annehmen, der jedoch eindeutig sein muss (und keinen Konflikt mit anderen momentan ausgeführten Transaktionen verursachen darf). Abhängig vom Server können die von TSQLConnection gestarteten Transaktionen verschachtelt (wie beispielsweise bei Verwendung von ADO) oder überlappend sein.

 var
   TD: TTransactionDesc;
 begin
   TD.TransactionID := 1;
   TD.IsolationLevel := xilREADCOMMITTED;
   SQLConnection1.StartTransaction(TD);

Bei überlappenden Transaktionen wird standardmäßig die erste Transaktion deaktiviert, sobald die zweite Transaktion gestartet wird, obwohl Sie das Festschreiben oder Rückgängigmachen der ersten Transaktion auf später verschieben können. Wenn Sie TSQLConnection in Kombination mit einer InterBase-Datenbank einsetzen, können Sie jede Datenmenge in Ihrer Anwendung mit einer bestimmten aktiven Transaktion identifizieren, indem Sie ihre Eigenschaft IsolationLevel setzen. Nachdem Sie also eine zweite Transaktion gestartet haben, können Sie mit beiden Transaktionen gleichzeitig weiterarbeiten, indem Sie einer Datenmenge einfach die gewünschte Transaktion zuordnen.

Hinweis: Anders als TADOConnection, empfangen TSQLConnection und TDatabase keine Ereignisse, wenn die Transaktion gestartet wird.

InterBase Express bietet Ihnen noch mehr Kontrolle als TSQLConnection, indem es eine separate Transaktionskomponente verwendet, statt Transaktionen mithilfe der Verbindungskomponente zu starten. Sie können jedoch TIBDatabase verwenden, um eine Standardtransaktion zu starten:

 if not IBDatabase1.DefaultTransaction.InTransaction then
   IBDatabase1.DefaultTransaction.StartTransaction;

Überlappende Transaktionen werden mithilfe von zwei separaten Transaktionskomponenten realisiert. Jede Transaktionskomponente hat mehrere Parameter, mit deren Hilfe Sie die Transaktion konfigurieren. Sie ermöglichen es Ihnen, die Isolationsstufe für die Transaktion anzugeben sowie verschiedene andere Eigenschaften der Transaktion.

Eine Transaktion beenden

Im Idealfall sollte eine Transaktion nur so lange wie nötig dauern. Je länger eine Transaktion aktiv ist, je mehr Benutzer gleichzeitig auf die Datenbank zugreifen und je mehr nebenläufige, gleichzeitige Transaktionen während der Dauer Ihrer Transaktion gestartet und beendet werden, desto wahrscheinlicher ist es, dass Ihre Transaktion einen Konflikt mit einer anderen Transaktion verursacht, wenn Sie versuchen, Änderungen festzuschreiben.

Nachdem alle Aktionen erfolgt sind, aus denen sich die Transaktion zusammensetzt, machen Sie die Änderungen in der Datenbank permanent, indem Sie die Transaktion festschreiben. Für TDatabase schreiben Sie eine Transaktion mithilfe der Methode Commit fest:

 MyOracleConnection.Commit;

Für TSQLConnection verwenden Sie ebenfalls die Methode Commit, müssen aber angeben, welche Transaktion Sie festschreiben wollen, indem Sie den Transaktionsdeskriptor bereitstellen, den Sie der Methode StartTransaction übergeben haben:

 MyOracleConnection.Commit(TD);

Für TIBDatabase schreiben Sie das Transaktionsobjekt mithilfe der Methode Commit fest:

 IBDatabase1.DefaultTransaction.Commit;

Für TADOConnection schreiben Sie eine Transaktion mithilfe der Methode CommitTrans fest:

 ADOConnection1.CommitTrans;

Hinweis: Es ist möglich, eine verschachtelte Transaktion so festzuschreiben, dass die Änderungen rückgängig gemacht werden können, falls die übergeordnete Transaktion rückgängig gemacht wird.

Nachdem die Transaktion erfolgreich festgeschrieben wurde, empfängt eine ADO-Verbindungskomponente das Ereignis OnCommitTransComplete. Andere Verbindungskomponenten erhalten keine vergleichbaren Ereignisse.

Ein Aufruf zum Festschreiben der aktuellen Transaktion wird normalerweise innerhalb einer try...except-Anweisung ausgeführt. Falls die Transaktion nicht erfolgreich festgeschrieben werden kann, können Sie auf diese Weise den except-Block ausführen, um den Fehler zu verarbeiten und die Operation später zu wiederholen oder die Transaktion rückgängig zu machen.

Falls während der innerhalb einer Transaktion vorgenommenen Änderungen ein Fehler auftritt, oder während Sie versuchen, die Transaktion festzuschreiben, sollten alle Änderungen verworfen werden, die die Transaktion vorgenommen hat. Das Verwerfen dieser Änderungen wird als Rückgängigmachen (roll back) der Transaktion bezeichnet.

Für TDatabase machen Sie eine Transaktion rückgängig, indem Sie die Methode Rollback aufrufen:

 MyOracleConnection.Rollback;

Für TSQLConnection verwenden Sie ebenfalls die Methode Rollback, müssen aber angeben, welche Transaktion Sie rückgängig machen wollen, indem Sie den Transaktionsdeskriptor bereitstellen, den Sie der Methode StartTransaction übergeben haben:

 MyOracleConnection.Rollback(TD);

Für TIBDatabase machen Sie ein Transaktionsobjekt rückgängig, indem Sie die Methode Rollback aufrufen:

 MyOracleConnection.Rollback(TD);

Für TADOConnection machen Sie eine Transaktion rückgängig, indem Sie die Methode RollbackTrans aufrufen:

 IBDatabase1.DefaultTransaction.Rollback;

Nachdem die Transaktion erfolgreich rückgängig gemacht wurde, erhält eine ADO- Verbindungskomponente das Ereignis OnRollbackTransComplete. Andere Verbindungskomponenten erhalten keine vergleichbaren Ereignisse.

Ein Aufruf zum Rückgängigmachen der aktuellen Transaktion erfolgt normalerweise in

  • Code von Exception-Behandlungsroutinen, falls ein Datenbankfehler nicht behoben werden konnte.
  • Code für Schaltflächen- oder Menüereignisse, wenn beispielsweise ein Benutzer auf die Schaltfläche Abbrechen klickt.

Siehe auch