ABAP COMMIT WORK et ROLLBACK WORK : Contrôle des transactions

Catégorie
ABAP-Statements
Publié
Auteur
Johannes

Les instructions COMMIT WORK et ROLLBACK WORK sont centrales pour le contrôle des transactions en ABAP. Elles déterminent si les modifications de base de données sont sauvegardées de manière permanente ou annulées.

Concept de base : Logical Unit of Work (LUW)

En ABAP, les modifications de base de données ne sont pas immédiatement sauvegardées de manière permanente. Au lieu de cela, elles sont collectées dans un tampon de transaction jusqu’à ce qu’une décision explicite soit prise :

  • COMMIT WORK : Toutes les modifications sont sauvegardées de manière permanente dans la base de données.
  • ROLLBACK WORK : Toutes les modifications depuis le dernier COMMIT sont annulées.

Une Logical Unit of Work (LUW) est l’ensemble de toutes les opérations de base de données entre deux points COMMIT. La LUW garantit que soit toutes les modifications sont sauvegardées, soit aucune (atomicité).

COMMIT WORK – Sauvegarder les modifications

Syntaxe

COMMIT WORK [AND WAIT].

Fonctionnement

  1. Toutes les modifications de base de données en tampon sont écrites dans la base de données.
  2. Tous les modules fonction UPDATE enregistrés sont exécutés.
  3. Le tampon de transaction est vidé.
  4. Une nouvelle LUW commence.

Variantes

VarianteDescription
COMMIT WORKCommit asynchrone. Le programme continue immédiatement.
COMMIT WORK AND WAITCommit synchrone. Le programme attend que toutes les modifications soient terminées.

Exemple

DATA: ls_customer TYPE zcustomer.
ls_customer-id = '1001'.
ls_customer-name = 'Nouvelle Société SARL'.
ls_customer-city = 'Paris'.
" Insérer l'enregistrement (pas encore permanent)
INSERT INTO zcustomer VALUES @ls_customer.
IF sy-subrc = 0.
" Sauvegarder les modifications de manière permanente
COMMIT WORK AND WAIT.
IF sy-subrc = 0.
WRITE: / 'Client créé et sauvegardé avec succès.'.
ELSE.
WRITE: / 'Erreur lors de la sauvegarde.'.
ENDIF.
ELSE.
" En cas d'erreur : Annuler les modifications
ROLLBACK WORK.
WRITE: / 'Le client n a pas pu être créé.'.
ENDIF.

ROLLBACK WORK – Annuler les modifications

Syntaxe

ROLLBACK WORK.

Fonctionnement

  1. Toutes les modifications de base de données en tampon sont annulées.
  2. Tous les modules fonction UPDATE enregistrés ne sont pas exécutés.
  3. Le tampon de transaction est vidé.
  4. Une nouvelle LUW commence.

Exemple

DATA: lt_orders TYPE TABLE OF zorder.
" Effectuer plusieurs opérations
INSERT zorder FROM TABLE @lt_orders.
UPDATE zcustomer SET last_order = @sy-datum
WHERE id = '1001'.
" Vérification des erreurs
IF sy-subrc <> 0.
" En cas d'erreur : Annuler TOUTES les modifications
ROLLBACK WORK.
WRITE: / 'Transaction annulée.'.
RETURN.
ENDIF.
" Tout OK : Sauvegarder
COMMIT WORK.

Champs système

Après COMMIT WORK :

  • sy-subrc :
    • 0 : Commit réussi (avec AND WAIT).
    • Pour un commit asynchrone sans AND WAIT, sy-subrc est toujours 0.

Après ROLLBACK WORK :

  • Aucun champ système pertinent n’est défini.

LUW Base de données vs. LUW SAP

LUW Base de données

La LUW base de données comprend toutes les opérations directes de base de données (INSERT, UPDATE, DELETE, SELECT) entre deux points COMMIT.

" LUW Base de données 1 commence
INSERT zcustomer FROM @ls_customer1.
UPDATE zproduct SET price = 100 WHERE id = 'P001'.
COMMIT WORK. " LUW Base de données 1 termine
" LUW Base de données 2 commence
DELETE FROM zlog WHERE created < '20240101'.
COMMIT WORK. " LUW Base de données 2 termine

LUW SAP (Logical Unit of Work)

La LUW SAP est un concept étendu qui inclut également les modules fonction UPDATE et la mise à jour. Elle permet de regrouper les modifications de base de données et de ne les exécuter qu’à la fin d’une transaction métier.

" Enregistrer les modifications (pas encore de modification DB)
CALL FUNCTION 'Z_UPDATE_CUSTOMER' IN UPDATE TASK
EXPORTING
customer = ls_customer.
CALL FUNCTION 'Z_UPDATE_ORDER' IN UPDATE TASK
EXPORTING
order = ls_order.
" Maintenant toutes les fonctions enregistrées sont exécutées
COMMIT WORK.

UPDATE TASK – Mise à jour

Avec IN UPDATE TASK, les modules fonction peuvent être enregistrés pour la mise à jour asynchrone :

Module fonction pour la mise à jour

FUNCTION z_update_customer.
*"----------------------------------------------------------------------
*" IMPORTING
*" VALUE(customer) TYPE zcustomer
*"----------------------------------------------------------------------
" Ce code est exécuté lors du COMMIT WORK
MODIFY zcustomer FROM customer.
ENDFUNCTION.

Appel dans le programme principal

DATA: ls_customer TYPE zcustomer.
ls_customer-id = '1001'.
ls_customer-name = 'Société modifiée'.
" Enregistrer la fonction de mise à jour
CALL FUNCTION 'Z_UPDATE_CUSTOMER' IN UPDATE TASK
EXPORTING
customer = ls_customer.
" Logique supplémentaire...
" À la fin : Exécuter toutes les mises à jour
COMMIT WORK AND WAIT.

Avantages de la mise à jour

  1. Regroupement : Toutes les modifications sont exécutées ensemble.
  2. Gestion des erreurs : En cas d’erreur, toute la LUW est annulée.
  3. Performance : L’exécution asynchrone décharge le dialogue.

COMMIT implicite

Un COMMIT WORK est exécuté automatiquement lors de :

  • Fin d’une étape de dialogue (action utilisateur comme ENTER, touche F)
  • Appel d’une transaction (CALL TRANSACTION, LEAVE TO TRANSACTION)
  • Appel d’un module fonction RFC
  • Envoi d’un message de type A (Abandon) ou X (Exit)

Attention : Cela peut provoquer des commits non intentionnels !

" ATTENTION : Commit implicite !
INSERT zcustomer FROM @ls_customer.
" Cet appel exécute un COMMIT implicite
CALL TRANSACTION 'VA01'.
" La modification INSERT est maintenant déjà commitée !
" Un ROLLBACK WORK ici n'aurait plus d'effet.

ROLLBACK implicite

Un ROLLBACK WORK est exécuté automatiquement lors de :

  • Erreur d’exécution (Dump)
  • Message de type A (dans certains contextes)
  • Abandon de programme

Bonnes pratiques pour les transactions

1. Gestion des erreurs avec ROLLBACK

DATA: lv_error TYPE abap_bool VALUE abap_false.
" Opération 1
INSERT zcustomer FROM @ls_customer.
IF sy-subrc <> 0.
lv_error = abap_true.
ENDIF.
" Opération 2
IF 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.
" Décision
IF lv_error = abap_false.
COMMIT WORK AND WAIT.
WRITE: / 'Transaction réussie.'.
ELSE.
ROLLBACK WORK.
WRITE: / 'Transaction échouée.'.
ENDIF.

2. TRY-CATCH avec 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: / 'Erreur lors de l insertion.'.
CATCH cx_root INTO DATA(lx_error).
ROLLBACK WORK.
WRITE: / 'Erreur inattendue:', lx_error->get_text( ).
ENDTRY.

3. Verrous avant modifications

" Demander le verrou
CALL FUNCTION 'ENQUEUE_EZCUSTOMER"
EXPORTING
id = ls_customer-id
EXCEPTIONS
foreign_lock = 1
OTHERS = 2.
IF sy-subrc <> 0.
WRITE: / 'L enregistrement est verrouillé.'.
RETURN.
ENDIF.
" Effectuer les modifications
UPDATE zcustomer FROM @ls_customer.
" Commit
COMMIT WORK AND WAIT.
" Libérer le verrou
CALL FUNCTION 'DEQUEUE_EZCUSTOMER"
EXPORTING
id = ls_customer-id.

COMMIT WORK vs. COMMIT WORK AND WAIT

AspectCOMMIT WORKCOMMIT WORK AND WAIT
ExécutionAsynchroneSynchrone
Temps d’attenteAucunAttend la fin
sy-subrcToujours 0Indique succès/échec
UtilisationArrière-plan, si résultat non critiqueDialogue, si résultat doit être vérifié
" Asynchrone : Plus rapide, mais pas de feedback
COMMIT WORK.
" Synchrone : Plus lent, mais avec vérification d'erreur
COMMIT WORK AND WAIT.
IF sy-subrc <> 0.
" Gestion des erreurs
ENDIF.

Erreurs fréquentes

1. COMMIT oublié

" FAUX : Pas de COMMIT
INSERT zcustomer FROM @ls_customer.
" La modification est perdue à la fin du programme !
" CORRECT :
INSERT zcustomer FROM @ls_customer.
COMMIT WORK.

2. COMMIT dans une boucle

" MAUVAIS : COMMIT à chaque itération
LOOP AT lt_customers INTO DATA(ls_cust).
INSERT zcustomer FROM @ls_cust.
COMMIT WORK. " Très inefficace !
ENDLOOP.
" MIEUX : Un seul COMMIT à la fin
INSERT zcustomer FROM TABLE @lt_customers.
COMMIT WORK.

3. COMMIT implicite ignoré

INSERT zcustomer FROM @ls_customer.
" ATTENTION : RFC provoque un COMMIT implicite !
CALL FUNCTION 'Z_REMOTE_FUNCTION' DESTINATION 'RFC_DEST'.
" ROLLBACK ici est sans effet - les données sont déjà commitées
ROLLBACK WORK.

Résumé

InstructionEffet
COMMIT WORKSauvegarde toutes les modifications de manière asynchrone
COMMIT WORK AND WAITSauvegarde toutes les modifications de manière synchrone (avec feedback)
ROLLBACK WORKAnnule toutes les modifications depuis le dernier COMMIT

Notes importantes / Bonnes pratiques

  • Exécutez COMMIT WORK uniquement aux limites logiques de transaction, pas après chaque opération individuelle.
  • Utilisez COMMIT WORK AND WAIT lorsque vous devez vérifier le résultat.
  • Implémentez une gestion des erreurs cohérente avec ROLLBACK WORK.
  • Tenez compte des COMMITs implicites lors des appels de transaction et RFC.
  • Utilisez les verrous SAP pour éviter les conflits de données lors des accès parallèles.
  • Testez les transactions critiques d’abord avec ROLLBACK WORK à la fin.
  • Dans les modules fonction de mise à jour (IN UPDATE TASK), n’utilisez jamais COMMIT WORK ou ROLLBACK WORK.
  • Utilisez INSERT, UPDATE, DELETE pour les modifications réelles de base de données.