Transactions MySQL expliquées : ACID, niveaux d’isolation, guide COMMIT & ROLLBACK

目次

1. Qu’est‑ce qu’une transaction MySQL?

Définition et importance des transactions

Une transaction désigne une unité de travail qui traite plusieurs opérations de base de données comme un groupe logique unique. Par exemple, considérez un virement bancaire. Retirer de l’argent du compte de la Personne A et le déposer sur le compte de la Personne B nécessite deux requêtes SQL. Si une seule de ces opérations s’exécute avec succès, la cohérence financière serait rompue.

C’est pourquoi nous avons besoin d’un mécanisme qui garantit que toutes les opérations réussissent ou que toutes soient annulées. Ce mécanisme s’appelle une transaction. Les transactions jouent un rôle crucial dans le maintien de l’intégrité des données.

Quelles sont les propriétés ACID ?

Pour assurer un traitement fiable, les transactions doivent satisfaire quatre propriétés connues sous le nom d’ACID.

  • Atomicité Toutes les opérations d’une transaction doivent réussir entièrement ou échouer entièrement. Si une erreur survient à mi‑parcours, toutes les modifications sont annulées.
  • Cohérence Garantit que l’intégrité de la base de données est préservée avant et après la transaction. Par exemple, les quantités d’inventaire ne doivent jamais devenir négatives.
  • Isolation Même lorsque plusieurs transactions s’exécutent simultanément, elles doivent être traitées sans interférer les unes avec les autres. Cela assure une exécution stable, non affectée par d’autres transactions.
  • Durabilité Une fois qu’une transaction est validée avec succès, ses modifications sont enregistrées de façon permanente dans la base de données. Même les pannes d’alimentation ne provoqueront pas de perte de données.

En respectant les propriétés ACID, les applications peuvent réaliser des opérations de données hautement fiables.

Avantages d’utiliser les transactions dans MySQL

Dans MySQL, les transactions sont prises en charge lorsqu’on utilise le moteur de stockage InnoDB. Les moteurs plus anciens comme MyISAM ne supportent pas les transactions, il faut donc être prudent.

Utiliser les transactions dans MySQL offre les avantages suivants :

  • Restaurer l’état des données lorsqu’une erreur survient (ROLLBACK)
  • Gérer les opérations multi‑étapes comme une unité logique unique
  • Maintenir la cohérence même en cas de pannes du système

En particulier dans les systèmes avec une logique métier complexe—tels que les plates‑formes e‑commerce, les systèmes financiers et la gestion d’inventaire—le support des transactions influence directement la fiabilité globale.

2. Opérations de base des transactions dans MySQL

Démarrer, valider et annuler les transactions

Les trois commandes fondamentales utilisées pour les transactions dans MySQL sont :

  • START TRANSACTION ou BEGIN : Démarrer une transaction
  • COMMIT : Confirmer et enregistrer les modifications
  • ROLLBACK : Annuler les modifications et restaurer l’état précédent

Exemple de flux de travail de base :

START TRANSACTION;

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

COMMIT;

En commençant par START TRANSACTION et en terminant par COMMIT, les deux opérations de mise à jour sont appliquées ensemble comme un seul processus logique. Si une erreur survient à mi‑parcours, vous pouvez annuler toutes les modifications avec ROLLBACK.

ROLLBACK;

Paramètres d’autocommit et différences de comportement

Par défaut, MySQL active le mode autocommit. Dans ce mode, chaque instruction SQL est automatiquement validée immédiatement après son exécution.

Vérifier le paramètre actuel :

SELECT @@autocommit;

Désactiver l’autocommit :

SET autocommit = 0;

Lorsque l’autocommit est désactivé, les modifications restent en attente jusqu’à ce que vous terminiez explicitement la transaction. Cela permet de gérer plusieurs opérations ensemble.

Exemple : exécuter en toute sécurité plusieurs instructions UPDATE

L’exemple suivant regroupe la réduction d’inventaire et l’insertion d’un enregistrement de vente au sein d’une seule transaction :

START TRANSACTION;

UPDATE products SET stock = stock - 1 WHERE id = 10 AND stock > 0;
INSERT INTO sales (product_id, quantity, sale_date) VALUES (10, 1, NOW());

COMMIT;

Le point clé est d’utiliser la condition stock > 0 pour empêcher l’inventaire de devenir négatif. Si nécessaire, vous pouvez vérifier le nombre de lignes affectées et exécuter ROLLBACK si aucune ligne n’a été mise à jour.

3. Niveaux d’isolation et leur impact

Qu’est-ce qu’un niveau d’isolation ? Comparaison des quatre types

Dans les SGBDR (Systèmes de Gestion de Bases de Données Relationnelles), y compris MySQL, il est courant que plusieurs transactions s’exécutent simultanément. Le mécanisme qui contrôle les transactions afin qu’elles n’interfèrent pas les unes avec les autres s’appelle le niveau d’isolation.

Il existe quatre niveaux d’isolation. Les niveaux supérieurs réduisent l’interférence entre les transactions de manière plus stricte, mais ils peuvent également affecter les performances.

Isolation LevelDescriptionMySQL Default
READ UNCOMMITTEDCan read uncommitted data from other transactions×
READ COMMITTEDCan read only committed data×
REPEATABLE READAlways reads the same data within the same transaction◎ (Default)
SERIALIZABLEFully serialized execution; most strict but slowest×

Phénomènes pouvant survenir à chaque niveau d’isolation

Selon le niveau d’isolation, trois problèmes liés à la cohérence peuvent survenir. Il est important de comprendre ce qu’ils sont et quels niveaux d’isolation les empêchent.

  1. Lecture sale
  • Lecture de données qu’une autre transaction n’a pas encore validées.
  • Empêché par : READ COMMITTED ou supérieur
  1. Lecture non répétable
  • Exécuter la même requête plusieurs fois renvoie des résultats différents parce qu’une autre transaction a modifié les données.
  • Empêché par : REPEATABLE READ ou supérieur
  1. Lecture fantôme
  • Des lignes sont ajoutées ou supprimées par une autre transaction, ce qui fait que la même condition de recherche renvoie un jeu de résultats différent.
  • Empêché par : SERIALIZABLE uniquement

Comment définir les niveaux d’isolation (avec exemples)

Dans MySQL, les niveaux d’isolation peuvent être définis par session ou globalement.

Paramétrage au niveau de la session (approche courante)

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

Vérifier le niveau d’isolation actuel

SELECT @@transaction_isolation;

Exemple : différence entre REPEATABLE READ et READ COMMITTED

-- Session A
START TRANSACTION;
SELECT * FROM products WHERE id = 10;

-- Session B
UPDATE products SET stock = stock - 1 WHERE id = 10;
COMMIT;

-- Session A
SELECT * FROM products WHERE id = 10; -- No change under REPEATABLE READ

Comme le montre l’exemple ci‑dessus, définir le niveau d’isolation approprié est crucial pour maintenir l’intégrité des données. Cependant, des niveaux plus stricts peuvent affecter négativement les performances, il faut donc les ajuster en fonction de votre cas d’utilisation.

4. Scénarios pratiques de transactions

Exemples de gestion d’inventaire et de e‑commerce

Dans les systèmes de e‑commerce, vous devez mettre à jour l’inventaire des produits lors du traitement des commandes. Si plusieurs utilisateurs tentent d’acheter le même produit simultanément, l’inventaire peut devenir inexact. En utilisant des transactions, vous pouvez gérer les opérations concurrentes tout en préservant la cohérence des données.

Exemple : diminuer l’inventaire et insérer l’historique des commandes en une seule transaction

START TRANSACTION;

UPDATE products SET stock = stock - 1 WHERE id = 101 AND stock > 0;
INSERT INTO orders (product_id, quantity, order_date) VALUES (101, 1, NOW());

COMMIT;

Le point clé est d’utiliser stock > 0 pour empêcher l’inventaire de devenir négatif. Si nécessaire, vous pouvez également vérifier le nombre de lignes mises à jour et exécuter ROLLBACK lorsqu’aucune ligne n’a été modifiée.

Conception de transactions pour les virements bancaires

Un virement bancaire entre comptes est un cas d’utilisation classique pour les transactions.

  • Décrémenter le solde du compte A
  • Augmenter le solde du même montant sur le compte B

Si l’une des opérations échoue, vous devez annuler l’ensemble du processus (ROLLBACK).

Exemple : traitement du virement

START TRANSACTION;

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

COMMIT;

Dans les systèmes de production réels, l’application ajoute généralement des validations supplémentaires — comme empêcher les soldes négatifs ou appliquer des limites de transfert — dans le cadre de la logique métier.

Exemples de transactions avec Laravel et PHP

Ces dernières années, il est de plus en plus courant de gérer les transactions via des frameworks. Ici, nous examinerons comment utiliser les transactions dans le framework PHP populaire Laravel.

Transactions dans Laravel

DB::transaction(function () {
    DB::table('accounts')->where('id', 1)->decrement('balance', 10000);
    DB::table('accounts')->where('id', 2)->increment('balance', 10000);
});

En utilisant la méthode DB::transaction(), Laravel gère automatiquement BEGIN, COMMIT et ROLLBACK en interne, ce qui donne un code sûr et lisible.

Exemple : Transactions manuelles avec try-catch

DB::beginTransaction();

try {
    // Processing logic
    DB::commit();
} catch (\Exception $e) {
    DB::rollBack();
    // Logging or notification, etc.
}

En tirant parti des fonctionnalités du framework et du langage, vous pouvez gérer les transactions sans écrire directement du SQL brut.

5. Pièges courants et optimisation des performances

Les transactions sont puissantes, mais une mauvaise utilisation peut entraîner une dégradation des performances et des problèmes inattendus. Dans cette section, nous expliquons les considérations importantes et les contre‑mesures lors de l’utilisation des transactions dans MySQL.

Opérations qui ne peuvent pas être annulées (DDL)

L’un des principaux avantages des transactions est la capacité de restaurer les modifications à l’aide de ROLLBACK. Cependant, toutes les instructions SQL ne peuvent pas être annulées.

Soyez particulièrement prudent avec les opérations utilisant le Data Definition Language (DDL). Les instructions suivantes ne peuvent pas être annulées :

  • CREATE TABLE
  • ALTER TABLE
  • DROP TABLE

Ces instructions sont validées immédiatement lors de leur exécution et ne sont pas affectées par le contrôle des transactions. Par conséquent, les opérations DDL doivent toujours être exécutées en dehors des transactions.

Verrous morts : causes et prévention

Lorsque les transactions sont fortement utilisées, plusieurs transactions peuvent finir par attendre indéfiniment les ressources des autres. Cette situation est connue sous le nom de verrou mort.

Exemple d’un verrou mort (simplifié)

  • La transaction A verrouille la ligne 1 et attend la ligne 2
  • La transaction B verrouille la ligne 2 et attend la ligne 1

Lorsque cela se produit, MySQL force automatiquement l’une des transactions à être annulée.

Stratégies de prévention

  • Standardiser l’ordre de verrouillage Lors de la mise à jour de lignes dans la même table, accédez toujours à celles-ci dans le même ordre.
  • Garder les transactions courtes Évitez les traitements inutiles à l’intérieur des transactions et exécutez COMMIT ou ROLLBACK le plus rapidement possible.
  • Limiter le nombre de lignes affectées Utilisez des clauses WHERE précises pour éviter de verrouiller des tables entières.

Checklist lorsque les transactions semblent lentes

Il existe de nombreuses causes possibles de performances lentes des transactions. Examiner les points suivants peut aider à identifier les goulots d’étranglement :

  • Les index sont-ils correctement configurés ? Les colonnes utilisées dans les clauses WHERE ou les conditions JOIN doivent avoir des index.
  • Le niveau d’isolation est-il trop élevé ? Vérifiez que vous n’utilisez pas inutilement des niveaux stricts comme SERIALIZABLE.
  • L’autocommit est-il laissé activé par inadvertance ? Assurez‑vous de gérer les transactions explicitement lorsque c’est nécessaire.
  • Les transactions restent‑elles ouvertes trop longtemps ? De longs intervalles entre START TRANSACTION et COMMIT peuvent provoquer des contentions de verrous.
  • Les tailles du pool de tampons InnoDB et des journaux sont‑elles appropriées ? Vérifiez que les paramètres du serveur correspondent à votre volume de données et envisagez un réglage si nécessaire.

6. Astuces avancées que vous voyez rarement ailleurs

Alors que de nombreux sites techniques expliquent les bases des transactions MySQL, moins d’articles couvrent les techniques pratiques utiles en production et en dépannage. Cette section présente des astuces pratiques pour approfondir votre compréhension.

Comment vérifier les transactions en cours

Lorsque plusieurs transactions s’exécutent simultanément, il peut être nécessaire d’inspecter leur état. Dans MySQL, vous pouvez vérifier le statut des verrous InnoDB et les informations de transaction à l’aide de la commande suivante :

SHOW ENGINE INNODB STATUS\G

Cette commande affiche l’état interne d’InnoDB, incluant :

  • Liste des transactions en cours
  • Transactions en attente de verrous
  • Historique des verrous morts

Lorsque des problèmes complexes surviennent, ces informations constituent souvent la première étape du débogage.

Analyser le comportement avec les journaux SQL et les journaux de requêtes lentes

Pour diagnostiquer les problèmes de transaction, l’analyse des journaux est essentielle. MySQL offre plusieurs fonctionnalités de journalisation :

  • Journal général : Enregistre toutes les instructions SQL
  • Journal des requêtes lentes : Enregistre uniquement les requêtes qui dépassent un temps d’exécution spécifié

Exemple : Activation du journal des requêtes lentes (my.cnf)

slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1

Avec cette configuration, les requêtes qui durent plus d’une seconde sont enregistrées. Si une transaction contient des requêtes lentes, ce journal aide à identifier la cause de la dégradation des performances.

Expérimenter avec plusieurs sessions pour comprendre le comportement

Comprendre les transactions sur le plan conceptuel est important, mais l’expérimentation pratique est tout aussi précieuse. En ouvrant deux terminaux et en exécutant des requêtes dans des sessions séparées, vous pouvez observer les différences de niveau d’isolation et le comportement des verrous.

Exemple d’expérimentation : comportement sous REPEATABLE READ

  • Session A
    SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    START TRANSACTION;
    SELECT * FROM products WHERE id = 1;
    -- Hold the result
    
  • Session B
    UPDATE products SET name = 'Updated Product Name' WHERE id = 1;
    COMMIT;
    
  • Session A
    SELECT * FROM products WHERE id = 1;
    -- The change is still not visible (due to REPEATABLE READ)
    COMMIT;
    

Grâce à des expériences comme celle-ci, vous pouvez éliminer les incohérences entre la logique et le comportement réel et mettre en œuvre des systèmes plus précis.

7. Questions fréquemment posées (FAQ)

En plus de l’utilisation de base, de nombreuses questions pratiques surgissent lorsqu’on travaille avec les transactions MySQL dans des environnements réels. Dans cette section, nous résumons les questions courantes et leurs réponses sous forme de Q&R.

Q1. Existe-t-il des situations où les transactions ne peuvent pas être utilisées dans MySQL ?

Oui. Si le moteur de stockage MySQL n’est pas InnoDB, la fonctionnalité de transaction n’est pas prise en charge. Dans les systèmes plus anciens, MyISAM peut encore être utilisé, et dans ces cas, les transactions ne fonctionneront pas.

Comment vérifier :

SHOW TABLE STATUS WHERE Name = 'table_name';

Assurez‑vous que la colonne Engine indique InnoDB.

Q2. L’utilisation des transactions ralentit‑elle toujours le traitement ?

Pas nécessairement. Cependant, une mauvaise conception des transactions peut nuire aux performances.

Les causes possibles incluent :

  • Garder les transactions ouvertes trop longtemps
  • Utiliser des niveaux d’isolation inutilement stricts
  • Un indexage insuffisant qui élargit la portée des verrous

Dans de tels cas, la contention des verrous et la charge du pool de tampons peuvent réduire les performances.

Q3. La désactivation d’autocommit transforme‑t‑elle automatiquement tout en transaction ?

Lorsque vous exécutez SET autocommit = 0;, toutes les requêtes suivantes restent en attente jusqu’à ce qu’un COMMIT ou ROLLBACK explicite soit exécuté. Cela peut inclure involontairement plusieurs opérations dans la même transaction et entraîner des problèmes inattendus.

Par conséquent, si vous désactivez autocommit, il est important de gérer clairement le début et la fin des transactions.

Q4. Que faire si une erreur survient pendant une transaction ?

Si une erreur survient pendant une transaction, vous devez généralement exécuter ROLLBACK pour restaurer l’état précédent. Du côté de l’application, le contrôle des transactions est généralement combiné à la gestion des exceptions.

Exemple (PHP + PDO)

try {
    $pdo->beginTransaction();

    // SQL processing
    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
    // Record error logs, etc.
}

Une gestion correcte des erreurs aide à éviter les écritures de données incomplètes et à améliorer la fiabilité globale du système.

8. Résumé

Dans cet article, nous avons exploré le sujet « Transactions MySQL » des fondamentaux aux applications pratiques, en incluant les stratégies de dépannage et les astuces avancées. Résumons les points clés.

Les transactions sont la clé de la fiabilité

Une transaction est une fonctionnalité centrale qui regroupe plusieurs opérations SQL en une seule unité afin de préserver l’intégrité et la fiabilité des données. Dans des systèmes tels que les plateformes financières, la gestion des stocks et les systèmes de réservation, une conception correcte des transactions est essentielle.

Un contrôle correct et une compréhension sont cruciaux

  • Maîtrisez le flux de base de START TRANSACTION à COMMIT et ROLLBACK
  • Comprenez la différence entre le mode autocommit et la gestion explicite des transactions
  • Ajustez les niveaux d’isolation de manière appropriée pour équilibrer performance et cohérence

Les scénarios pratiques et les astuces vous renforcent en production

Dans les environnements réels de développement et d’exploitation, il ne suffit pas de connaître la syntaxe. Vous devez également comprendre comment inspecter les transactions en cours et résoudre les problèmes à l’aide des journaux et des outils de surveillance.

Les transactions MySQL sont souvent étudiées uniquement lorsque des problèmes surviennent. En les apprenant de manière systématique à l’avance, vous acquérez une compétence puissante qui améliore directement la fiabilité et les performances du système.

Nous espérons que ce guide approfondira votre compréhension des transactions et vous donnera confiance dans votre travail quotidien de développement et d’exploitation.

Si vous avez des questions ou des sujets que vous souhaiteriez voir abordés plus en détail, n’hésitez pas à laisser un commentaire. Nous continuerons à fournir des informations techniques pratiques et exploitables.