Un virement coupé en deux
Cycles Loire paie son fournisseur de pneus : 400 euros passent d'un compte à l'autre. Le programme retire d'abord 400 euros au compte de l'atelier. Juste après, le serveur s'arrête.
L'argent a quitté un compte et n'est jamais arrivé sur l'autre. Une banque ne peut pas se le permettre. Les bases de données ont un outil pour éviter cela.
À la fin de cette leçon
Remarque
Je peux expliquer pourquoi un virement doit se faire en entier ou pas du tout.
Mots clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Transaction | un groupe d'écritures qui réussissent toutes ou aucune | |
| BEGIN | ouvre une transaction | BEGIN; |
| COMMIT | valide toutes les écritures depuis BEGIN | COMMIT; |
| ROLLBACK | annule toutes les écritures depuis BEGIN | ROLLBACK; |
| UPDATE | modifie des lignes existantes | |
| Solde | l'argent présent sur un compte |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Un virement, ce sont deux écritures
Jusqu'ici, vos requêtes lisaient. UPDATE écrit : il change des lignes existantes.
Un virement demande deux UPDATE. Le premier retire l'argent d'un compte. Le second l'ajoute sur l'autre. Si seul le premier passe, l'argent disparaît. Si seul le second passe, l'argent apparaît de nulle part. Les deux cas sont graves.
BEGIN ouvre, COMMIT valide
BEGIN ouvre une transaction. Les écritures qui suivent sont en attente, pas encore définitives.
COMMIT les rend définitives toutes ensemble. Si le serveur s'arrête avant COMMIT, la base les efface au redémarrage. Elle ne garde jamais une transaction à moitié faite.
Essayez : un virement validé
-- Un virement de 400 euros, en une transaction.
BEGIN;
UPDATE comptes SET solde = solde - 400 WHERE id = 1;
UPDATE comptes SET solde = solde + 400 WHERE id = 2;
COMMIT;
SELECT * FROM comptes;
Exemple détaillé : les soldes pas à pas
| Étape | Compte 1 | Compte 2 | Total |
|---|---|---|---|
| Avant BEGIN | 1 200 | 300 | 1 500 |
| Après le débit | 800 | 300 | 1 100 |
| Après le crédit | 800 | 700 | 1 500 |
| Après COMMIT | 800 | 700 | 1 500 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
ROLLBACK annule tout
Parfois, c'est le programme qui voit un problème : un solde trop bas, un compte fermé. Il écrit alors ROLLBACK.
Toutes les écritures depuis BEGIN sont annulées. La base revient exactement à l'état d'avant. Lancez le bloc suivant, puis remplacez ROLLBACK par COMMIT pour voir la différence.
Essayez : un virement annulé
-- Le débit est fait, puis un problème survient.
BEGIN;
UPDATE comptes SET solde = solde - 400 WHERE id = 1;
-- Le programme détecte une erreur : il annule tout depuis BEGIN.
ROLLBACK;
SELECT * FROM comptes;
-- Remplacez ROLLBACK par COMMIT et relancez. Où sont passés les 400 euros ?
Une erreur fréquente
Attention
Beaucoup pensent qu'une erreur au milieu annule tout toute seule. C'est faux sans transaction. Chaque UPDATE est alors gardé dès qu'il est fait. Dès que deux écritures doivent aller ensemble, mettez-les entre BEGIN et COMMIT.
La même règle dans un programme
Dans une application, le code doit aussi respecter le tout ou rien. La règle la plus simple : vérifier avant d'écrire.
Dans la tâche suivante, la fonction virer retire l'argent puis vérifie le solde. C'est trop tard : le débit est déjà fait. Corrigez-la pour qu'un refus ne change rien.