Transactions ACID
Une transaction regroupe plusieurs opérations en un bloc tout-ou-rien. Les propriétés ACID — Atomicité, Cohérence, Isolation, Durabilité — garantissent qu’elle ne laisse jamais la base dans un état incohérent, même en cas de panne ou d’accès concurrent.
Sommaire
Le problème #
Imaginez un virement bancaire de 100 euros entre deux comptes : débiter le compte A, puis créditer le compte B. Ce sont deux opérations distinctes. Si le serveur plante juste après le débit et avant le crédit — panne électrique, crash applicatif, coupure réseau — le compte A a perdu 100 euros qui n’existent plus nulle part. La base est dans un état incohérent, et personne ne s’en aperçoit avant qu’un client ne s’en plaigne.
Ce problème existe dès qu’une opération métier nécessite plusieurs écritures liées. Sans garantie particulière, chaque écriture est indépendante et vulnérable à toute interruption entre les deux.
L’idée générale #
Une transaction regroupe plusieurs opérations en un seul bloc tout ou rien. Les propriétés ACID définissent les garanties que ce bloc doit respecter :
- Atomicité : soit toutes les opérations de la transaction réussissent, soit aucune n’est appliquée. Pas de virement à moitié fait.
- Cohérence : la transaction fait passer la base d’un état valide à un autre état valide, en respectant toutes les contraintes (clés étrangères, contraintes
CHECK, unicité…). - Isolation : les transactions concurrentes ne voient pas les états intermédiaires les unes des autres — le niveau exact de cette garantie dépend du niveau d’isolation choisi (voir l’article dédié).
- Durabilité : une fois la transaction validée (
COMMIT), les changements survivent à toute panne — ils sont écrits de façon persistante, généralement via un journal des transactions.
Analogie du quotidien #
Une transaction, c’est comme signer un contrat de vente immobilière chez le notaire. Le vendeur ne remet pas les clés avant d’avoir reçu l’argent, et l’acheteur ne paie pas avant d’avoir la garantie de recevoir les clés. Les deux actions — payer et transférer la propriété — sont liées : soit elles ont lieu ensemble, au même instant juridique (la signature), soit la vente n’a pas lieu du tout.
Il n’existe pas d’état intermédiaire où l’acheteur a payé mais où le bien n’est pas encore transféré : le notaire (l’équivalent du moteur transactionnel) garantit que tout se valide d’un bloc, ou que rien ne se passe si un élément manque.
Diagramme #
Exemple de code #
BEGIN;
UPDATE comptes SET solde = solde - 100 WHERE id = 'A';
UPDATE comptes SET solde = solde + 100 WHERE id = 'B';
-- Si le solde du compte A devient négatif, une contrainte CHECK
-- peut faire échouer la transaction et déclencher un ROLLBACK automatique
COMMIT;
// Exemple avec JDBC : transaction explicite autour d'un virement
Connection conn = dataSource.getConnection();
try {
conn.setAutoCommit(false);
try (PreparedStatement debit = conn.prepareStatement(
"UPDATE comptes SET solde = solde - ? WHERE id = ?")) {
debit.setBigDecimal(1, montant);
debit.setString(2, compteA);
debit.executeUpdate();
}
try (PreparedStatement credit = conn.prepareStatement(
"UPDATE comptes SET solde = solde + ? WHERE id = ?")) {
credit.setBigDecimal(1, montant);
credit.setString(2, compteB);
credit.executeUpdate();
}
conn.commit();
} catch (SQLException e) {
conn.rollback(); // annule tout : le compte A n'a jamais réellement perdu son argent
throw e;
} finally {
conn.setAutoCommit(true);
conn.close();
}
Quand utiliser une transaction ? #
- Dès qu’une opération métier nécessite plusieurs écritures liées qui doivent réussir ou échouer ensemble (virement, création de commande avec décrément de stock, inscription avec création de profil).
- Pour garantir qu’une contrainte métier n’est jamais violée temporairement, même en cas d’erreur applicative en plein milieu du traitement.
- Moins pertinent pour une écriture unique et isolée, où l’atomicité est déjà garantie nativement par le moteur sans bloc
BEGIN/COMMITexplicite. - À manier avec précaution sur des transactions longues : elles retiennent des verrous et peuvent bloquer d’autres opérations concurrentes.
Points importants #
- Une transaction non terminée par
COMMITouROLLBACKexplicite reste ouverte et retient des ressources — toujours s’assurer qu’elle se termine, y compris en cas d’exception (blocfinally). - La Durabilité repose généralement sur un journal des transactions (write-ahead log) : les changements sont écrits dans ce journal avant d’être appliqués aux fichiers de données, ce qui permet de rejouer les transactions validées après un crash.
- ACID décrit des garanties, pas une implémentation unique : chaque moteur (PostgreSQL, MySQL/InnoDB…) les respecte avec ses propres mécanismes internes.
- Isolation et Atomicité sont souvent confondues : l’Atomicité protège une transaction en elle-même, l’Isolation protège les transactions les unes des autres (détaillé dans l’article sur l’isolation transactionnelle).
🐻 À retenir
- ●ACID = Atomicité (tout ou rien), Cohérence (les règles restent respectées), Isolation (les transactions ne se marchent pas dessus), Durabilité (une fois validé, c’est définitif).
- ●Une transaction se termine toujours par un
COMMIT(on valide) ou unROLLBACK(on annule tout) — jamais un état intermédiaire persistant. - ●Le cas d’école : un virement bancaire. Débiter un compte sans créditer l’autre est un état incohérent que ACID interdit.