TECHNOLOGIES / MySQL

MySQL : la base de données relationnelle de nos projets Symfony

MySQL est le système de gestion de base de données relationnelle open source le plus utilisé au monde. Chez SmartBooster, il equipe l'ensemble de nos projets Symfony via Doctrine ORM, conteneurisé dans notre stack Docker standard.

Cette page vous explique pourquoi nous avons fait ce choix, compare les performances entre versions et documente les commandes utiles au quotidien pour l'équipe.

9.7 LTS Nouveau LTS (avr. 2026) Sorti avril 2026 - support Premier jusqu'en 2031, Extended jusqu'en 2034
8.4 LTS LTS précédente (actif) Sorti avril 2024 - support Oracle jusqu'en avril 2032 - recommandée pour les projets existants
8.0 EOL depuis avr. 2026 Plus aucun correctif de sécurité - migration vers 8.4 LTS ou 9.7 LTS urgente

PRÉSENTATION

Qu'est-ce que MySQL ?

MySQL est un SGBDR (Système de Gestion de Bases de Données Relationnelles) open source créé en 1995 par Michael Widenius. Aujourd'hui maintenu par Oracle, il est utilisé par des millions d'applications dans le monde, des blogs WordPress aux systèmes transactionnels d'entreprise.

Son moteur de stockage InnoDB, devenu le défaut depuis MySQL 5.5, garantit les propriétés ACID : Atomicité, Cohérence, Isolation et Durabilité. Chaque transaction est soit entièrement appliquée, soit entièrement annulée, même en cas de crash serveur.

Chez SmartBooster, MySQL s'intègre dans notre stack via Doctrine ORM qui génère les requêtes SQL optimisées et gère les migrations de schéma depuis le code source PHP.

Logo MySQL

POURQUOI MYSQL

Ce qui en fait notre standard de base de données

MySQL est présent sur tous nos projets Symfony dès le premier jour. Voici pourquoi nous ne développons plus sans lui.

Base de référence de l'écosystème Symfony

MySQL est la base de données par défaut des projets Symfony chez SmartBooster. Doctrine ORM génère des requêtes optimisées pour MySQL et notre template symfony-docker intègre MySQL nativement dans la stack de développement.

Transactions ACID et fiabilité InnoDB

Le moteur InnoDB garantit des transactions atomiques, une cohérence des données après crash et des clés étrangères avec contraintes d'intégrité. Aucune donnée corrompue en cas de coupure réseau au milieu d'un INSERT groupé.

Performance indexée pour les applications métier

Les index composites, les index couvrants et le query optimizer MySQL s'intègrent avec Doctrine ORM. L'essentiel des gains de performance vient de la structure des index et des requêtes, pas de la version MySQL.

Image Docker officielle prête à l'emploi

L'image officielle mysql:8.4 est disponible sur Docker Hub et intégrée dans notre stack Docker standard. Démarrage en une commande, données persistées dans un volume nommé, configuration via variables d'environnement.

Migrations de schéma versionnées avec Doctrine

Les migrations Doctrine générées depuis les entités PHP créent des scripts SQL versionnés et rejouables. Chaque evolution du schéma est tracée dans Git et déployée automatiquement en CI avant chaque mise en production.

Deux versions LTS au choix

MySQL 8.4 LTS (support jusqu'en 2032) et MySQL 9.7 LTS sorti avril 2026 (support jusqu'en 2034). Pour les projets existants sur 8.4 : aucune migration forcée avant 2032. Pour les nouveaux projets, MySQL 9.7 LTS est le choix naturel.

PERFORMANCE

MySQL par version : gains de performance

MySQL publie régulièrement de nouvelles versions LTS et Innovation. Voici les gains de performance observés sur des applications web PHP/Symfony standards, mesurés via des benchmarks sysbench OLTP sur des charges mixtes lecture/écriture.

Saut de version Gain typique Explication
MySQL 5.6 → 5.7 Scalabilité (forte concurrence) Refonte de la scalabilité InnoDB en read-write : purge multi-threadée, pool de buffer mieux partitionné et statistiques adaptatives de l'optimiseur. Percona observe un net gain de débit à forte concurrence (plusieurs centaines de connexions simultanées). À faible concurrence en revanche, 5.7 n'apporte pas de gain et peut rester légèrement derrière 5.6, son exécution mono-thread étant plus lente.
MySQL 5.7 → 8.0 5.7 souvent plus rapide Contrairement à l'idée reçue, MySQL 8.0 n'est pas toujours plus rapide que 5.7. Sur un test sysbench à 24 threads, Percona mesure 5.7 plus rapide dans toutes les configurations : de 12 à 22 % avec les binary logs activés (cas standard pour la réplication), de 5 à 16 % sans. L'intérêt de migrer vers 8.0 est avant tout fonctionnel : CTE, Window Functions, roles, JSON enrichi et Atomic DDL.
MySQL 8.0 → 8.4 LTS Marginal (< 5 %) La version 8.4 LTS est une consolidation, pas une refonte de moteur. Les gains de performance sont anecdotiques sur les workloads applicatifs classiques. L'intérêt de la migration est exclusivement la sécurité et la garantie de support jusqu'en 2032, pas le débit.
MySQL 8.4 → 9.7 LTS +6.5 % (moyenne PGO)
+14.3 % (pic) 32 Go, 1 thread
MySQL 9.7 LTS est le premier binaire MySQL compilé avec le PGO (Profile-Guided Optimization) : le compilateur analyse les chemins d'exécution chauds lors d'un profiling réel, puis recompile l'ensemble du code en ciblant ces chemins. Percona mesure +6.5 % en moyenne sur sysbench OLTP, avec un pic à +14.3 % sur les configurations 32 Go (grand buffer pool) à faible concurrence. Le gain est le plus fort avec un grand buffer pool et s'amenuise sur les petites configurations mémoire et à très haute concurrence.

Les gains indiqués sont des ordres de grandeur issus de benchmarks sysbench OLTP et de mesures en conditions réelles sur des applications PHP/Symfony. Ils varient selon le ratio lecture/écriture, la taille des tables, la configuration du pool de buffer InnoDB et l'infrastructure. Ces chiffres ne se substituent pas à un profiling sur votre propre application. Sources : Percona : MySQL 5.7 read-write benchmarks, Percona : MySQL 8 n'est pas toujours plus rapide que 5.7, Percona : MySQL 9.7.0 PGO benchmark analysis, Percona : rapport 2026 MySQL ecosystem benchmark.

HISTORIQUE

Versions de MySQL

MySQL suit un double calendrier depuis 2024 : le canal LTS (Long Term Support, tous les 2-3 ans) pour la stabilité en production, et le canal Innovation (trimestriel) pour les nouvelles fonctionnalités. Voir les dates de fin de support officielles →

Chez SmartBooster, nous utilisons exclusivement des versions LTS en production. Les versions du canal Innovation (sorties trimestrielles : 8.1 à 8.3, 9.0 à 9.6) apportent les nouvelles fonctionnalités mais sans garantie de support long terme : leur description ci-dessous précise qu'elles ne sont pas des LTS et qu'elles sont rapidement éclipsées par la LTS suivante.

  • MySQL 9.7 LTS

    Recommandée

    Avr. 2026

    Deuxième version LTS officielle d'Oracle depuis le passage au nouveau cycle de publication. Intègre les fonctionnalités des versions Innovation 9.0 à 9.6 et introduit le PGO (Profile-Guided Optimization). Support Premier jusqu'en 2031, Extended jusqu'en 2034. Le choix naturel pour tout nouveau projet.

    • Hypergraph optimizer (GA)
      Le nouvel optimiseur modélise la requête complète comme un hypergraphe et explore un espace de plans d'exécution bien plus large que le legacy optimizer. Gain mesurable sur les jointures complexes avec plusieurs tables.
    • JavaScript UDF natif
      Fonctions utilisateur en JavaScript exécutées via GraalVM directement dans le moteur MySQL. Logique métier sans aller-retour réseau entre l'application et la base de données.
    • JSON duality views
      Vues qui exposent les données simultanément en modèle relationnel et en documents JSON, sans duplication de stockage. Simplifie les applications hybrides SQL/document.
    • Fonctionnalités Enterprise en Community
      Métriques de réplication, statistiques Group Replication et télémétrie : des outils auparavant réservés à MySQL Enterprise Edition sont disponibles gratuitement.
  • MySQL 9.0 → 9.6

    Obsolète depuis avr. 2026

    Juil. 2024 → Jan. 2026

    Versions du canal Innovation d'Oracle : sorties trimestrielles avec de nouvelles fonctionnalités sans garantie de support long terme. Cette branche non-LTS n'est plus maintenue depuis la sortie de 9.7 LTS, qui a intégré ses fonctionnalités stables.

    • Vector Type natif
      Type de colonne pour stocker des embeddings vectoriels. Utilisé pour les recherches de similarité (RAG, recommandations) sans extension tierce.
    • JavaScript UDF
      Fonctions utilisateur en JavaScript via le moteur GraalVM. Permet d'écrire de la logique métier directement dans la base de données.
  • MySQL 8.4 LTS

    Support actif avr. 2029

    Avr. 2024

    Première version LTS officielle d'Oracle pour MySQL 8.x, toujours en support actif. Support de sécurité jusqu'en avril 2032. Recommandée pour les projets existants : aucune migration forcée vers 9.7 avant 2032.

    • Support LTS 8 ans
      Garantie de correctifs de sécurité jusqu'en avril 2032. La version cible pour tout projet en production qui veut éviter les migrations fréquentes.
    • GTID activé par défaut
      Les Global Transaction Identifiers sont activés par défaut pour la réplication. Simplifie la configuration des architectures primaire/réplica.
    • Suppression des dépréciations 8.0
      Certaines syntaxes dépréciées depuis MySQL 8.0 sont supprimées dans 8.4. Un audit des requêtes est nécessaire avant la migration depuis 8.0.
  • MySQL 8.1 → 8.3

    Obsolète depuis avr. 2024

    Juil. 2023 → Jan. 2024

    Premières versions du nouveau canal Innovation d'Oracle, introduit avec la bifurcation de la branche MySQL 8.x. Ces versions trimestrielles non-LTS ont été éclipsées par la sortie de MySQL 8.4 LTS en avril 2024.

  • MySQL 8.0

    Obsolète depuis avr. 2026

    Avr. 2018

    Version majeure avec refonte de la gestion des droits, JSON enrichi et Window Functions. Avant le nouveau modèle LTS/Innovation d'Oracle, MySQL 8.0 a assuré un long cycle de support (2018-2026). Plus de correctifs de sécurité depuis avril 2026 : migration vers 8.4 LTS ou 9.7 LTS urgente.

    • Roles et gestion des droits
      Les roles MySQL permettent de regrouper des ensembles de privilèges et de les assigner à plusieurs utilisateurs. Remplace les scripts de GRANT laborieux.
    • Window Functions
      ROW_NUMBER(), RANK(), LAG(), LEAD()... Les fonctions analytiques permettent des agrégations glissantes et des classements sans sous-requêtes imbriquées complexes.
    • CTE (Common Table Expressions)
      Les expressions WITH améliorent la lisibilité des requêtes complexes. Les CTE récursives permettent de parcourir des structures arborescentes (catégories imbriquées, commentaires) en SQL natif.
    • Atomic DDL
      Les opérations DDL (CREATE, DROP, ALTER) sont atomiques et enregistrées dans le redo log. Plus de tables orphelines ou d'état incohérent après un crash pendant un ALTER TABLE en production.
    • UTF8MB4 par défaut
      L'encodage 4 octets devient le défaut, couvrant l'intégralité d'Unicode dont les emojis. Fin des truncations silencieuses sur les champs VARCHAR avec des caractères hors BMP.
  • MySQL 6 et 7

    Versions inexistantes

    Non publiés

    MySQL 6.0 a été lancé en développement en 2007 puis abandonné après le rachat de MySQL AB par Sun Microsystems en 2008. Les fonctionnalités utiles ont été réintégrées dans la branche 5.x. MySQL 7.x est réservé à MySQL Cluster NDB, la variante distribuée de MySQL. Oracle a sauté directement à MySQL 8.0 en 2018 pour éviter toute ambiguïté de numérotation.

  • MySQL 5.7

    Obsolète depuis oct. 2023

    Oct. 2015

    Version qui a introduit le type JSON natif et amélioré InnoDB de façon significative. Fin de support en octobre 2023 : tout projet encore sur MySQL 5.7 doit migrer immédiatement.

    • Type JSON natif
      Stockage optimisé et indexation de documents JSON directement dans InnoDB. Opérateurs ->, ->> et JSON_EXTRACT() pour accéder aux champs sans désérialiser.
    • Generated columns
      Colonnes virtuelles calculées depuis d'autres colonnes, indexables sans stockage physique (VIRTUAL) ou matérialisées (STORED). Utiles pour indexer un champ extrait d'un document JSON.
    • sys schema
      Base de données de diagnostic pré-installée avec des vues lisibles des tables performance_schema. Simplifie considérablement l'identification des requêtes lentes et des locks.
  • MySQL 5.6

    Obsolète

    Févr. 2013

    La version qui a modernisé InnoDB et introduit la réplication GTID. Plus maintenue depuis février 2021, cette version ne doit plus être utilisée en production.

    • Réplication GTID
      Les Global Transaction Identifiers simplifient la gestion des architectures de réplication en identifiant chaque transaction de façon unique sur tous les noeuds.
    • Online DDL
      Les ALTER TABLE s'exécutent sans verrouiller complètement la table en lecture. Les migrations de schéma sur des tables volumineuses deviennent moins risquées en production.
    • Full-text search InnoDB
      La recherche full-text étendue nativement à InnoDB (auparavant réservée à MyISAM). Utilisable pour la recherche textuelle sans solution tierce pour les volumes modérés.
  • MySQL 5.5

    Obsolète

    Déc. 2010

    La version qui a fait d'InnoDB le moteur par défaut, remplaçant définitivement MyISAM pour les tables transactionnelles. Introduction de la semi-synchronous replication et du Performance Schema.

    • InnoDB moteur par défaut
      InnoDB remplace MyISAM comme moteur de stockage par défaut. Transactions ACID, clés étrangères et récupération sur crash deviennent le standard MySQL.
    • Performance Schema
      Nouvelle base de données de monitoring avec des tables d'instrumentation du serveur. Ancêtre du sys schema de MySQL 5.7, orienté DBA plutôt que développeur.
  • MySQL 5.0

    Obsolète

    Oct. 2005

    Version majeure qui a apporté les fonctionnalités attendues d'un SGBDR professionnel : procédures stockées, vues et déclencheurs.

    • Procédures stockées
      Logique métier encapsulée côté base de données, exécutable via CALL. Réduit les allers-retours réseau sur les traitements complexes.
    • Vues (Views)
      Tables virtuelles basées sur des requêtes SELECT, permettant de simplifier l'accès aux données et de gérer les droits par vue.
    • Triggers
      Déclencheurs exécutés automatiquement sur INSERT, UPDATE ou DELETE. Utilisés pour l'audit, la dénormalisation automatique ou les contraintes complexes.
  • MySQL 4.0 / 4.1

    Obsolète

    2003-2004

    Introduction des sous-requêtes (4.1), de la commande UNION et de l'intégration optionnelle d'InnoDB. Première étape vers un SGBDR complet.

  • MySQL 3.23

    Obsolète

    2001

    Première version avec le support optionnel d'InnoDB et de MyISAM. Introduction de la réplication master-slave. Début de la popularisation sur les hébergements mutualisés.

Rester sur une version active de MySQL, c'est bénéficier des correctifs de sécurité et de la compatibilité avec les dernières versions de PHP et Doctrine ORM. Une version obsolète expose votre application à des vulnérabilités non corrigées et bloque les mises à jour de vos dépendances Symfony.

NOTRE USAGE

Comment nous utilisons MySQL chez SmartBooster

MySQL est au coeur de tous nos projets Symfony. Voici les trois piliers qui structurent notre usage au quotidien.

Entités et Repositories Doctrine

Chaque table MySQL correspond à une entité PHP annotée avec les attributs Doctrine. Le Repository associé centralise toutes les requêtes sur cette table. Cette séparation garantit que la logique de persistance ne se dilue pas dans les controllers ou les services.

Migrations versionnées (up/down)

Chaque modification de schéma génère un fichier de migration avec une méthode up() (applique le changement) et down() (annule le changement). Ces fichiers sont versionnés dans Git et déployés automatiquement en CI : la structure de la base reste toujours synchronisée avec le code, sans intervention manuelle.

Fixtures de développement

Des fixtures standardisées alimentent chaque environnement de développement avec des données cohérentes et reproductibles. Chaque développeur qui clone le projet rejoue les fixtures et retrouve immédiatement un état de base connu, sans dépendre d'un dump personnel.

MOTEURS DE STOCKAGE

InnoDB, MyISAM et les autres moteurs MySQL

MySQL supporte plusieurs moteurs de stockage interchangeables par table. En pratique, InnoDB est le seul choix pertinent pour les applications Symfony en production depuis MySQL 5.5 (2010).

Moteur Transactions ACID Clés étrangères Usage
InnoDB Oui Oui Moteur par défaut depuis MySQL 5.5. Le seul choix pour toute table applicative avec Symfony/Doctrine : transactions, contraintes d'intégrité et récupération après crash.
MyISAM Non Non Moteur historique, plus rapide en lecture pure sur les très vieilles versions MySQL, mais sans sécurité transactionnelle. A éviter sur tout nouveau projet.
MEMORY Non Non Données stockées en RAM, volatiles au redémarrage. Utile pour des tables temporaires dans des procédures stockées ou des caches intermédiaires.
ARCHIVE Non Non Stockage compressé en append-only, sans mise à jour ni suppression possible. Pour des journaux d'audit à très fort volume qu'on ne modifie jamais.

Doctrine ORM génère du DDL ((Data Definition Language) InnoDB par défaut. Si une table existante tourne sous MyISAM, une migration ALTER TABLE ... ENGINE=InnoDB suffit à la convertir.

ALTERNATIVES

MariaDB et Percona Server : les variantes de MySQL

MySQL officiel n'est pas la seule distribution. MariaDB et Percona Server sont deux variantes majeures, compatibles au niveau du protocole, mais avec des différences importantes à connaître avant de choisir son hébergeur.

Distribution Éditeur Compatibilité MySQL Particularité
MySQL officiel Oracle Référence Canal LTS et Innovation, support Oracle garanti. Version officielle de MySQL.
MariaDB MariaDB Foundation Haute mais diverge Fork créé en 2009 par Michael Widenius (le créateur originel de MySQL) après le rachat par Oracle. Diverge de plus en plus depuis MySQL 8.0 : certaines fonctionnalités récentes ne sont pas portées. Présent sur de nombreux hébergements mutualisés sous le label "MySQL" : vérifier avec SELECT VERSION().
Percona Server Percona 100% compatible Distribution MySQL avec des patches de performance, des outils de monitoring avancés et Percona XtraBackup pour les sauvegardes à chaud sans downtime. Binaire drop-in compatible avec MySQL officiel. Clever Cloud utilise Percona Server pour son add-on MySQL.

Source : Documentation Clever Cloud — Add-on MySQL (Percona Server) . Les dumps SQL (mysqldump) et Doctrine ORM fonctionnent de façon identique entre MySQL officiel, MariaDB et Percona Server.

BONNES PRATIQUES

Performance MySQL : les bases pour un développeur Symfony

Pas besoin d'être DBA pour éviter les pièges classiques. Ces règles couvrent 90 % des problèmes de performance rencontrés sur des applications Symfony en production.

A faire

Utiliser EXPLAIN avant d'optimiser

EXPLAIN SELECT ... révèle le plan d'exécution : type ALL signifie un full table scan (mauvais), ref ou range signifie qu'un index est utilisé (bon). MySQL 8.0+ : EXPLAIN ANALYZE donne les vrais temps d'exécution mesurés, pas juste le plan estimé.

A faire

Indexer les colonnes utilisées en WHERE et JOIN

Un index manquant force un full table scan sur chaque requête. Les colonnes de clé étrangère, de filtre (status, type) et de tri (created_at) doivent systématiquement être indexées. Avec Doctrine, l'attribut #[ORM\Index] sur l'entité génère l'index via la migration.

Erreur classique

Le N+1 en Doctrine

Charger 100 entités puis accéder à leur relation en lazy loading génère 101 requêtes MySQL. Solution : ->leftJoin('u.posts', 'p')->addSelect('p') dans le QueryBuilder pour charger les relations en une seule requête avec un JOIN.

Erreur classique

Enrober une colonne indexée dans une fonction

WHERE YEAR(created_at) = 2024 empêche l'utilisation de l'index sur created_at. Réécrire en plage de dates : WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01' pour que l'index B-tree soit exploité.

Erreur classique

SELECT * sur des entités volumineuses

Doctrine charge par défaut toutes les colonnes. Sur une liste, utiliser ->select('u.id, u.name') dans le QueryBuilder pour éviter de transférer des colonnes TEXT ou BLOB inutilement sur chaque ligne.

Erreur classique

LIKE '%texte%' ne peut pas utiliser un index

Un LIKE '%mot%' avec un joker en début de motif force un full table scan. Pour la recherche textuelle, préférer un index FULLTEXT avec MATCH AGAINST, ou Blackfire pour identifier les requêtes problématiques sur un volume réel.

STRATÉGIE D'INDEXATION

Comment choisir, positionner et nettoyer ses index

Un index manquant ralentit les lectures. Un index inutile ralentit les écritures. La bonne stratégie se construit sur les requêtes réelles, pas sur l'intuition.

1. Détecter avec le slow query log

Activer le slow query log pour enregistrer toutes les requêtes dépassant un seuil. C'est la source de vérité : on indexe ce qui est lent en production, pas ce qu'on suppose lent.

-- Activer en session (sans redémarrer MySQL)
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 0.5; -- en secondes
SET GLOBAL log_queries_not_using_indexes = 'ON';

L'outil pt-query-digest (Percona Toolkit) agrège le log et liste les requêtes les plus coûteuses en premier.

2. Radiographier avec EXPLAIN

EXPLAIN affiche le plan d'exécution sans exécuter la requête. La colonne type révèle si un index est utilisé.

type Lecture
const / refIndex utilisé, peu de lignes lues
rangeIndex sur une plage (BETWEEN, >, <)
ALLFull Table Scan : aucun index utilisé

EXPLAIN ANALYZE exécute réellement la requête et affiche les temps mesurés (MySQL 8.0+).

3. Quelles colonnes indexer en priorité

L'ordre de priorité pour les colonnes candidates à l'indexation :

  1. 1 WHERE : la colonne filtrée est la candidate principale. Plus elle est sélective, plus l'index est efficace.
  2. 2 JOIN ON : les colonnes de jointure sans index forcent un scan complet de la table jointe.
  3. 3 ORDER BY : un index sur la colonne de tri évite le tri en mémoire (filesort dans EXPLAIN).
  4. SELECT uniquement : une colonne présente seulement dans le SELECT ne bénéficie pas d'un index.

4. Index composite : la règle du préfixe gauche

Un index composite (status, created_at) sert les requêtes qui filtrent sur le préfixe gauche des colonnes.

WHERE status = 'published' utilise l'index
WHERE status = 'x' AND created_at > '2025' utilise l'index
WHERE created_at > '2025' pas d'index

Ordre dans l'index : colonne la plus sélective en premier. Tester avec EXPLAIN ANALYZE sur les données réelles avant de décider.

5. Pas toutes les combinaisons : le coût des index

Chaque index doit être mis à jour à chaque INSERT, UPDATE et DELETE. Un index a un coût en écriture, pas seulement en espace disque. Indexer seulement les requêtes qui apparaissent dans le slow query log ou dans les endpoints critiques mesurés.

Workflow recommandé

  1. 1.Activer le slow query log en production
  2. 2.Identifier les requêtes lentes avec pt-query-digest
  3. 3.EXPLAIN sur chaque requête problématique
  4. 4.Ajouter un index ciblé (Doctrine : #[ORM\Index])
  5. 5.Vérifier avec EXPLAIN ANALYZE

6. Nettoyer les index inutilisés

MySQL enregistre les statistiques d'utilisation des index dans performance_schema. La vue sys.schema_unused_indexes liste tous les index jamais utilisés depuis le dernier démarrage du serveur.

-- Index jamais utilisés depuis le démarrage
SELECT object_schema, object_name, index_name
FROM sys.schema_unused_indexes
WHERE object_schema = 'ma_base'
ORDER BY object_name;

-- Confirmer le non-usage avec le compteur brut
SELECT object_schema, object_name, index_name, count_star
FROM performance_schema.table_io_waits_summary_by_index_usage
WHERE index_name IS NOT NULL
  AND count_star = 0
  AND object_schema = 'ma_base'
ORDER BY object_name;

Précaution : les statistiques sont remises à zéro au redémarrage de MySQL. Observer sur une période représentative (idéalement plusieurs semaines en production) avant de supprimer un index.

Cas particulier : les index UNIQUE ne doivent jamais être supprimés sans vérifier les contraintes d'intégrité, même s'ils n'apparaissent pas dans les lectures.

BONNES PRATIQUES & DOCUMENTATION

Nos conventions MySQL

Documentation de référence pour l'équipe SmartBooster.

Se connecter à MySQL depuis un conteneur Docker

Dans nos projets Symfony, MySQL tourne dans un conteneur Docker. Pour ouvrir une session MySQL interactive depuis le poste de développement :

# Connexion au conteneur mysql, puis lancement du client MySQL
docker compose exec mysql mysql -u root -p

# Connexion directe en une commande (mot de passe via variable d'environnement)
docker compose exec mysql mysql -u app -papp app

Le troisième argument (app) est le nom de la base de données. Les identifiants sont définis dans le docker-compose.yml via les variables MYSQL_USER, MYSQL_PASSWORD et MYSQL_DATABASE.

Commandes MySQL utiles au quotidien

Une fois connecté au client MySQL, les commandes suivantes couvrent l'essentiel des besoins quotidiens :

Commande Explication
SHOW DATABASES; Liste toutes les bases de données accessibles avec l'utilisateur courant
USE nom_base; Sélectionne la base de données active pour les requêtes suivantes
SHOW TABLES; Liste les tables de la base de données active
DESCRIBE nom_table; Affiche la structure d'une table (colonnes, types, clés, valeurs par défaut)
SHOW CREATE TABLE nom_table\G Affiche le DDL complet de la table, utile pour auditer les index
SHOW FULL PROCESSLIST; Liste les requêtes en cours d'exécution, pour identifier les requêtes bloquantes
SHOW STATUS LIKE 'Slow%'; Compteurs de requêtes lentes depuis le démarrage du serveur

Analyser les requêtes lentes avec EXPLAIN

EXPLAIN est la commande clé pour diagnostiquer les problèmes de performance. Elle affiche le plan d'exécution choisi par l'optimiseur MySQL pour une requête donnée.

EXPLAIN SELECT * FROM commande WHERE client_id = 42 AND statut = 'en_cours';

Les colonnes à surveiller en priorité :

  • type : ALL signifie un full table scan (problème). ref, range ou const indiquent qu'un index est utilisé.
  • key : nom de l'index utilisé. NULL = pas d'index = problème.
  • rows : estimation du nombre de lignes scannées. Plus ce chiffre est proche du résultat attendu, mieux c'est.
  • Extra : Using filesort ou Using temporary sont des signaux de requêtes à optimiser.

EXPLAIN ANALYZE (MySQL 8.0+) exécute réellement la requête et retourne les temps d'exécution réels par étape, beaucoup plus précis que l'estimation de EXPLAIN seul.

Gestion des dumps SQL

Exporter une base de données (depuis le conteneur) :

docker compose exec mysql mysqldump -u root -p app > dump.sql

Exporter uniquement la structure (sans les données) :

docker compose exec mysql mysqldump -u root -p --no-data app > structure.sql

Restaurer un dump dans un conteneur :

docker compose exec -T mysql mysql -u root -p app < dump.sql

Le flag -T (sans TTY) est nécessaire pour la redirection stdin dans docker compose exec.

Commandes Doctrine au quotidien (Symfony)

Les migrations de schéma passent par Doctrine et non par MySQL directement. Les commandes bin/console à connaître :

# Générer une migration depuis les changements d'entités PHP
php bin/console doctrine:migrations:diff

# Appliquer les migrations en attente (à lancer avant chaque mise en production)
php bin/console doctrine:migrations:migrate

# Voir le statut des migrations (lesquelles sont appliquées, lesquelles sont en attente)
php bin/console doctrine:migrations:status

# Valider que le schéma en base correspond aux entités PHP (pratique en CI)
php bin/console doctrine:schema:validate

En développement local, doctrine:schema:update --force peut être utilisé pour synchroniser rapidement le schéma sans passer par les migrations. En environnement de recette ou production, utiliser exclusivement doctrine:migrations:migrate.

Pour aller plus loin

Documentation utile

Documentation officielle MySQL 9.7 LTS

Référence complète MySQL 9.7 LTS : Hypergraph optimizer, JavaScript UDF, JSON duality et PGO.

Documentation officielle MySQL 8.4 LTS

Référence complète MySQL 8.4 LTS : SQL, InnoDB, réplication, sécurité et performance.

endoflife.date/mysql : calendrier des versions

Dates de fin de support par version MySQL, mises à jour automatiquement par la communauté.

Pour aller plus loin

Approfondir votre réflexion

Doctrine ORM

Doctrine ORM mappe les entités PHP sur MySQL et génère les migrations de schéma. Relations, index, DQL et bonnes pratiques de performance documentés sur la page dédiée.

Docker

MySQL tourne dans un conteneur Docker sur tous nos projets. Notre stack symfony-docker intègre MySQL 8.4 avec un volume nommé pour la persistance des données.

Symfony

Symfony fournit le framework au-dessus de MySQL et Doctrine ORM. Les migrations Doctrine versionnent les évolutions de schéma directement dans Git.

Développement de logiciel sur mesure

MySQL equipe nos logiciels métier sur mesure : de la TPE avec quelques milliers de lignes aux plateformes à fort volume avec indexation avancée.

Vous avez un projet ?

Contactez-nous pour savoir comment nous pouvons vous aider.