Möchtest Du den gesamten Artikel lesen? Und vielleicht sogar den Artikel im PDF-Format und die Beispieldateien herunterladen? Dann hole Dir den Artikel gleich hier - völlig kostenlos!
Transaktionen im Kontext von Datenbankanwendungen sind mehrere SQL-Anweisungen zum Ändern, Löschen oder Hinzufügen von Daten, die entweder alle oder gar nicht ausgeführt werden. Wir markieren den Start einer solchen Transaktion durch eine bestimmte Methode, führen dann eine oder mehrere SQL-Anweisungen aus und entscheiden dann, ob die Transaktion abgebrochen oder abgeschlossen werden soll. Wenn die Transaktion abgebrochen wird, werden alle seit Beginn der Transaktion in ihrem Kontext durchgeführten Änderungen rückgängig gemacht. In diesem Artikel sehen wir uns an, wie wir solche Transaktionen mit der Execute-Methode von ADODB umsetzen können.
Methoden zum Steuern von Transaktionen
Zum Durchführen von Transaktionen bietet die Connection-Klasse der ADODB-Bibliothek die folgenden Methoden an:
- BeginTrans: Startet eine Transaktion, um mehrere Operationen als Einheit auszuführen.
- CommitTrans: Bestätigt eine laufende Transaktion und speichert die Änderungen dauerhaft in der Datenbank.
- RollbackTrans: Bricht eine Transaktion ab und stellt die Daten vor der Transaktion wieder her.
Beispiel für eine Transaktion
In einem einfachen Beispiel haben wir eine Tabelle namens tblKonten angelegt, die wir wie in Bild 1 im SQL Server entworfen haben.
Bild 1: Die Tabelle tblKonten im SQL Server
Hier finden wir die Felder KontoID (Primärschlüsselfeld der Tabelle), Kontostand (Datentyp money, speichert den aktuellen Kontostand und darf in diesem Fall nicht kleiner als 0 werden) und Bezeichnung (nvarchar(255), speichert eine Bezeichnung für das Konto).
Die Tabelle kannst Du mit der folgenden T-SQL-Anweisung in einer SQL Server-Datenbank anlegen:
CREATE TABLE dbo.tblKonten ( KontoID INT IDENTITY(1,1) PRIMARY KEY, Kontostand MONEY NOT NULL DEFAULT 0 CHECK (Kontostand >= 0), Bezeichnung NVARCHAR(255) NULL);
Der besseren Übersichtlichkeit halber haben wir der Beispieldatenbank eine Tabellenverknüpfung auf diese Tabelle hinzufügt. Die Transaktion wollen wir jedoch nicht auf Basis der Tabellenverknüpfungen durchführen (was auch möglich wäre), sondern auf Basis der SQL Server-Tabellen über eine entsprechende Connection.
Dazu starten wir in der Prozedur aus Listing 1 mit dem Deklarieren eines Connection-Objekts namens cnn. Danach öffnen wir die Verbindung mit der Open-Methode.
Public Sub TransaktionBank() Dim cnn As ADODB.Connection Set cnn = New ADODB.Connection cnn.ConnectionString = "Provider=MSOLEDBSQL;Data Source=amvDesktop2023;" _ & "Initial Catalog=Transaktionen;Integrated Security=SSPI;" cnn.Open cnn.BeginTrans On Error GoTo Fehler ''1 Geld von Konto A abbuchen cnn.Execute "UPDATE tblKonten SET Kontostand = Kontostand - 100 WHERE KontoID = 1" ''2 Geld auf Konto B gutschreiben cnn.Execute "UPDATE tblKonten SET Kontostand = Kontostand + 100 WHERE KontoID = 2" On Error GoTo 0 cnn.CommitTrans MsgBox "Überweisung erfolgreich!", vbInformation Exit Sub Fehler: cnn.RollbackTrans MsgBox "Fehler aufgetreten - Überweisung wurde storniert!", vbCritical End Sub
Listing 1: Diese Prozedur führt eine einfache Transaktion durch.
Anschließend starten wir bereits die Transaktion mit der Methode BeginTrans des Connection-Objekts. Diese Methode hat keine Parameter. Die einzige Eigenschaft, die sie hat, ist das Objekt, in dessen Kontext sie aufgerufen wird – sie bezieht sich nun auf die Verbindung aus cnn.
Danach wollen wir eine Banktransaktion ausführen, die sich vereinfacht aus dem Abbuchen eines bestimmten Betrags von einem Konto und dem Hinzubuchen des gleichen Betrags zu einem anderen Konto zusammensetzt.
Dazu sind zwei UPDATE-Anweisung nötig, mit denen wir die betroffenen Datensätze anpassen.
Dass dabei etwas nicht funktioniert, wollen wir am Auftreten eines Fehlers festmachen.
Dazu deaktivieren wir die eingebaute Fehlerbehandlung und sorgen mit On Error Resume Fehler dafür, dass der Code bei einem Fehler an der Sprungmarke Fehler weiterläuft.
Anschließend führen wir die erste der beiden UPDATE-Anweisungen durch, mit der wir den Kontostand des Kontos mit dem Wert 1 im Feld KontoID um 100 verringern.
Die zweite UPDATE-Anweisung erhöht den Wert des zweiten Kontos um 100.
Da hier bereits ein entsprechender Fehler aufgetreten sein sollte, können wir die eingebaute Fehlerbehandlung mit On Error Goto 0 wieder aktivieren.
Schließlich führen wir mit der CommitTrans-Methode des Connection-Objekts die Transaktion endgültig durch und liefern eine entsprechende Erfolgsmeldung.
Es kann jedoch auch ein Fehler aufgetreten sein. Zu Beispielzwecken haben wir dazu bei der Tabellendefinition angegeben, dass der Wert des Feldes Kontostand niemals kleiner als 0 werden darf.
Wenn wir also eine Überweisung durchführen, die mit der ersten UPDATE-Anweisung dafür sorgt, dass der Kontostand auf dem ersten Konto kleiner wird als 0, löst dies einen Fehler aus und wir landen bei der Sprungmarke Fehler.
Hier wird die Transaktion mit der Methode RollbackTrans komplett rückabgewickelt und es erscheint eine entsprechende Meldung (siehe Bild 2).
Bild 2: Die Tabelle tblKonten nach einem Fehler innerhalb der Transaktion
Das ACID-Prinzip
Transaktionen sollen das Einhalten des ACID-Prinzips sicherstellen. Dieses besteht aus:
- Atomicity (Atomarität): Entweder alle Änderungen oder keine – keine halben Updates.
- Consistency (Konsistenz): Datenbank bleibt immer in einem gültigen Zustand.
- Isolation (Isolation): Eine Transaktion sieht keine halbfertigen Änderungen anderer.
- Durability (Dauerhaftigkeit): Nach CommitTrans sind Änderungen dauerhaft gespeichert.
Was genau geschieht bei der Transaktion, wenn diese fehlschlägt?
- Die Transaktion wird gestartet.
- Die erste UPDATE-Anweisung wird ausgeführt und der Betrag wird vom ersten Konto abgezogen.
- Die Änderung wird nur im Speicher (Buffer Pool) und in der Transaction Log-Datei (LDF) gespeichert – aber noch nicht endgültig in die Datenbank (MDF) geschrieben.
- Die zweite UPDATE-Anweisung schlägt fehl (zum Beispiel, weil das Konto nicht existiert).
- Die Prozedur erkennt den Fehler und führt die RollbackTrans-Methode aus.
- Alle Änderungen seit BeginTrans werden verworfen, und der vorherige Zustand wird aus dem Transaktionsprotokoll (Transaction Log) wiederhergestellt.
Kann ich den aktuellen Zustand während einer Transaktion prüfen?
Wir können den aktuellen Zustand prüfen, aber bei den Standardeinstellungen nur innerhalb der Transaktion – das ist sowohl bezüglich des Zeitraums als auch bezüglich der Verbindung zu sehen.
Wir können also zum Beispiel zwischen die erste und die zweite UPDATE-Anweisung die folgenden Anweisungen einfügen, um die zu diesem Zeitpunkt gültigen Kontostände zu betrachten (das Beispiel enthält nur die beiden Konten, daher müssen wir hier nicht filtern):
Dim rst As ADODB.Recordset Set rst = cnn.Execute("SELECT * FROM tblKonten") Do While Not rst.EOF Debug.Print rst!KontoID, rst!Kontostand rst.MoveNext Loop
Hier sehen wir den bereits reduzierten Kontostand des ersten Kontos und den noch nicht erhöhten Kontostand des zweiten Kontos.
Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...
den kompletten Artikel im PDF-Format mit Beispieldatenbank
diesen und alle anderen Artikel mit dem Jahresabo