Table des matières :
- Compatibilités à figer : versions MariaDB, paramètres serveur, drivers PHP
- MySQL vs MariaDB en 2026 : incompatibilités concrètes qui se voient en prod
- InnoDB partout : audit des tables, conversion, et effets de bord PrestaShop
- Collation UTF‑8 : utf8mb4, choix de collation et pièges d’index
- Stratégies de migration : dump/restauration, réplication, bascule et rollback
- Vérifications post-bascule : cohérence données, performance, slow queries et alerting
Les migrations MySQL → MariaDB sur une boutique PrestaShop cassent rarement “à cause de PrestaShop”. Elles cassent parce que l’écosystème (collations, moteurs de stockage, modes SQL, plugins d’auth, options InnoDB) n’a pas été figé avant bascule. Ce billet se concentre sur les prérequis système et les points de friction réels : MariaDB, InnoDB et collation UTF‑8 (utf8mb4), avec des commandes reproductibles.
Compatibilités à figer : versions MariaDB, paramètres serveur, drivers PHP
Commencez par figer une matrice de compatibilité réelle (et pas “ça devrait marcher”) : version PrestaShop, version PHP, version MariaDB, et connecteur (PDO/MySQLi). Sur PrestaShop 8.x et 9.x, le cœur reste très dépendant de comportements MySQL historiques (requêtes sans ONLY_FULL_GROUP_BY, conventions de collation, tailles d’index), donc les variations de defaults entre distributions MariaDB comptent. Pour une base de référence côté versions, appuyez-vous sur la page interne Exigences système : compatibilités PHP, MariaDB et Elasticsearch minimales.
Une bonne pratique simple : documentez noir sur blanc ce que vous allez figer, puis automatisez la vérification (même via un simple runbook). Exemple de matrice minimale à compléter :
| Élément | Source (prod actuelle) | Cible (staging/prod) | À valider |
|---|---|---|---|
| PrestaShop | 8.x / 9.x | 8.x / 9.x | Modules + overrides |
| PHP-FPM | 8.x | 8.x | Extensions pdo_mysql, intl, gd, zip… |
| Serveur DB | MySQL 5.7/8.0 | MariaDB 10.x/11.x | Auth, collations, sql_mode |
| Driver PHP | mysqlnd / libmysqlclient |
idem | Compat TLS + plugin auth |
| Charset/collation | utf8 / utf8mb4 |
utf8mb4 |
Uniformité base/tables/colonnes |
| Engine | InnoDB / mix | InnoDB | Tables “module” incluses |
Le prérequis le plus sous-estimé : vérifier que l’authentification et le client PHP supportent votre serveur cible. En pratique :
- PHP doit charger
pdo_mysql(et/oumysqli) avec un client compatible. - Sur un durcissement serveur, vous pouvez imposer TLS pour MariaDB (dans MariaDB c’est généralement géré via la configuration SSL du serveur et, selon votre politique, via des comptes configurés pour exiger SSL et/ou des proxies).
Validez côté application avec un test CLI minimal (même environnement que FPM) :
php -m | egrep 'pdo_mysql|mysqli'
php -r 'new PDO("mysql:host=127.0.0.1;dbname=prestashop;charset=utf8mb4","user","pass"); echo "ok\n";'
Complétez par deux contrôles qui évitent des surprises “incompréhensibles” le jour J :
1) Identifier le driver MySQL réellement utilisé côté PHP (mysqlnd vs lib cliente), utile pour anticiper certains comportements de TLS et d’authentification :
php -i | egrep -i 'mysqlnd|Client API version|PDO drivers'
2) Vérifier le plugin d’authentification côté MariaDB (certains plugins “exotiques” peuvent être incompatibles avec votre stack, surtout si vous durcissez) :
SELECT user, host, plugin
FROM mysql.user
ORDER BY user, host;
Enfin, fixez les variables serveur qui impactent directement PrestaShop : sql_mode, time_zone, max_allowed_packet, innodb_buffer_pool_size, innodb_flush_log_at_trx_commit, character_set_server, collation_server. Deux environnements “MariaDB 10.x” peuvent diverger fortement selon la distribution (Debian/Ubuntu/RHEL), l’image Docker, ou les fichiers *.cnf. Exportez un snapshot des variables sur l’existant, et comparez-le au futur :
SHOW VARIABLES WHERE Variable_name IN (
'version','version_comment','sql_mode','time_zone','max_allowed_packet',
'character_set_server','collation_server','innodb_file_per_table',
'innodb_default_row_format','innodb_strict_mode'
);
Deux points concrets “terrain” (souvent invisibles tant que vous n’avez pas un incident) :
- Fuseau horaire : beaucoup de serveurs tournent en UTC (
SYSTEM). Si vos équipes opèrent en France, fixertime_zone='Europe/Paris'(ou au minimum documenter UTC) évite des écarts dans les exports, rapprochements et analyses (ex. “commandes du jour” autour des changements d’heure). - Paquets et imports : si vous avez des imports produits volumineux (CSV/ERP) ou des logs modules qui gonflent,
max_allowed_packettrop bas provoque des erreurs intermittentes (“MySQL server has gone away”). Ce n’est pas une optimisation : c’est un garde-fou.
MySQL vs MariaDB en 2026 : incompatibilités concrètes qui se voient en prod
Dire “MariaDB est compatible MySQL” n’est utile que si vous listez ce qui ne l’est pas. La première zone grise, c’est la sémantique des types et fonctions : par exemple, JSON n’a pas la même implémentation (selon versions, MariaDB traite JSON comme un alias/validation sur LONGTEXT + fonctions associées), et des fonctions JSON diffèrent (noms, comportements, indexation). Beaucoup de modules PrestaShop n’utilisent pas JSON dans le schéma core, mais certains modules (tracking, feed, connecteurs) oui : faites un grep SQL des schémas/modules avant migration.
Mini-audit rapide (utile sur un dump ou directement sur la prod, en lecture seule) :
-- Colonnes "JSON" (ou équivalents) dans le schéma
SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, COLUMN_TYPE
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND (DATA_TYPE = 'json' OR COLUMN_TYPE LIKE '%json%')
ORDER BY TABLE_NAME, COLUMN_NAME;
Deuxième point : collations et règles de tri. MySQL 8 a introduit des collations utf8mb4_0900_* basées sur UCA 9.0, alors que MariaDB a ses propres collations (par ex. utf8mb4_unicode_ci, utf8mb4_unicode_520_ci). Si vous migrez depuis MySQL 8 vers MariaDB, une restauration brute peut échouer à cause d’une collation inconnue côté MariaDB. Prérequis : décider d’une collation commune et la normaliser avant dump/restauration (section dédiée plus bas).
Troisième point : modes SQL et requêtes “tolérées”. PrestaShop et ses modules font encore circuler des requêtes qui passent sur un serveur permissif et explosent sur un serveur strict (typiquement ONLY_FULL_GROUP_BY, insertions implicites, conversions silencieuses). Si vous voulez réduire les surprises, alignez sql_mode au plus près de la production actuelle, puis remontez graduellement le niveau de strictness dans un cycle séparé. Pour travailler côté requêtes et schémas, l’article interne Développeur MySQL : optimiser requêtes, schémas et performances en production est un bon complément.
Deux incompatibilités supplémentaires (souvent rencontrées lors des migrations “système”, même quand PrestaShop va bien) :
- Outils clients MySQL 8 → serveur MariaDB : si votre poste/CI utilise
mysqldumpd’un client MySQL 8, vous pouvez déclencher des options non supportées par MariaDB (ex. statistiques de colonnes). C’est un problème d’outillage, pas de données. - Réplication et GTID : MySQL et MariaDB ont des implémentations et des paramètres GTID différents. Si vous visez une migration “quasi sans downtime” par réplication, vous devez tester très tôt (format binlog, compat des événements, options GTID) et documenter le chemin exact.
Enfin, point de cadrage important : InnoDB est le moteur de stockage par défaut et le plus largement couvert en production. Cela se traduit directement en migrations : si votre historique contient encore du MyISAM, vous réduisez drastiquement le risque en convergeant vers InnoDB.
InnoDB partout : audit des tables, conversion, et effets de bord PrestaShop
Le prérequis InnoDB n’est pas idéologique, il est opérationnel : verrous ligne-à-ligne, crash recovery, contraintes de transaction, et comportement plus stable sous charge (checkout + indexation + facettes). Sur une boutique avec pics de trafic et import massif, MyISAM transforme vite le serveur en goulot (verrou table global) et dégrade la latence. Si vous êtes déjà dans une démarche perf, vous pouvez mettre ça en perspective avec PrestaShop performance : optimiser gros catalogues et Core Web Vitals.
Auditez d’abord l’existant : quelles tables ne sont pas en InnoDB, et lesquelles sont critiques (commandes, paniers, index de recherche, logs) ?
SELECT TABLE_SCHEMA, TABLE_NAME, ENGINE, TABLE_ROWS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND ENGINE <> 'InnoDB'
ORDER BY ENGINE, TABLE_NAME;
Avant de convertir, prenez 5 minutes pour évaluer l’impact (c’est souvent là que les projets dérapent) :
- Espace disque : une conversion peut nécessiter de la place temporaire (reconstruction d’index, copie). Sur VM/volumes contraints, vous pouvez vous retrouver “à court” au milieu d’un
ALTER. - Fenêtre : une table de logs de plusieurs dizaines de millions de lignes peut monopoliser l’I/O sans être “métier”. Parfois, la bonne décision est de purger/archiver avant conversion.
- Verrous : selon version MariaDB et opérations,
ALTER TABLEpeut locker plus ou moins. Si votre boutique tourne encore, planifiez.
Ensuite, convertissez de manière contrôlée. Sur une base de taille moyenne, un ALTER TABLE ... ENGINE=InnoDB; suffit. Sur une base volumineuse, prévoyez une fenêtre de maintenance et un plan de rollback : la conversion peut être longue (copie de table, reconstruction d’indexes) et consommer disque + I/O. Exemple de conversion (à exécuter table par table, pas en “shotgun” si vous ne maîtrisez pas l’impact) :
ALTER TABLE ps_connections ENGINE=InnoDB;
ALTER TABLE ps_cart ENGINE=InnoDB;
ALTER TABLE ps_orders ENGINE=InnoDB;
Vous pouvez prioriser intelligemment avec une liste “métier d’abord” (commandes/paniers), “performance ensuite” (recherche), et “hygiène” (tables d’audit, stats, tracking) en dernier.
Points d’attention spécifiques PrestaShop :
1) FULLTEXT : InnoDB supporte FULLTEXT depuis MySQL 5.6 et MariaDB depuis longtemps, mais les settings (innodb_ft_min_token_size, stopwords) et la qualité du corpus influencent vos résultats. Si vous touchez à ces paramètres, attendez-vous à devoir reconstruire l’index de recherche PrestaShop. En pratique, sur une boutique française, les stopwords et la taille minimale des tokens changent fortement la pertinence sur des requêtes courtes (ex. “XL”, “TV”, “bio”).
2) Row format / taille d’index : si vous migrez depuis un MySQL ancien, vous avez peut-être des dépendances implicites à COMPACT/REDUNDANT ou à des limites d’index avec utf8mb4. Sur MariaDB moderne, ROW_FORMAT=DYNAMIC et innodb_file_per_table=ON simplifient la vie (mais validez les defaults de votre distribution). Sur des environnements historiques, la limite d’index plus faible combinée à utf8mb4 est une cause classique d’échec lors d’un ALTER TABLE ... CONVERT TO CHARACTER SET.
3) Durabilité vs performance : innodb_flush_log_at_trx_commit=1 est le réglage durable (fsync à chaque commit), mais coûteux sur stockage SATA/virtio “mou”. Sur e-commerce, baisser à 2 peut réduire la latence write, mais augmente le risque de perte de transactions en cas de crash. Décidez ça explicitement avec votre RPO/RTO, pas au hasard.
Checklist “prérequis InnoDB” (rapide, utile en runbook) :
- [ ]
innodb_file_per_tableactivé (attendu sur MariaDB modernes, mais à confirmer) - [ ]
innodb_buffer_pool_sizedimensionné (serveur dédié DB : souvent la majorité de la RAM, en laissant de la marge à l’OS) - [ ]
innodb_default_row_formatcohérent (éviter les surprises sur de nouvelles tables) - [ ] toutes les tables applicatives en InnoDB (y compris celles des modules critiques)
Collation UTF‑8 : utf8mb4, choix de collation et pièges d’index
Si votre objectif est “UTF‑8”, traduisez-le en MySQL/MariaDB : charset utf8mb4 (4 octets) + une collation cohérente. L’erreur classique : rester en utf8 (3 octets) et découvrir plus tard que certains caractères (emoji, certains symboles, caractères hors BMP) se corrompent ou sont rejetés. En 2026, utf8mb4 n’est pas un “nice to have” : c’est un prérequis pour éviter des données incohérentes dans des champs “libres” (avis, messages SAV, attributs personnalisés, imports).
Le choix de collation doit être pragmatique : il vous faut une collation supportée par MariaDB et compatible avec vos dumps. Pour des migrations MySQL 5.7/8.0 → MariaDB, utf8mb4_unicode_ci reste un choix robuste (tri Unicode raisonnable, compatibilité large). Si vous partez de MySQL 8 en utf8mb4_0900_ai_ci, prévoyez une étape de normalisation (MySQL → collation “commune”) avant restauration sur MariaDB, sinon vous aurez des erreurs du type Unknown collation.
Pour aller plus loin sur le support des jeux de caractères et collations côté MariaDB (liste et comportements), la documentation officielle est la référence : Documentation MariaDB : jeux de caractères et collations
Cas d’usage concret (souvent rencontré en e-commerce FR) : tri et recherche sur des libellés avec accents. Une collation Unicode “correcte” réduit les comportements contre-intuitifs entre “cote”, “côté”, “côte” (comparaison et tri), surtout quand vous avez des exports, des facettes, ou des règles de prix basées sur des libellés importés. L’objectif n’est pas la perfection linguistique, mais la cohérence entre environnements.
Audit rapide : base, tables, colonnes (ce sont souvent les colonnes qui divergent via des ALTER TABLE passés par des modules) :
-- Charset/collation par base
SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME = DATABASE();
-- Collations par table
SELECT TABLE_NAME, TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
ORDER BY TABLE_COLLATION, TABLE_NAME;
-- Collations par colonne (focus texte)
SELECT TABLE_NAME, COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME, COLUMN_TYPE
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND CHARACTER_SET_NAME IS NOT NULL
ORDER BY COLLATION_NAME, TABLE_NAME;
Astuce utile : quantifiez plutôt que “survoler”. Par exemple, compter les colonnes hors standard :
SELECT COLLATION_NAME, COUNT(*) AS nb_colonnes
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND COLLATION_NAME IS NOT NULL
GROUP BY COLLATION_NAME
ORDER BY nb_colonnes DESC;
Conversion contrôlée (exemple) :
1) Fixez les defaults (nouveaux objets) :
ALTER DATABASE prestashop
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
2) Convertissez table par table (reconstruit les colonnes textuelles + indexes) :
ALTER TABLE ps_product
CONVERT TO CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
3) Vérifiez les indexes trop longs : utf8mb4 augmente la taille en octets, donc certains indexes “au bord” peuvent dépasser la limite (selon format et version). Sur PrestaShop, ça se voit surtout sur des colonnes VARCHAR(255) indexées (URL rewrites, meta, champs custom). Le correctif est parfois de réduire la longueur indexée (INDEX(col(191))) ou de revoir le schéma du module fautif. Ne “réparez” pas en repassant en utf8_general_ci : vous masquez le problème au lieu de le résoudre.
Mini-scénario typique : vous migrez une boutique avec un module SEO qui a créé un index sur meta_title VARCHAR(255) en utf8. Le passage en utf8mb4 casse l’ALTER TABLE (index trop long) → vous bloquez la migration “sur une table module”, pas sur le cœur PrestaShop. D’où l’intérêt de faire l’audit avant le jour de bascule.
Stratégies de migration : dump/restauration, réplication, bascule et rollback
Avant de parler commandes : le prérequis est une stratégie de migration compatible avec vos contraintes (downtime acceptable, taille DB, fenêtre de gel, possibilité de double-écriture). Pour une boutique en croissance, arrêtez de penser “copier/coller une DB” : vous voulez une bascule maîtrisée, idéalement blue/green avec rollback. Référence interne utile : Migration PrestaShop : audit technique et plan incrémental blue/green et, pour la discipline rollback, Migration PrestaShop 9 : sécurité, tests et plan de rollback.
Pour une migration “simple” (DB < quelques dizaines de Go, downtime accepté), le dump logique reste le plus portable :
# côté source (MySQL)
mysqldump \
--single-transaction --routines --triggers --events \
--hex-blob --default-character-set=utf8mb4 \
--set-gtid-purged=OFF \
--databases prestashop \
| gzip -1 > prestashop.sql.gz
# côté cible (MariaDB)
gzip -dc prestashop.sql.gz | mariadb --binary-mode=1
# post-restore (MariaDB)
mysql_upgrade
Si votre client mysqldump est en MySQL 8 (très fréquent sur des runners CI récents) et que vous restaurez vers MariaDB, ajoutez souvent ces options préventives (elles évitent des erreurs qui ressemblent à des incompatibilités “mystiques”) :
--column-statistics=0: désactive les statistiques de colonnes ajoutées par défaut dans certains clients MySQL 8.--no-tablespaces: utile quand des informations de tablespaces posent problème à l’export/import (selon versions/outils).
Exemple (à adapter à votre contexte) :
mysqldump \
--single-transaction --routines --triggers --events \
--hex-blob --default-character-set=utf8mb4 \
--set-gtid-purged=OFF \
--column-statistics=0 --no-tablespaces \
--databases prestashop \
| gzip -1 > prestashop.sql.gz
Trois pièges récurrents :
- Collations MySQL 8 non supportées : si votre dump contient
utf8mb4_0900_ai_ci, la restauration cassera. Normalisez avant le dump, ou utilisez un filtre (avec prudence) pour remplacer la collation dans le SQL. - Données volumineuses (logs, connexions, stats) : un dump logique peut exploser le temps de maintenance. Avant migration, purge/archivage peut être rationnel (sans toucher aux tables métier). L’outil MedCleanMyShop peut aider côté nettoyage, mais à utiliser avec un audit et des backups : MedCleanMyShop
- Temps de lock applicatif : passez PrestaShop en maintenance, stoppez les cron et workers (imports, sync, feeds), et bloquez toute écriture (webhooks, ERP) le temps de la dernière synchronisation.
Conseil “process” (souvent décisif) : planifiez une répétition générale sur un environnement staging représentatif (même taille d’index, mêmes modules, même version PHP). Mesurez :
- durée dump + transfert + import,
- pics CPU/IO pendant
ALTER(collation/engine), - et temps de réchauffement des caches (après bascule).
Pour une base plus grosse ou un downtime quasi nul : répliquez (ou sync) jusqu’à un point de coupure, puis basculez. Selon versions, MySQL → MariaDB en réplication n’est pas “plug and play” (formats binlog, GTID, fonctions), donc testez en staging et documentez les contraintes. Si vous ne pouvez pas garantir une réplication fiable, revenez à une stratégie blue/green avec freeze court + dump incrémental (ou double-run des imports) : c’est souvent plus simple à sécuriser.
Vérifications post-bascule : cohérence données, performance, slow queries et alerting
Après restauration, faites une vérification de cohérence avant d’ouvrir le trafic. À minima : comptez les lignes sur les tables cœur (produits, déclinaisons, commandes), contrôlez les encodages, et vérifiez que les routines/triggers ont bien été importés. mysqlcheck est utile pour un sanity check (sans prétendre à une preuve formelle) :
mysqlcheck --databases prestashop --check-upgrade --auto-repair
Ajoutez quelques vérifications SQL “ciblées” qui détectent vite les régressions de prérequis (InnoDB/utf8mb4) :
-- Tables non InnoDB (doit retourner 0 ligne si vous avez standardisé)
SELECT TABLE_NAME, ENGINE
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND ENGINE <> 'InnoDB';
-- Collations "exotiques" (à adapter à votre standard)
SELECT TABLE_NAME, TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_COLLATION NOT IN ('utf8mb4_unicode_ci');
-- Variables de base (tracez-les dans le runbook)
SELECT @@version, @@sql_mode, @@time_zone, @@character_set_server, @@collation_server;
Côté application, validez des scénarios d’écriture/lecture qui touchent les zones les plus fragiles : création panier, commande, paiement (sandbox), génération facture, emails, réindexation recherche, back-office (filtres, exports). Si vous utilisez des modules qui injectent beaucoup de requêtes, activez temporairement un niveau de logs plus verbeux et surveillez les erreurs SQL. Pour un socle d’observabilité PrestaShop (PHP/MySQL/JS), voir PrestaShop monitoring d’erreurs : logs PHP, MySQL, JavaScript et alertes e-mail.
La migration DB est aussi un moment parfait pour instrumenter la perf. Activez le slow query log (sur un périmètre contrôlé), et corrigez les requêtes réellement coûteuses au lieu de “tuner au pif” la RAM. Procédure côté PrestaShop : Activer le slow query log ; et côté profiling SQL applicatif : PrestaShop debug & profiling
Un réflexe utile après import (surtout si vous avez fait beaucoup d’ALTER/rebuild) : exécuter un ANALYZE TABLE sur quelques tables critiques pour aider l’optimiseur à repartir sur des stats propres (à planifier hors pic si la table est énorme). Exemple :
ANALYZE TABLE ps_product, ps_product_lang, ps_stock_available, ps_orders, ps_order_detail;
Enfin, ne laissez pas la collation et InnoDB “implicites”. Déclarez explicitement vos defaults (charset/collation) dans la création de base, documentez-les dans le runbook, et ajoutez un test de conformité (CI ou script d’audit) qui échoue si une nouvelle table repasse en MyISAM ou en collation exotique. Une boutique qui accepte des régressions de moteur/collation via un module installé à la va-vite finit toujours par payer la facture… au pire moment (migration majeure, scaling, incident).
