Back

Comprendre les transactions de base de données

Comprendre les transactions de base de données

Lorsqu’un utilisateur passe une commande sur votre plateforme, plusieurs opérations se produisent simultanément : le stock diminue, un enregistrement de paiement est créé et une entrée de commande est sauvegardée. Si le serveur plante en cours de route, vous pourriez vous retrouver avec un client débité mais sans commande enregistrée. Les transactions de base de données existent précisément pour éviter ce type d’échec partiel.

Cet article explique ce que sont les transactions de base de données, comment les propriétés ACID garantissent la fiabilité, comment les niveaux d’isolation des transactions contrôlent l’accès concurrent, et comment les bases de données modernes utilisent MVCC pour faire fonctionner tout cela de manière efficace.

Points clés à retenir

  • Une transaction de base de données regroupe plusieurs opérations en une seule unité de travail — soit toutes réussissent, soit toutes sont annulées.
  • Les propriétés ACID (Atomicité, Cohérence, Isolation, Durabilité) définissent les garanties de fiabilité qu’offrent les transactions.
  • SQL définit quatre niveaux d’isolation, mais le comportement réel varie considérablement selon les moteurs de base de données comme PostgreSQL, MySQL et SQLite.
  • MVCC permet aux bases de données modernes de gérer efficacement les lectures et écritures concurrentes en maintenant plusieurs versions de lignes au lieu de s’appuyer sur un verrouillage intensif.

Qu’est-ce qu’une transaction de base de données ?

Une transaction de base de données est une séquence d’opérations traitée comme une seule unité de travail. Soit toutes les opérations réussissent et les modifications sont validées (committed), soit quelque chose échoue et tout est annulé (rolled back) pour revenir à l’état précédent.

En SQL, une transaction basique ressemble à ceci :

BEGIN;

UPDATE accounts SET balance = balance - 500 WHERE id = 1;
UPDATE accounts SET balance = balance + 500 WHERE id = 2;

COMMIT;

Si quelque chose échoue entre BEGIN et COMMIT, un ROLLBACK restaure la base de données à son état avant le début de la transaction. La plupart des bases de données prennent également en charge SAVEPOINT pour des annulations partielles au sein d’une transaction.

Propriétés ACID : ce qu’elles signifient réellement

ACID est l’ensemble des garanties qui rendent les transactions fiables :

  • Atomicité (Atomicity) — Toutes les étapes réussissent, ou aucune. Pas de mises à jour partielles.
  • Cohérence (Consistency) — La base de données passe d’un état valide à un autre. Les contraintes et règles sont appliquées.
  • Isolation — Les transactions concurrentes n’interfèrent pas les unes avec les autres.
  • Durabilité (Durability) — Une fois validées, les modifications survivent aux plantages. Cela est généralement implémenté via la journalisation en écriture anticipée (write-ahead logging ou WAL).

La conformité ACID a un coût en termes de performance. Certains systèmes vous permettent d’échanger des garanties strictes contre de la vitesse, c’est pourquoi comprendre ces propriétés est important lors de la conception de votre couche de données.

Les niveaux d’isolation des transactions expliqués

L’isolation est la plus nuancée des quatre propriétés ACID. SQL définit quatre niveaux d’isolation des transactions standard, chacun permettant différents compromis entre cohérence et concurrence :

Niveau d’isolationLectures salesLectures non répétablesLectures fantômes
READ UNCOMMITTEDPossiblesPossiblesPossibles
READ COMMITTEDEmpêchéesPossiblesPossibles
REPEATABLE READEmpêchéesEmpêchéesPossibles
SERIALIZABLEEmpêchéesEmpêchéesEmpêchées

Important : Le comportement réel varie selon le moteur de base de données.

  • PostgreSQL n’implémente pas READ UNCOMMITTED — il le met silencieusement à niveau vers READ COMMITTED. Sa valeur par défaut est READ COMMITTED comme documenté dans le guide officiel des niveaux d’isolation.
  • MySQL (InnoDB) utilise par défaut REPEATABLE READ. Il utilise des verrous d’intervalle (gap locks) dans certains cas pour réduire les lectures fantômes, mais le comportement dépend du niveau d’isolation et du modèle de requête comme décrit dans la documentation d’isolation InnoDB.
  • SQLite utilise un modèle à écrivain unique, ce qui signifie qu’une seule transaction d’écriture peut s’exécuter à la fois. Il prend en charge les modes de transaction DEFERRED, IMMEDIATE et EXCLUSIVE plutôt que les niveaux d’isolation standard, comme indiqué dans la documentation des transactions SQLite.

Ne présumez pas d’un comportement identique entre les bases de données. Vérifiez toujours la documentation de votre moteur spécifique.

Comment MVCC rend l’isolation pratique

La plupart des bases de données relationnelles modernes — notamment PostgreSQL et MySQL (InnoDB) — implémentent l’isolation via le contrôle de concurrence multi-versions (Multi-Version Concurrency Control ou MVCC) plutôt que par simple verrouillage.

Avec MVCC, les requêtes voient un instantané cohérent des données, mais le moment où cet instantané est pris (par instruction ou par transaction) dépend du niveau d’isolation et du moteur de base de données. Les écrivains créent de nouvelles versions de lignes plutôt que de les écraser. Les lecteurs ne bloquent pas les écrivains, et les écrivains ne bloquent pas les lecteurs.

C’est pourquoi PostgreSQL peut servir des charges de travail à forte lecture sans que les lecteurs attendent constamment les verrous. Le compromis est que les anciennes versions de lignes s’accumulent et doivent être nettoyées — dans PostgreSQL, cela est géré par le processus VACUUM.

MVCC est ce qui rend REPEATABLE READ et l’isolation par instantané (snapshot isolation) pratiques à grande échelle.

Les transactions dans différents systèmes

Toutes les bases de données ne gèrent pas les transactions de la même manière :

  • MySQL (InnoDB) prend en charge les transactions ACID complètes. L’ancien moteur MyISAM ne le fait pas.
  • PostgreSQL dispose d’un MVCC robuste et prend en charge l’isolation SERIALIZABLE avec de véritables garanties de sérialisabilité.
  • SQLite est entièrement conforme ACID mais sérialise toutes les écritures, ce qui le rend inadapté aux charges de travail d’écriture à forte concurrence.
  • MongoDB a ajouté les transactions multi-documents dans la version 4.0, mais elles entraînent plus de surcharge que dans les bases de données relationnelles traditionnelles et doivent être utilisées de manière sélective.

Recommandations pratiques pour l’utilisation des transactions

  • Gardez les transactions courtes. Les transactions de longue durée maintiennent des verrous ou conservent d’anciens instantanés MVCC, ce qui dégrade les performances.
  • N’enveloppez pas inutilement les requêtes en lecture seule dans des transactions — surtout dans les API à fort trafic.
  • Gérez les erreurs explicitement. Assurez-vous toujours qu’un ROLLBACK se produit en cas d’échec, que vous écriviez du SQL brut ou utilisiez un ORM.
  • Choisissez délibérément votre niveau d’isolation. READ COMMITTED est une valeur par défaut raisonnable pour la plupart des applications web. N’utilisez SERIALIZABLE que lorsque la justesse l’exige, et testez l’impact sur les performances.

Conclusion

Les transactions de base de données vous offrent un moyen fiable de maintenir la cohérence des données à travers plusieurs opérations. Comprendre les propriétés ACID vous indique avec quelles garanties vous travaillez. Connaître vos niveaux d’isolation et comment votre base de données spécifique implémente MVCC vous indique ce que ces garanties coûtent réellement — et où se trouvent les cas limites. Cette connaissance est ce qui distingue les développeurs qui utilisent les transactions de ceux qui les utilisent bien.

FAQ

Utilisez SERIALIZABLE lorsque votre application nécessite des garanties de justesse strictes, comme pour les calculs financiers ou la gestion des stocks où les transactions concurrentes ne doivent pas produire de résultats contradictoires. Pour la plupart des applications web, READ COMMITTED offre un bon équilibre entre cohérence et performance. Testez toujours SERIALIZABLE dans votre environnement, car il peut réduire la concurrence et entraîner des nouvelles tentatives de transaction selon le moteur de base de données.

La plupart des bases de données enveloppent automatiquement chaque instruction SQL individuelle dans une transaction implicite, donc un seul INSERT ou UPDATE est déjà atomique. Les transactions explicites deviennent nécessaires lorsque vous devez regrouper plusieurs instructions en une seule unité de travail, garantissant qu'elles réussissent toutes ou échouent toutes ensemble. Envelopper une instruction isolée dans BEGIN et COMMIT ajoute une surcharge sans bénéfice significatif.

Utilisez toujours des blocs try-catch ou équivalents de gestion d'erreurs autour de votre logique transactionnelle. Si une opération dans la transaction génère une erreur, émettez un ROLLBACK pour annuler toutes les modifications. De nombreux ORM et bibliothèques de base de données fournissent des assistants de transaction intégrés qui annulent automatiquement en cas d'exceptions. Évitez d'ignorer silencieusement les erreurs, car cela peut laisser vos données dans un état incohérent.

Le verrouillage traditionnel peut amener les lecteurs et les écrivains à se bloquer mutuellement plus souvent, ce qui limite la concurrence. MVCC évite cela en conservant plusieurs versions de chaque ligne afin que les lecteurs accèdent à un instantané cohérent sans attendre les écrivains. Le compromis est que les anciennes versions de lignes doivent être périodiquement nettoyées, comme PostgreSQL le fait avec son processus VACUUM. MVCC offre généralement un meilleur débit pour les charges de travail à forte lecture.

Gain control over your UX

See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay