Lektionen/Datenzugriff

Transaktionen: BeginTrans & CommitTrans

Profi10 Min. Lesezeit

Stell dir eine Überweisung vor: Von Konto A wird abgebucht, auf Konto B gutgeschrieben. Bricht der Vorgang nach dem Abbuchen ab, ist Geld verschwunden. Genau solche zusammenhängenden Änderungen sicherst du mit Transaktionen ab — sie gelten nach dem Prinzip Alles-oder-nichts: Entweder alle Schritte greifen, oder keiner.

Warum Transaktionen?

Ohne Transaktion wird jede Änderung sofort einzeln geschrieben. Kracht dein Code mitten in einer Reihe von Updates, bleibt die Datenbank in einem halbfertigen, inkonsistenten Zustand. Eine Transaktion klammert mehrere Operationen zusammen:

  • BeginTrans – Transaktion starten,
  • CommitTrans – alle Änderungen endgültig bestätigen,
  • Rollback – im Fehlerfall alles zurücknehmen, als wäre nichts geschehen.

Der Workspace in DAO

In DAO laufen Transaktionen über das Workspace-Objekt, nicht direkt über die Datenbank. Den Standard-Workspace holst du dir über DBEngine.Workspaces(0):

Dim ws As DAO.Workspace
Dim db As DAO.Database

Set ws = DBEngine.Workspaces(0)
Set db = ws.Databases(0)      ' oder: Set db = CurrentDb

Wichtig: BeginTrans/CommitTrans/Rollback sind Methoden des Workspace. Die betroffenen Recordsets oder Execute-Aufrufe müssen zu einer Datenbank desselben Workspace gehören, sonst umschließt die Transaktion sie nicht.

Ein vollständiges Beispiel

Hier die klassische Überweisung: zwei zusammenhängende Updates, die nur gemeinsam gelten dürfen. Der On Error-Handler sorgt dafür, dass bei jedem Fehler ein Rollback erfolgt:

Public Sub Ueberweisung(vonKonto As Long, nachKonto As Long, betrag As Currency)
    Dim ws As DAO.Workspace
    Dim db As DAO.Database
    Dim inTrans As Boolean

    Set ws = DBEngine.Workspaces(0)
    Set db = CurrentDb

    On Error GoTo Fehler

    ws.BeginTrans
    inTrans = True

    ' 1. Abbuchen
    db.Execute "UPDATE Konten SET Saldo = Saldo - " & betrag & _
               " WHERE KontoID = " & vonKonto, dbFailOnError

    ' 2. Gutschreiben
    db.Execute "UPDATE Konten SET Saldo = Saldo + " & betrag & _
               " WHERE KontoID = " & nachKonto, dbFailOnError

    ws.CommitTrans            ' beide Schritte gemeinsam bestätigen
    inTrans = False

    Set db = Nothing
    Set ws = Nothing
    Exit Sub

Fehler:
    If inTrans Then ws.Rollback   ' nur zurückrollen, wenn Trans läuft
    Set db = Nothing
    Set ws = Nothing
    MsgBox "Überweisung fehlgeschlagen: " & Err.Description, vbCritical
End Sub

Das dbFailOnError bei Execute ist entscheidend: Ohne diese Option schluckt DAO Fehler bei betroffenen Datensätzen still, dein Handler springt gar nicht an — und der Rollback bleibt aus.

Warum das Flag inTrans?

Ein Rollback ohne laufende Transaktion löst selbst einen Fehler aus. Springt dein Code in den Handler, bevor BeginTrans lief (oder nachdem CommitTrans schon durch ist), darfst du nicht zurückrollen. Das Boolean inTrans merkt sich den Zustand sauber.

Performance-Vorteil bei Massen-Updates

Transaktionen sind nicht nur für die Konsistenz da — sie beschleunigen viele Einzeländerungen oft drastisch. Ohne Transaktion schreibt die Datenbank-Engine nach jeder Änderung auf die Platte. In einer Transaktion sammelt sie die Änderungen und schreibt sie gebündelt beim CommitTrans:

Public Sub PreiseErhoehen()
    Dim ws As DAO.Workspace
    Dim db As DAO.Database
    Dim rs As DAO.Recordset

    Set ws = DBEngine.Workspaces(0)
    Set db = CurrentDb
    Set rs = db.OpenRecordset("Artikel", dbOpenDynaset)

    On Error GoTo Fehler
    ws.BeginTrans

    Do Until rs.EOF
        rs.Edit
        rs!Preis = rs!Preis * 1.05        ' 5 % Aufschlag
        rs.Update
        rs.MoveNext
    Loop

    ws.CommitTrans                        ' alles auf einmal schreiben
    rs.Close
    Set rs = Nothing: Set db = Nothing: Set ws = Nothing
    Exit Sub

Fehler:
    ws.Rollback
    If Not rs Is Nothing Then rs.Close
    MsgBox "Abgebrochen: " & Err.Description
End Sub

Bei zehntausenden Datensätzen kann das den Unterschied zwischen Minuten und Sekunden ausmachen — als Nebeneffekt ist der Vorgang auch noch abbruchsicher.

Hinweise und Grenzen

  • Verschachtelung: Transaktionen lassen sich schachteln (bis zu fünf Ebenen). Ein äußeres Rollback nimmt auch bereits committete innere Transaktionen zurück.
  • Speicher: Alle Änderungen einer offenen Transaktion werden zwischengepuffert. Extrem große Transaktionen (Millionen Zeilen) können den Puffer sprengen — dann in Blöcken committen.
  • Verknüpfte ODBC-Tabellen: Bei per ODBC verknüpften Server-Tabellen greift die DAO-Transaktion nicht immer wie erwartet; dort ist ADO/serverseitige Transaktionssteuerung sicherer.
  • Nicht vergessen abzuschließen: Eine offene Transaktion ohne CommitTrans oder Rollback hält Sperren und wird beim Schließen des Workspace verworfen.
  • DDL: Strukturänderungen (Tabellen anlegen/löschen) sind nicht zuverlässig transaktionsfähig — Transaktionen sind für Datenänderungen (DML) gedacht.

Zusammengefasst

  • Transaktionen bündeln mehrere Änderungen nach dem Alles-oder-nichts-Prinzip und verhindern halbfertige, inkonsistente Zustände.
  • In DAO über den Workspace: ws.BeginTrans, ws.CommitTrans, ws.Rollback — die Datenbank muss zum selben Workspace gehören.
  • Immer mit On Error absichern und im Fehlerfall Rollback; ein inTrans-Flag verhindert einen Rollback ohne laufende Transaktion.
  • Execute mit dbFailOnError verwenden, sonst schlägt der Fehler nicht durch und der Rollback bleibt aus.
  • Für Massen-Updates bringen Transaktionen einen großen Geschwindigkeitsvorteil; Grenzen bei Puffergröße, ODBC-Tabellen und DDL beachten.
Nächste Lektion
Tabellen & Felder per DAO erstellen