Die Anweisungen COMMIT WORK und ROLLBACK WORK sind zentral für die Transaktionssteuerung in ABAP. Sie bestimmen, ob Datenbankänderungen dauerhaft gespeichert oder rückgängig gemacht werden.
Grundkonzept: Logical Unit of Work (LUW)
In ABAP werden Datenbankänderungen nicht sofort permanent gespeichert. Stattdessen werden sie in einem Transaktionspuffer gesammelt, bis explizit entschieden wird:
COMMIT WORK: Alle Änderungen werden dauerhaft in der Datenbank gespeichert.ROLLBACK WORK: Alle Änderungen seit dem letzten COMMIT werden verworfen.
Eine Logical Unit of Work (LUW) ist die Menge aller Datenbankoperationen zwischen zwei COMMIT-Punkten. Die LUW garantiert, dass entweder alle Änderungen gespeichert werden oder keine (Atomarität).
COMMIT WORK – Änderungen speichern
Syntax
COMMIT WORK [AND WAIT].Funktionsweise
- Alle gepufferten Datenbankänderungen werden in die Datenbank geschrieben.
- Alle registrierten UPDATE-Funktionsbausteine werden ausgeführt.
- Der Transaktionspuffer wird geleert.
- Eine neue LUW beginnt.
Varianten
| Variante | Beschreibung |
|---|---|
COMMIT WORK | Asynchroner Commit. Das Programm läuft sofort weiter. |
COMMIT WORK AND WAIT | Synchroner Commit. Das Programm wartet, bis alle Änderungen abgeschlossen sind. |
Beispiel
DATA: ls_customer TYPE zcustomer.
ls_customer-id = '1001'.ls_customer-name = 'Neue Firma GmbH'.ls_customer-city = 'Berlin'.
" Datensatz einfügen (noch nicht permanent)INSERT INTO zcustomer VALUES @ls_customer.
IF sy-subrc = 0. " Änderungen dauerhaft speichern COMMIT WORK AND WAIT.
IF sy-subrc = 0. WRITE: / 'Kunde erfolgreich angelegt und gespeichert.'. ELSE. WRITE: / 'Fehler beim Speichern.'. ENDIF.ELSE. " Bei Fehler: Änderungen verwerfen ROLLBACK WORK. WRITE: / 'Kunde konnte nicht angelegt werden.'.ENDIF.ROLLBACK WORK – Änderungen verwerfen
Syntax
ROLLBACK WORK.Funktionsweise
- Alle gepufferten Datenbankänderungen werden verworfen.
- Alle registrierten UPDATE-Funktionsbausteine werden nicht ausgeführt.
- Der Transaktionspuffer wird geleert.
- Eine neue LUW beginnt.
Beispiel
DATA: lt_orders TYPE TABLE OF zorder.
" Mehrere Operationen durchführenINSERT zorder FROM TABLE @lt_orders.
UPDATE zcustomer SET last_order = @sy-datum WHERE id = '1001'.
" Prüfung auf FehlerIF sy-subrc <> 0. " Bei Fehler: ALLE Änderungen rückgängig machen ROLLBACK WORK. WRITE: / 'Transaktion abgebrochen.'. RETURN.ENDIF.
" Alles OK: SpeichernCOMMIT WORK.Systemfelder
Nach COMMIT WORK:
sy-subrc:0: Commit erfolgreich (beiAND WAIT).- Bei asynchronem Commit ohne
AND WAITistsy-subrcimmer0.
Nach ROLLBACK WORK:
- Keine relevanten Systemfelder werden gesetzt.
Datenbank-LUW vs. SAP-LUW
Datenbank-LUW
Die Datenbank-LUW umfasst alle direkten Datenbankoperationen (INSERT, UPDATE, DELETE, SELECT) zwischen zwei COMMIT-Punkten.
" Datenbank-LUW 1 beginnt
INSERT zcustomer FROM @ls_customer1.UPDATE zproduct SET price = 100 WHERE id = 'P001'.
COMMIT WORK. " Datenbank-LUW 1 endet
" Datenbank-LUW 2 beginnt
DELETE FROM zlog WHERE created < '20240101'.
COMMIT WORK. " Datenbank-LUW 2 endetSAP-LUW (Logical Unit of Work)
Die SAP-LUW ist ein erweitertes Konzept, das auch UPDATE-Funktionsbausteine und Verbuchung einschließt. Sie ermöglicht es, Datenbankänderungen zu bündeln und erst am Ende einer Geschäftstransaktion auszuführen.
" Änderungen registrieren (noch keine DB-Änderung)CALL FUNCTION 'Z_UPDATE_CUSTOMER' IN UPDATE TASK EXPORTING customer = ls_customer.
CALL FUNCTION 'Z_UPDATE_ORDER' IN UPDATE TASK EXPORTING order = ls_order.
" Jetzt werden alle registrierten Funktionen ausgeführtCOMMIT WORK.UPDATE TASK – Verbuchung
Mit IN UPDATE TASK können Funktionsbausteine für die asynchrone Verbuchung registriert werden:
Funktionsbaustein für Verbuchung
FUNCTION z_update_customer.*"----------------------------------------------------------------------*" IMPORTING*" VALUE(customer) TYPE zcustomer*"----------------------------------------------------------------------
" Dieser Code wird beim COMMIT WORK ausgeführt MODIFY zcustomer FROM customer.
ENDFUNCTION.Aufruf im Hauptprogramm
DATA: ls_customer TYPE zcustomer.
ls_customer-id = '1001'.ls_customer-name = 'Geänderte Firma'.
" Verbuchungsfunktion registrierenCALL FUNCTION 'Z_UPDATE_CUSTOMER' IN UPDATE TASK EXPORTING customer = ls_customer.
" Weitere Logik...
" Am Ende: Alle Verbuchungen ausführenCOMMIT WORK AND WAIT.Vorteile der Verbuchung
- Bündelung: Alle Änderungen werden zusammen ausgeführt.
- Fehlerbehandlung: Bei Fehler wird die gesamte LUW zurückgerollt.
- Performance: Asynchrone Ausführung entlastet den Dialog.
Impliziter COMMIT
Ein COMMIT WORK wird automatisch ausgeführt bei:
- Ende eines Dialogschritts (Benutzeraktion wie ENTER, F-Taste)
- Aufruf einer Transaktion (
CALL TRANSACTION,LEAVE TO TRANSACTION) - Aufruf eines RFC-Funktionsbausteins
- Senden einer Nachricht mit Typ
A(Abbruch) oderX(Exit)
Achtung: Dies kann unbeabsichtigte Commits verursachen!
" VORSICHT: Impliziter Commit!INSERT zcustomer FROM @ls_customer.
" Dieser Aufruf führt einen impliziten COMMIT ausCALL TRANSACTION 'VA01'.
" Die INSERT-Änderung ist jetzt bereits committed!" Ein ROLLBACK WORK hier hätte keine Wirkung mehr.Impliziter ROLLBACK
Ein ROLLBACK WORK wird automatisch ausgeführt bei:
- Laufzeitfehler (Dump)
- Nachricht mit Typ
A(in manchen Kontexten) - Programmabbruch
Best Practices für Transaktionen
1. Fehlerbehandlung mit ROLLBACK
DATA: lv_error TYPE abap_bool VALUE abap_false.
" Operation 1INSERT zcustomer FROM @ls_customer.IF sy-subrc <> 0. lv_error = abap_true.ENDIF.
" Operation 2IF lv_error = abap_false. UPDATE zorder SET customer_id = @ls_customer-id WHERE order_id = @lv_order_id. IF sy-subrc <> 0. lv_error = abap_true. ENDIF.ENDIF.
" EntscheidungIF lv_error = abap_false. COMMIT WORK AND WAIT. WRITE: / 'Transaktion erfolgreich.'.ELSE. ROLLBACK WORK. WRITE: / 'Transaktion fehlgeschlagen.'.ENDIF.2. TRY-CATCH mit ROLLBACK
TRY. INSERT zcustomer FROM @ls_customer. IF sy-subrc <> 0. RAISE EXCEPTION TYPE cx_failed_insert. ENDIF.
UPDATE zorder SET status = 'PROCESSED' WHERE customer_id = @ls_customer-id.
COMMIT WORK AND WAIT.
CATCH cx_failed_insert. ROLLBACK WORK. WRITE: / 'Fehler beim Einfügen.'.
CATCH cx_root INTO DATA(lx_error). ROLLBACK WORK. WRITE: / 'Unerwarteter Fehler:', lx_error->get_text( ).ENDTRY.3. Sperren vor Änderungen
" Sperre anfordernCALL FUNCTION 'ENQUEUE_EZCUSTOMER' EXPORTING id = ls_customer-id EXCEPTIONS foreign_lock = 1 OTHERS = 2.
IF sy-subrc <> 0. WRITE: / 'Datensatz ist gesperrt.'. RETURN.ENDIF.
" Änderungen durchführenUPDATE zcustomer FROM @ls_customer.
" CommitCOMMIT WORK AND WAIT.
" Sperre freigebenCALL FUNCTION 'DEQUEUE_EZCUSTOMER' EXPORTING id = ls_customer-id.COMMIT WORK vs. COMMIT WORK AND WAIT
| Aspekt | COMMIT WORK | COMMIT WORK AND WAIT |
|---|---|---|
| Ausführung | Asynchron | Synchron |
| Wartezeit | Keine | Wartet auf Abschluss |
| sy-subrc | Immer 0 | Zeigt Erfolg/Fehler |
| Anwendung | Hintergrund, wenn Ergebnis nicht kritisch | Dialog, wenn Ergebnis geprüft werden muss |
" Asynchron: Schneller, aber kein FeedbackCOMMIT WORK.
" Synchron: Langsamer, aber mit FehlerprüfungCOMMIT WORK AND WAIT.IF sy-subrc <> 0. " FehlerbehandlungENDIF.Häufige Fehler
1. Vergessener COMMIT
" FALSCH: Kein COMMITINSERT zcustomer FROM @ls_customer." Änderung geht verloren bei Programmende!
" RICHTIG:INSERT zcustomer FROM @ls_customer.COMMIT WORK.2. COMMIT in Schleife
" SCHLECHT: COMMIT in jeder IterationLOOP AT lt_customers INTO DATA(ls_cust). INSERT zcustomer FROM @ls_cust. COMMIT WORK. " Sehr ineffizient!ENDLOOP.
" BESSER: Ein COMMIT am EndeINSERT zcustomer FROM TABLE @lt_customers.COMMIT WORK.3. Impliziter COMMIT übersehen
INSERT zcustomer FROM @ls_customer.
" VORSICHT: RFC verursacht impliziten COMMIT!CALL FUNCTION 'Z_REMOTE_FUNCTION' DESTINATION 'RFC_DEST'.
" ROLLBACK hier ist wirkungslos - Daten sind bereits committedROLLBACK WORK.Zusammenfassung
| Anweisung | Wirkung |
|---|---|
COMMIT WORK | Speichert alle Änderungen asynchron |
COMMIT WORK AND WAIT | Speichert alle Änderungen synchron (mit Feedback) |
ROLLBACK WORK | Verwirft alle Änderungen seit letztem COMMIT |
Wichtige Hinweise / Best Practice
- Führen Sie
COMMIT WORKnur an logischen Transaktionsgrenzen aus, nicht nach jeder Einzeloperation. - Verwenden Sie
COMMIT WORK AND WAITwenn Sie das Ergebnis prüfen müssen. - Implementieren Sie eine konsistente Fehlerbehandlung mit
ROLLBACK WORK. - Beachten Sie implizite COMMITs bei Transaktionsaufrufen und RFCs.
- Nutzen Sie SAP-Sperren um Datenkonflikte bei parallelen Zugriffen zu vermeiden.
- Testen Sie kritische Transaktionen zuerst mit
ROLLBACK WORKam Ende. - In Verbuchungsbausteinen (
IN UPDATE TASK) niemalsCOMMIT WORKoderROLLBACK WORKverwenden. - Verwenden Sie
INSERT,UPDATE,DELETEfür die eigentlichen Datenbankänderungen.