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.
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.
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éeAvr. 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.
- Hypergraph optimizer (GA)
-
MySQL 9.0 → 9.6
Obsolète depuis avr. 2026Juil. 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.
- Vector Type natif
-
MySQL 8.4 LTS
Support actif avr. 2029Avr. 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.
- Support LTS 8 ans
-
MySQL 8.1 → 8.3
Obsolète depuis avr. 2024Juil. 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. 2026Avr. 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.
- Roles et gestion des droits
-
MySQL 6 et 7
Versions inexistantesNon 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. 2023Oct. 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.
- Type JSON natif
-
MySQL 5.6
ObsolèteFé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.
- Réplication GTID
-
MySQL 5.5
ObsolèteDé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.
- InnoDB moteur par défaut
-
MySQL 5.0
ObsolèteOct. 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.
- Procédures stockées
-
MySQL 4.0 / 4.1
Obsolète2003-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ète2001
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 / ref | Index utilisé, peu de lignes lues |
| range | Index sur une plage (BETWEEN, >, <) |
| ALL | Full 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 WHERE : la colonne filtrée est la candidate principale. Plus elle est sélective, plus l'index est efficace.
- 2 JOIN ON : les colonnes de jointure sans index forcent un scan complet de la table jointe.
- 3 ORDER BY : un index sur la colonne de tri évite le tri en mémoire (
filesortdans EXPLAIN). - ✕ 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.Activer le slow query log en production
- 2.Identifier les requêtes lentes avec pt-query-digest
- 3.EXPLAIN sur chaque requête problématique
- 4.Ajouter un index ciblé (Doctrine :
#[ORM\Index]) - 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
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
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
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 :
ALLsignifie un full table scan (problème).ref,rangeouconstindiquent 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 filesortouUsing temporarysont 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
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)
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
Référence complète MySQL 9.7 LTS : Hypergraph optimizer, JavaScript UDF, JSON duality et PGO.
Référence complète MySQL 8.4 LTS : SQL, InnoDB, réplication, sécurité et performance.
Dates de fin de support par version MySQL, mises à jour automatiquement par la communauté.
Pour aller plus loin
Approfondir votre réflexion
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.
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 fournit le framework au-dessus de MySQL et Doctrine ORM. Les migrations Doctrine versionnent les évolutions de schéma directement dans Git.
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.