Transactions et verrous

Parcours l'atomicité avec BEGIN/COMMIT/ROLLBACK, le rollback partiel avec SAVEPOINT, AUTOCOMMIT, et les concepts de verrous, niveaux d'isolation et propriétés ACID — le tout avec des schémas et des exemples de code en lecture seule.

Cet article est construit sur des schémas et du code en lecture seule

Les transactions ne prennent vraiment vie que sur un véritable SGBDR où plusieurs utilisateurs accèdent à la base de données en même temps, et la console intégrée au navigateur de ce cours ne peut pas reproduire fidèlement ce comportement.

C'est pourquoi cet article n'a pas d'exercices exécutables — lis les blocs code de chaque section comme des exemples destinés à être exécutés sur un véritable SGBDR (MySQL / PostgreSQL / Oracle, etc.).

Qu'est-ce qu'une transaction — traiter plusieurs instructions SQL comme une seule unité

Une transaction est un moyen de traiter plusieurs instructions SQL comme une seule unité : si elles réussissent toutes, elles sont validées ensemble ; si quelque chose tourne mal au milieu, elles sont toutes annulées ensemble.

C'est essentiel pour tout processus où le succès d'une seule moitié du travail poserait problème — pense aux virements bancaires (un UPDATE pour débiter, un pour créditer), ou à la confirmation d'une commande en ligne (décrémenter le stock, insérer la ligne de commande).

La forme de base est BEGIN; (démarrer) → plusieurs instructions → COMMIT; (confirmer) / ROLLBACK; (annuler).

Les blocs code de cet article utilisent une table account qui représente des comptes bancaires. Les trois colonnes sont account_id, owner (nom du titulaire) et balance. Suppose les données initiales suivantes en lisant.

account_idownerbalance
1Alice1000
2Bob500
3Carol800
4Dave1200

Atomicité — BEGIN ... COMMIT / ROLLBACK

Quand tu fais BEGIN; puis COMMIT;, chaque changement entre ces deux instructions est appliqué ensemble.

Exécute ROLLBACK; à la place et chaque changement après BEGIN; est annulé, remettant la base de données dans son état d'avant le début de la transaction.

Cette propriété « tout ou rien » s'appelle l'atomicité — c'est-à-dire une unité qui ne peut pas être découpée en éléments plus petits.

Quand quelque chose comme une violation de contrainte CHECK se produit au milieu d'une transaction, le geste standard est ROLLBACK; pour tout dérouler en toute sécurité.

L'embranchement COMMIT / ROLLBACK
BEGINessayer les changementsvérifier le résultatCOMMITconfirmer les changementsROLLBACKrevenir au départtout va bienabandon / erreur
Après BEGIN, COMMIT confirme les changements ; ROLLBACK ramène tout à l'état d'avant BEGIN. Même après une violation CHECK, ROLLBACK annule tout en toute sécurité.
-- Virement : Alice -> Bob, 100 (destiné à un véritable SGBDR)
BEGIN;
UPDATE account SET balance = balance - 100 WHERE owner = 'Alice';
UPDATE account SET balance = balance + 100 WHERE owner = 'Bob';
COMMIT;   -- les deux UPDATE sont confirmés au même instant

-- Annulation : on a changé d'avis / quelque chose a mal tourné
BEGIN;
UPDATE account SET balance = balance - 300 WHERE owner = 'Alice';
UPDATE account SET balance = balance + 300 WHERE owner = 'Bob';
ROLLBACK; -- les deux UPDATE sont rejetés ensemble

SAVEPOINT — annuler seulement une partie d'une transaction

SAVEPOINT name; pose un marqueur au milieu d'une transaction, et ROLLBACK TO name; annule alors uniquement jusqu'à ce marqueur.

Les changements faits avant le marqueur restent en place, tu peux donc continuer avec d'autres opérations et faire COMMIT; à la fin.

Un usage typique : un processus en plusieurs étapes comme « confirmer la commande → attribuer les points → décrémenter le stock », où seul le décrément de stock a échoué et tu veux ne réessayer que cette étape. C'est plus fin que de jeter toute la transaction avec ROLLBACK;.

SAVEPOINT et ROLLBACK TO — rollback partiel
BEGINUPDATEAlice -100SAVEPOINT sp1marqueur iciUPDATEBob -100ROLLBACK TO sp1annuler seulement la part de BobCOMMITconfirmer seulement Alice -100annulercontinuer
Plante un marqueur avec SAVEPOINT et annule uniquement les changements après lui avec ROLLBACK TO. Les changements avant le marqueur restent et peuvent être confirmés avec COMMIT à la fin.
-- Annuler uniquement la deuxième mise à jour avec SAVEPOINT (destiné à un véritable SGBDR)
BEGIN;
UPDATE account SET balance = balance - 100 WHERE owner = 'Carol';
SAVEPOINT sp1;
UPDATE account SET balance = balance - 100 WHERE owner = 'Dave';
ROLLBACK TO sp1;   -- annuler seulement Dave (Carol -100 reste)
COMMIT;            -- confirmer seulement Carol -100

AUTOCOMMIT — par défaut, chaque instruction se valide elle-même

Lorsque tu exécutes un UPDATE ou un INSERT autonome sans écrire BEGIN; d'abord, chaque instruction est validée automatiquement de son côté.

Cela s'appelle AUTOCOMMIT — le mode par défaut dans lequel chaque instruction est validée dès qu'elle s'exécute.

Pour valider ou annuler plusieurs instructions comme une seule unité, tu dois démarrer explicitement une transaction avec BEGIN;.

AUTOCOMMIT vs une transaction explicite
Sans BEGIN(AUTOCOMMIT)Avec BEGINtransaction expliciteUPDATEvalidé sur le champUPDATEpas encore validéimpossible d'annulerCOMMIT pour confirmerROLLBACK pour annuler
Sans BEGIN, chaque instruction est validée au moment où elle s'exécute. Avec BEGIN, tout jusqu'au COMMIT devient une seule unité que tu peux annuler d'un bloc.

Verrous et interblocages — bases de la concurrence

Les bases de données réelles sont sollicitées par de nombreux utilisateurs en même temps. Disons qu'Alice a un solde de 1000, et que deux magasins (X et Y) essaient de la facturer au même moment — les deux peuvent lire « 1000 » et soustraire à partir de là, et l'un de ces débits disparaît silencieusement.

La défense contre cela est un verrou : pendant que la transaction d'un utilisateur touche une ligne, quiconque essaie de toucher la même ligne doit attendre. Le premier verrouille la ligne, et le second attend.

Mais il y a un revers : si l'utilisateur A verrouille les comptes dans l'ordre « compte 1 → compte 2 » et que l'utilisateur B les verrouille dans l'ordre « compte 2 → compte 1 », ils finissent par attendre indéfiniment les verrous l'un de l'autre. C'est un interblocage. Le correctif classique est de toujours acquérir les verrous dans le même ordre (par exemple, toujours par account_id croissant). Si un interblocage se produit, la base de données annulera de force l'une des transactions pour casser le cycle.

Verrous et leur impasse (interblocage)
Utilisateur Averrouille compte 1Utilisateur Bverrouille compte 2A demande le compte 2et attendB demande le compte 1et attendInterblocageles deux attendent indéfinimentLa BDD annule de forcel'une des deux
Pendant qu'un utilisateur met à jour une ligne, cette ligne est verrouillée et l'autre utilisateur doit attendre. Si deux transactions détiennent chacune ce dont l'autre a besoin, les deux attendent indéfiniment — un interblocage.

Niveaux d'isolation et ACID — récapitulatif de terminologie

Un niveau d'isolation contrôle dans quelle mesure une transaction donnée peut voir le travail en cours des autres transactions concurrentes.

Les réglages plus faibles (comme READ COMMITTED) sont plus rapides mais te laissent voir davantage des changements des autres, tandis que les réglages plus forts (comme SERIALIZABLE) sont plus sûrs mais imposent plus d'attentes.

Avec l'atomicité (A), la cohérence (C), l'isolation (I) et la durabilité (D — une fois qu'un COMMIT a lieu, les données restent sur le disque et survivent aux pannes ou coupures de courant), ces quatre forment les propriétés ACID.

Le comportement exact des verrous et niveaux d'isolation varie selon le produit, donc lorsque tu construis quelque chose pour de vrai, consulte la spécification de la base de données que tu utilises.

ACIDSignification
A — AtomicitéLes instructions entre BEGIN et COMMIT s'appliquent toutes ou aucune.
C — CohérenceLes contraintes CHECK, les clés étrangères et les autres règles d'intégrité tiennent avant et après la transaction.
I — IsolationLe travail en cours des autres transactions concurrentes est caché selon le niveau d'isolation.
D — DurabilitéUn résultat validé reste sur le disque et survit aux coupures de courant ou pannes.
QUIZ

Vérification des connaissances

Répondez à chaque question une par une.

Question 1Comment s'appelle la propriété qui traite les deux UPDATE (débit + crédit) d'un virement comme une seule unité — les validant ensemble si les deux réussissent, ou annulant les deux si quelque chose échoue au milieu ?

Question 2Que se passe-t-il pour la table quand tu exécutes BEGIN; UPDATE ...; UPDATE ...; ROLLBACK; ?

Question 3Que se passe-t-il lorsque tu exécutes un seul UPDATE à part, sans écrire BEGIN; d'abord ?