Retour Experience Migration Mysql
Retour d’expérience : migrer un socle MySQL 5.5/5.6 vers MySQL 8.4
J’ai récemment participé à une migration MySQL qui avait tout du “simple upgrade” sur le papier, et tout d’un vrai chantier de modernisation dans la réalité.
Le point de départ : plusieurs instances legacy, sous Windows, en MySQL 5.5 et 5.6, avec des historiques de configuration différents, de la réplication, des schémas applicatifs critiques, et une exigence forte de continuité de service.
Le vrai sujet n’était pas d’installer MySQL 8.4. Le vrai sujet consistait à rendre explicite tout ce que l’existant avait normalisé implicitement au fil des années. Cela recouvrait des options obsolètes, des encodages hétérogènes, des reliquats MyISAM, des objets SQL avec DEFINER, des tests de reprise incomplets, ainsi que des environnements hors production ayant besoin de données réalistes sans exposer de données sensibles.
En bref
Cette migration m’a rappelé trois choses simples :
- une migration 5.x vers 8.x n’est pas un copier-coller de
my.ini - il faut dissocier la montée de version des autres transformations risquées
- la réussite se joue autant sur l’exploitation (monitoring, sauvegarde, restauration, rollback) que sur le SQL lui-même
Le contexte technique de départ
Avant de parler cible, nous avons commencé par inventorier l’existant.
Le plus important : il n’y avait pas un legacy, mais plusieurs. Chaque instance racontait une histoire différente. On retrouvait notamment :
- des versions 5.5 et 5.6 cohabitant encore
- des configurations avec
latin1comme encodage serveur historique - du
query_cache, dessql_modeanciens, des options disparues en 8.x, et des réglages mémoire hérités d’une autre époque - une volumétrie de connexions élevée côté applicatif
- des schémas hétérogènes avec InnoDB majoritaire, mais aussi du MyISAM résiduel
- des routines et des vues qui embarquaient des
DEFINERexplicites - des environnements de secours et de pré-production qu’il fallait réaligner avec une vraie stratégie de validation
Autrement dit : la montée de version n’était que la partie visible du problème.
Pourquoi nous avons choisi une migration logique
À ce niveau d’écart de versions, je n’avais pas envie de “parier” sur un upgrade in-place. Nous avons donc retenu une approche plus contrôlable :
- inventorier précisément les instances, leur configuration et leurs objets SQL ;
- installer une cible propre en MySQL 8.4 ;
- migrer par exports/rechargements logiques ;
- valider sur un enchaînement recette -> pré-production -> production ;
- documenter le mode opératoire et le rollback avant la bascule finale.
Le point clé, c’est la séparation des sujets. Un dump logique permet de revoir ce qu’on remonte réellement sur la cible. En pratique, cela évite de transporter aveuglément des hypothèses legacy qui ne sont plus valables.
C’est particulièrement vrai pour les objets système. Quand on migre depuis de vieilles versions, la tentation est grande de tout déplacer “tel quel”. En réalité, il faut traiter à part :
- les schémas applicatifs ;
- les comptes et privilèges ;
- les objets stockés (routines, vues, triggers éventuels) ;
- les éléments d’exploitation comme la sauvegarde, les binlogs et la supervision.
Une base mysql issue d’un 5.x n’a pas vocation à devenir un simple artefact réimporté tel quel sur une 8.x. C’est une source d’inventaire, pas un plan de restauration naïf.
Le premier vrai chantier : repartir d’une configuration saine
Le piège classique sur ce type de projet, c’est de prendre le my.ini existant et d’essayer de le “faire rentrer” dans la nouvelle version.
C’est exactement ce qu’il ne faut pas faire.
Une configuration legacy contient souvent un mélange de :
- réglages encore utiles ;
- réglages tolérés mais obsolètes ;
- réglages supprimés ;
- réglages devenus contre-productifs ;
- réglages qui traduisaient surtout les contraintes matérielles ou logicielles du moment où le serveur a été installé.
Sur ce chantier, la bonne approche a été de repartir d’une base propre côté MySQL 8.4, puis de ne réinjecter que ce qui avait encore un sens : chemins, stratégie de binlogs, politique de sauvegarde, paramètres de capacité, conventions d’instance, comptes techniques, sécurité, etc.
Le bénéfice est énorme : on migre vers une cible cohérente, pas vers une copie modernisée du désordre existant.
Deuxième chantier : ne pas empiler toutes les transformations risquées
Quand on hérite d’un socle ancien, on a souvent envie de “tout remettre d’équerre” d’un coup : version, charset, collations, moteurs, comptes, requêtes, observabilité, sécurité…
C’est tentant. C’est aussi une excellente manière de rendre le diagnostic impossible en cas d’écart.
L’une des décisions les plus utiles a été de dissocier les sujets :
- d’abord sécuriser la montée de version ;
- ensuite traiter progressivement les modernisations fonctionnelles ou structurelles.
Typiquement, quand un patrimoine mélange latin1 côté serveur historique, des tables en utf8, et des conventions applicatives parfois implicites, il faut résister à la tentation du “grand soir UTF-8”. La conversion d’encodage peut être un projet à part entière.
Même logique pour MyISAM : lorsqu’il reste quelques tables non InnoDB, il faut les inventorier et décider explicitement de leur sort. Pas les convertir par réflexe pendant la même fenêtre que la migration de version, sauf si le périmètre est parfaitement maîtrisé.
J’essaie désormais d’appliquer une règle simple : stabiliser d’abord, moderniser ensuite.
Troisième chantier : nettoyer les objets SQL qui cassent silencieusement
Sur les migrations importantes, les problèmes les plus pénibles ne viennent pas toujours des grosses tables. Ils viennent souvent des détails “invisibles” dans les objets SQL :
DEFINERliés à des comptes qui n’existeront plus tels quels ;- vues dépendantes d’un contexte de privilèges historique ;
- routines stockées qui supposent une configuration antérieure ;
- identifiants devenus sensibles à des changements de mots réservés ;
- dates nulles ou valeurs historiques qui passaient autrefois, mais deviennent problématiques avec des modes stricts plus modernes.
C’est là qu’un simple dump de schéma devient précieux. On peut l’analyser hors ligne, faire des imports à blanc, corriger, rejouer, puis industrialiser.
Le trio d’outils qui nous a le plus aidés sur cette phase a été très simple :
pt-mysql-summary > instance.aud
mysqldump --no-data --routines --triggers --events --all-databases > schema.sql
Puis un audit ciblé du dump et de la configuration, par exemple :
grep -E "DEFINER|0000-00-00|ENGINE=MyISAM|CHARSET|COLLATE" schema.sql
grep -E "query_cache|NO_AUTO_CREATE_USER|table_cache|innodb_additional_mem_pool_size" my.ini
Ce n’est pas “spectaculaire”, mais c’est le genre de travail qui évite les erreurs les plus coûteuses en recette et en production.
Quatrième chantier : performance et exploitation dès la recette
Un autre enseignement important : la performance ne se traite pas après le succès de l’import.
Sur un socle 5.x, certains comportements applicatifs ont parfois vécu des années avec des béquilles historiques : query_cache, tolérance à certaines requêtes peu optimisées, plans d’exécution jamais remis en question, paramètres mémoire calibrés pour une charge ancienne, etc.
Une fois en MySQL 8.x, certaines de ces habitudes ne tiennent plus. C’est normal. Le danger consiste à découvrir cela trop tard.
Nous avons donc traité très tôt :
- les tests de non-régression applicative ;
- les batchs les plus coûteux ;
- le monitoring ;
- les logs utiles au diagnostic ;
- les premiers ajustements de paramétrage avancé ;
- les vérifications de reprise et de redémarrage.
En pratique, cela veut dire que la recette doit déjà ressembler à de l’exploitation, pas seulement à une preuve que le serveur démarre.
Cinquième chantier : une bascule ne vaut rien sans restauration testée
C’est probablement le point le plus sous-estimé dans les projets de migration.
Avoir des sauvegardes n’est pas suffisant. Avoir une procédure de restauration testée change tout.
Sur ce chantier, la logique de sécurisation s’est construite autour de plusieurs garde-fous :
- snapshots avant les étapes sensibles ;
- environnement de recette validé avant clonage vers la pré-production ;
- mise en place ou réalignement de la réplication quand cela avait du sens ;
- campagne de tests de résilience ;
- validation du restore avant la bascule finale ;
- synthèse GO / NO-GO fondée sur des vérifications concrètes.
J’en retiens une leçon très simple : un secondaire, un snapshot ou une sauvegarde ne sont pas un plan de retour arrière tant qu’ils n’ont pas été vérifiés en conditions proches du réel.
Sixième chantier : profiter de la migration pour remettre à plat la donnée hors production
Ce projet a aussi été l’occasion de traiter un sujet que beaucoup d’équipes repoussent : la qualité des données en recette et en pré-production.
On veut des données réalistes pour tester correctement. Mais on ne veut pas exposer inutilement des données sensibles hors production.
Nous avons donc ajouté un chantier d’anonymisation / pseudonymisation piloté par la structure des données :
- mapping stable pour les identifiants utilisés en clé primaire / clé étrangère ;
- génération aléatoire pour certains emails, dates ou identifiants secondaires ;
- dictionnaires pour les noms et champs assimilés ;
- constantes anonymisées pour certains textes ou messages non structurés ;
- conservation raisonnée pour les champs réellement non sensibles et utiles aux tests.
Cette approche a deux vertus.
La première : elle réduit le risque sur les environnements hors production.
La seconde : elle rend les refresh plus industrialisables. On ne dépend plus d’une copie “tolérée” de la production ; on construit une chaîne de données de test plus propre.
Ce qui a le plus fait la différence
Avec le recul, la réussite n’a pas tenu à une commande magique. Elle a tenu à quelques principes d’exécution assez basiques, mais appliqués sérieusement :
- faire l’inventaire avant de concevoir la cible ;
- repartir d’une configuration propre au lieu de porter le legacy tel quel ;
- séparer montée de version, conversion d’encodage et refonte moteur ;
- tester les objets SQL cachés, pas seulement les tables ;
- intégrer monitoring, sauvegarde et restauration dans le plan de migration ;
- faire plusieurs répétitions avant la bascule finale ;
- écrire le mode opératoire pendant le projet, pas la veille de la mise en production.
Ce que je referais exactement de la même manière
Si je devais recommencer demain, je referais sans hésiter ces choix :
- audit initial par instance avec croisement configuration + dump de schéma + lecture d’exploitation ;
- cible 8.4 reconstruite proprement ;
- migration logique plutôt que transplantation brutale ;
- validation en plusieurs étages ;
- tests de restauration avant la production ;
- traitement de la donnée hors prod comme un vrai sujet d’architecture, pas comme un détail de conformité.
Conclusion
Ce type de migration n’est pas seulement une montée de version. C’est un exercice de clarification.
On découvre ce qui, dans le legacy, relevait :
- d’un vrai besoin métier ;
- d’une dette technique acceptable ;
- d’un contournement devenu inutile ;
- d’une fragilité que tout le monde avait fini par considérer comme normale.
C’est aussi pour cela que ce genre de chantier est intéressant. Bien mené, il ne se contente pas de passer en MySQL 8.4. Il remet à plat l’exploitation, la qualité de la recette, les hypothèses applicatives, et la manière dont on prépare les changements à risque.
Et au fond, c’est probablement la meilleure définition d’une migration réussie : la nouvelle version n’est pas juste plus récente, elle est plus compréhensible, plus testable et plus exploitable.