Dans les volets précédents, nous avons vu ce que sont les transactions, leurs propriétés (ACID), et pourquoi elles sont essentielles pour garantir l'intégrité de nos données.
Passons maintenant à la pratique avec une implémentation des transactions dans trois systèmes de bases de données courants :
- ✅ MySQL
- ✅ PostgreSQL
- ✅ SQL Server
Nous allons également voir comment cela se traduit dans une application Laravel à travers Eloquent ou le Query Builder.
🔄 Rappel : Que fait une transaction ?
Une transaction permet d’exécuter plusieurs opérations comme une seule unité de travail.
Si l’une échoue, toutes les autres sont annulées (rollback). Si tout réussit, elles sont validées (commit).
⚙️ Syntaxe SQL brute pour les transactions
🟢 MySQL & PostgreSQL
1START TRANSACTION;23UPDATE accounts SET balance = balance - 100 WHERE id = 1;4UPDATE accounts SET balance = balance + 100 WHERE id = 2;5COMMIT;1START TRANSACTION;23UPDATE accounts SET balance = balance - 100 WHERE id = 1;4UPDATE accounts SET balance = balance + 100 WHERE id = 2;5COMMIT;
En cas d’erreur : remplacer COMMIT; par ROLLBACK;
✅ Note : Pour PostgreSQL, BEGIN peut aussi être utilisé
🔵 SQL Server (T-SQL)
1BEGIN TRANSACTION;23UPDATE accounts SET balance = balance - 100 WHERE id = 1;4UPDATE accounts SET balance = balance + 100 WHERE id = 2;56COMMIT TRANSACTION;1BEGIN TRANSACTION;23UPDATE accounts SET balance = balance - 100 WHERE id = 1;4UPDATE accounts SET balance = balance + 100 WHERE id = 2;56COMMIT TRANSACTION;
⚠️ Si une erreur survient, exécuter ROLLBACK TRANSACTION;
🧑💻 Équivalent Laravel avec le Query Builder
Exemple : Transférer de l'argent entre deux comptes
1use Illuminate\Support\Facades\DB;23DB::transaction(function () {4 DB::table('accounts')->where('id', 1)->decrement('balance', 100);5 DB::table('accounts')->where('id', 2)->increment('balance', 100);6});1use Illuminate\Support\Facades\DB;23DB::transaction(function () {4 DB::table('accounts')->where('id', 1)->decrement('balance', 100);5 DB::table('accounts')->where('id', 2)->increment('balance', 100);6});
🧠 Laravel gère automatiquement le commit si tout passe et le rollback si une exception est levée.
🧱 Exemple complet avec gestion d’exception
1use Illuminate\Support\Facades\DB;2use Throwable;34try {5 DB::beginTransaction();67 DB::table('accounts')->where('id', 1)->decrement('balance', 100);8 DB::table('accounts')->where('id', 2)->increment('balance', 100);910 DB::commit();11} catch (Throwable $e) {12 DB::rollBack();13 // Log l'erreur ou notifier14 throw $e;15}1use Illuminate\Support\Facades\DB;2use Throwable;34try {5 DB::beginTransaction();67 DB::table('accounts')->where('id', 1)->decrement('balance', 100);8 DB::table('accounts')->where('id', 2)->increment('balance', 100);910 DB::commit();11} catch (Throwable $e) {12 DB::rollBack();13 // Log l'erreur ou notifier14 throw $e;15}
✅ Cette méthode est utile quand on veut gérer les erreurs ou faire du logging personnalisé.
📦 Exemple avec Eloquent
Imaginons deux modèles Account :
1DB::transaction(function () {2 $sender = Account::find(1);3 $receiver = Account::find(2);45 $sender->balance -= 100;6 $receiver->balance += 100;78 $sender->save();9 $receiver->save();10});1DB::transaction(function () {2 $sender = Account::find(1);3 $receiver = Account::find(2);45 $sender->balance -= 100;6 $receiver->balance += 100;78 $sender->save();9 $receiver->save();10});
Eloquent + transactions = 🧠 Puissance + sécurité
💡 Bonnes pratiques à retenir
🔹 Toujours encapsuler plusieurs écritures liées dans une transaction 🔹 Ne pas laisser de logique métier lourde entre begin et commit 🔹 Gérer proprement les exceptions 🔹 Éviter les requêtes longues pour ne pas verrouiller la base trop longtemps 🔹 Tester les rollbacks dans vos tests automatisés
✅ Conclusion
Que vous utilisiez MySQL, PostgreSQL ou SQL Server, les principes sont les mêmes :
- Démarrer la transaction
- Exécuter vos opérations critiques
- Commit si tout passe, rollback sinon
Laravel vous offre une interface propre et expressive pour gérer tout cela en toute sécurité.