Voici venu le temps de mettre à jour MySQL 8.0 vers MySQL 8.4 LTS sur notre serveur Ubuntu 24.04 Noble, pour plus de performance, sécurité et stabilité.
Changements clés entre MySQL 8.0 et MySQL 8.4 LTS
Vue d’ensemble
MySQL 8.4 est une version LTS (Long Term Support) donc la cadence des mises à jour est stable, continue, avec peu de ruptures.
Sécurité et authentification
mysql_native_password
désactivé par défaut. Le plugin existe encore, mais n’est plus chargé en 8.4. Résultat : les comptes qui l’utilisent échouent à l’authentification jusqu’à ce que vous le réactiviez (temporaire) ou que vous migriez les comptes verscaching_sha2_password
.- Paramètres changent : l’ancien
default_authentication_plugin
est retiré ; utilisez désormais la politique d’authentification actuelle (et migrez les comptes).
Outils et commandes retirés / modifiés
- Retirés :
mysql_upgrade
(mise à niveau du dictionnaire gérée automatiquement au démarrage du serveur) etmysqlpump
(préférezmysqldump
ou les utilitaires de MySQL Shell). - Terminologie réplication : nettoyage achevé (adieu les anciennes commandes “master”). Utilisez les variantes modernes (
SHOW BINARY LOG STATUS
, etc.).
InnoDB et perfs (nouveaux défauts)
8.4 affine plusieurs valeurs par défaut pour mieux coller au matériel actuel (I/O, concurrency). Attendez-vous à des valeurs plus agressives pour la capacité I/O et des toggles historiques coupés par défaut (ex. Adaptive Hash Index OFF). Vérifiez vos overrides côté mysqld.cnf
.
SQL, DDL & privilèges
- Interdiction définitive :
AUTO_INCREMENT
surFLOAT/DOUBLE
— toléré (déprécié) en 8.0, erreur en 8.4. Corrigez avant de migrer (changez de type ou retirez l’AUTO_INCREMENT). - Nouveaux privilèges plus fins :
SET_ANY_DEFINER
etALLOW_NONEXISTENT_DEFINER
remplacent l’ancienSET_USER_ID
(retiré). Utile pour sécuriser routines/triggers avec DEFINER.
LTS : ce que ça change opérationnellement
Les versions 8.4.x apportent surtout des corrections et des ajustements à faible risque. Les notes de version par point release (8.4.4, 8.4.5, 8.4.6…) détaillent les bugfixes et micro-améliorations.
Checklist de migration de MySQL 8.0 vers MySQL 8.4
1. Audit pré-upgrade
- Lisez la page « What’s new in 8.4 since 8.0 » et la section “Changes in MySQL 8.4” pour repérer ce qui casse chez vous (options retirées, syntaxes interdites).
- Cherchez
AUTO_INCREMENT
surFLOAT/DOUBLE
dans votre schéma et corrigez. - Passez un coup d’œil à vos
my.cnf
: supprimezdefault_authentication_plugin
, autres options dépréciées 8.0, et adaptez si besoin.
2. Authentification (le vrai sujet qui casse les apps)
Option A (transitoire) : réactivez le plugin legacy pour rallumer vite vos apps, puis migrez proprement:
# nano /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
mysql_native_password=ON
Code language: PHP (php)
Redémarrez MySQL, puis planifiez la migration de tous les comptes vers caching_sha2_password
.
Option B (propre, recommandée) : migrez chaque compte applicatif :
ALTER USER 'app_user'@'localhost'
IDENTIFIED WITH caching_sha2_password BY 'MotDePasseSolide!';
FLUSH PRIVILEGES;
Code language: JavaScript (javascript)
PHP 8.x et mysqlnd gèrent caching_sha2_password
nativement.
3. Réplication & scripts
Mettez à jour scripts et dashboards qui appellent les anciennes commandes “master/slave”. Utilisez SHOW REPLICA STATUS
, SHOW BINARY LOG STATUS
, etc.
4. Outils & automatisation
- Retirez
mysql_upgrade
de vos playbooks ; le serveur fait le nécessaire au démarrage. - Remplacez
mysqlpump
si vous l’utilisiez.
5. Post-upgrade
Lisez les notes de votre point release (8.4.x) et surveillez les journaux au premier démarrage.
Procédure de mise à jour (APT / Ubuntu)
1. Mettez à jour le dépôt MySQL vers la piste 8.4 LTS.
Si vous avez suivi le tuto Mettre à jour MySQL client, server et apt-config, il suffit de lancer le script de mise à jour de mysql-apt-config
:
bash /home/scripts/install-latest-mysql-apt3.sh
Ensuite, lancez:
dpkg-reconfigure mysql-apt-config
Puis sélectionnez MySQL 8.4 LTS à chaque étape.
2. Retirez/ajustez les options obsolètes de mysqld.cnf
Pour le moment, on ajoute mysql_native_password=ON
dans la section [mysqld]
du fichier /etc/mysql/mysql.conf.d/mysqld.cnf
:
# nano /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
mysql_native_password=ON
Code language: PHP (php)
3. On met à jour les paquets MySQL (client et serveur)
apt update && apt upgrade
Et ensuite :
apt install -y mysql-common
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following packages were automatically installed and are no longer required:
gsasl-common guile-3.0-libs libaio1 libgc1 libgsasl18 libgssglue1 libntlm0 libpq5 mailutils-common
Use 'apt autoremove' to remove them.
The following additional packages will be installed:
mysql-client mysql-community-client mysql-community-client-core mysql-community-client-plugins mysql-community-server
mysql-community-server-core mysql-server
The following packages will be REMOVED:
dovecot-mysql libmailutils9t64 libmysqlclient21 libopendbx1-mysql mailutils postfix-mysql
The following packages will be upgraded:
mysql-client mysql-common mysql-community-client mysql-community-client-core mysql-community-client-plugins
mysql-community-server mysql-community-server-core mysql-server
8 upgraded, 0 newly installed, 6 to remove and 0 not upgraded.
Need to get 36.5 MB of archives.
After this operation, 5226 kB disk space will be freed.
Get:1 http://repo.mysql.com/apt/ubuntu noble/mysql-8.4-lts amd64 mysql-server amd64 8.4.6-1ubuntu24.04 [58.2 kB]
Get:2 http://repo.mysql.com/apt/ubuntu noble/mysql-8.4-lts amd64 mysql-community-client amd64 8.4.6-1ubuntu24.04 [2160 kB]
Get:3 http://repo.mysql.com/apt/ubuntu noble/mysql-8.4-lts amd64 mysql-community-client-core amd64 8.4.6-1ubuntu24.04 [1793 kB]
Get:4 http://repo.mysql.com/apt/ubuntu noble/mysql-8.4-lts amd64 mysql-community-client-plugins amd64 8.4.6-1ubuntu24.04 [1435 kB]
Get:5 http://repo.mysql.com/apt/ubuntu noble/mysql-8.4-lts amd64 mysql-community-server-core amd64 8.4.6-1ubuntu24.04 [30.9 MB]
Get:6 http://repo.mysql.com/apt/ubuntu noble/mysql-8.4-lts amd64 mysql-community-server amd64 8.4.6-1ubuntu24.04 [67.8 kB]
Get:7 http://repo.mysql.com/apt/ubuntu noble/mysql-8.4-lts amd64 mysql-client amd64 8.4.6-1ubuntu24.04 [58.2 kB]
Get:8 http://repo.mysql.com/apt/ubuntu noble/mysql-8.4-lts amd64 mysql-common amd64 8.4.6-1ubuntu24.04 [59.5 kB]
Fetched 36.5 MB in 3s (13.7 MB/s)
Preconfiguring packages ...
Code language: JavaScript (javascript)
A ce stade, MySQL 8.4 est installé et si vous redémarrez le service, vos sites devraient être fonctionnels – vérifiez bien l’étape 2 ! On redémarre le service :
service mysql restart
Vérification de notre version de MySQL :
# mysql --version
mysql Ver 8.4.6 for Linux on x86_64 (MySQL Community Server - GPL)
# systemctl status mysql --no-pager
● mysql.service - MySQL Community Server
Loaded: loaded (/usr/lib/systemd/system/mysql.service; enabled; preset: enabled)
Active: active (running) since Sat 2025-10-11 12:43:24 CEST; 1min 40s ago
Docs: man:mysqld(8)
http://dev.mysql.com/doc/refman/en/using-systemd.html
Process: 2687497 ExecStartPre=/usr/share/mysql-8.4/mysql-systemd-start pre (code=exited, status=0/SUCCESS)
Main PID: 2687536 (mysqld)
Status: "Server is operational"
Tasks: 39 (limit: 38095)
Memory: 437.8M (peak: 452.0M)
CPU: 1.661s
CGroup: /system.slice/mysql.service
└─2687536 /usr/sbin/mysqld
Oct 11 12:43:23 apollo systemd[1]: Starting mysql.service - MySQL Community Server...
Oct 11 12:43:24 apollo systemd[1]: Started mysql.service - MySQL Community Server.
Code language: PHP (php)
4. Réinstallation des paquets supprimés
À l’étape précédente, vous avez vu que l’installation a supprimé des paquets essentiels pour mon serveur de mail (Postfix et Dovecot) ? Nous réinstallons les nouvelles versions :
apt install -y libmysqlclient24 postfix-mysql dovecot-mysql mailutils
5. Migrez les comptes vers caching_sha2_password
Bon, on ne va pas y aller par quatre chemins : dans l’étape 2, nous sommes obligés de réactiver un plugin pour que les sites hébergés sur le serveur soient opérationnels. Le problème, c’est que MySQL 9.1, la prochaine version majeur va tout simplement interdire mysql_native_password
: nous devons donc impérativement migrer tous nos utilisateurs SQL vers caching_sha2_password
.
Tout d’abord, commençons par faire un état des lieux :
mysql -e "SELECT user,host,plugin FROM mysql.user WHERE plugin<>'caching_sha2_password';"
Code language: HTML, XML (xml)
Cela vous donne la liste de tous les utilisateurs, par site qui doivent être migrés vers le plugin caching_sha2_password
.
Nous allons créer un script bash qui va aller récupérer l’utilisateur et le mot de passe de la base de données pour chacun des sites WordPress hébergés sur le serveur. Ensuite, nous allons tout simplement écrire les requêtes SQL qui permettront de mettre à jour nos utilisateurs avec le nouveau plugin de chiffrement des mots de passe.
On crée notre script :
nano /home/scripts/migrate-wp-users-to-caching-sha2.sh
Et on y ajoute :
#!/usr/bin/env bash
# migrate-wp-users-to-caching-sha2.sh (debug-hardened)
# Usage:
# ./migrate-wp-users-to-caching-sha2.sh
# DEBUG=1 ./migrate-wp-users-to-caching-sha2.sh
# ./migrate-wp-users-to-caching-sha2.sh --apply
# Author : Matt Biscay
# Author URI : https://www.mattbiscay.com
# Script URI: https://www.skyminds.net/?p=614912
set -Eeuo pipefail
WP_GLOB="/home/www/*/wp-config.php"
SQL_OUT="/root/alter-wp-users-to-caching_sha2.sql"
APPLY=0
[[ "${1:-}" == "--apply" ]] && APPLY=1
# Debug toggles
ts(){ date +"%F %T"; }
log(){ echo "[$(ts)] $*"; }
trap 'log "ERROR on line $LINENO"; exit 1' ERR
if [[ "${DEBUG:-0}" == "1" ]]; then
export PS4='+ ${BASH_SOURCE##*/}:${LINENO}: ${FUNCNAME[0]:-main}: '
set -x
fi
# Tooling
command -v mysql >/dev/null || { log "mysql not found"; exit 1; }
command -v php >/dev/null || { log "php not found"; exit 1; }
# MySQL defaults file (optional): uncomment if your mysql CLI needs creds
# : "${MYSQL_DEFAULTS:=/root/.my.cnf}"
# [[ -f "$MYSQL_DEFAULTS" ]] && MYSQL_ARGS=( --defaults-file="$MYSQL_DEFAULTS" ) || MYSQL_ARGS=()
MYSQL_ARGS=() # empty by default
# --- PHP extractor in a temp file (robust on all shells) ---
PHP_HELPER="$(mktemp -t wpdbx.XXXXXX.php)"
cleanup(){ rm -f "$PHP_HELPER" 2>/dev/null || true; }
trap cleanup EXIT
cat >"$PHP_HELPER" <<'PHP'
<?php
$f = $argv[1] ?? '';
$c = @file_get_contents($f);
if ($c === false) { /* silent: caller logs */ exit(0); }
/* Extract define('NAME','value') or define("NAME","value") */
function get_define($name, $src) {
$rx = "/define\\s*\\(\\s*['\\\"]".preg_quote($name,'/')."['\\\"]\\s*,\\s*(['\\\"])(.*?)\\1\\s*\\)/s";
if (preg_match($rx, $src, $m)) return $m[2];
return "";
}
$u = get_define('DB_USER', $c);
$p = get_define('DB_PASSWORD', $c);
$h = get_define('DB_HOST', $c);
echo $u,"\t",$p,"\t",$h,"\n";
PHP
log "mysql: $(command -v mysql)"
log "php: $(command -v php)"
: > "$SQL_OUT" || { log "Cannot write $SQL_OUT"; exit 1; }
log "Output SQL -> $SQL_OUT"
# Collect wp-config files
shopt -s nullglob
files=( $WP_GLOB )
shopt -u nullglob
log "Scanning ${#files[@]} wp-config.php files"
for f in "${files[@]:0:8}"; do log " - $f"; done
# Temp mapping: user@host<TAB>password
TMP_MAP="$(mktemp -t wpusers.XXXXXX)"
: > "$TMP_MAP"
# 1) Extract creds
for f in "${files[@]}"; do
out="$(php "$PHP_HELPER" "$f" || true)"
if [[ -z "$out" ]]; then
log "WARN: no creds parsed in $f"
continue
fi
u="$(printf '%s' "$out" | awk -F '\t' '{print $1}')"
p="$(printf '%s' "$out" | awk -F '\t' '{print $2}')"
h="$(printf '%s' "$out" | awk -F '\t' '{print $3}')"
[[ -z "$u" ]] && { log "WARN: DB_USER empty in $f"; continue; }
# normalise host for grants
case "$h" in
""|/*|"127.0.0.1") h="localhost" ;;
*) h="${h%%:*}" ;;
esac
printf '%s@%s\t%s\n' "$u" "$h" "$p" >> "$TMP_MAP"
done
# 2) Deduplicate without in-place sort (portable)
DEDUP_MAP="$(mktemp -t wpusers_dedup.XXXXXX)"
awk -F'\t' '!seen[$0]++' "$TMP_MAP" > "$DEDUP_MAP"
mv -f "$DEDUP_MAP" "$TMP_MAP"
# 3) Query mysql.user and emit ALTERs for non-caching accounts
COUNT=0
while IFS=$'\t' read -r key pass; do
[[ -z "$key" ]] && continue
u="${key%@*}"
# fetch host+plugin for this user
rows="$(mysql "${MYSQL_ARGS[@]}" -Nse "SELECT host,COALESCE(plugin,'') FROM mysql.user WHERE user='${u//\'/\'\'}';" || true)"
if [[ -z "$rows" ]]; then
log "INFO: user '$u' not found in mysql.user"
continue
fi
# iterate rows safely
while IFS=$'\n' read -r line; do
[[ -z "$line" ]] && continue
host="$(printf '%s\n' "$line" | awk '{print $1}')"
plugin="$(printf '%s\n' "$line" | awk '{print $2}')"
[[ -z "$host" ]] && continue
if [[ "$plugin" != "caching_sha2_password" ]]; then
p_sql="${pass//\'/\'\'}"
cat >>"$SQL_OUT" <<SQL
ALTER USER '${u}'@'${host}'
IDENTIFIED WITH caching_sha2_password BY '${p_sql}';
SQL
((++COUNT))
log "MARK: ${u}@${host} -> caching_sha2_password"
fi
done <<< "$rows"
done < "$TMP_MAP"
(( COUNT > 0 )) && echo "FLUSH PRIVILEGES;" >> "$SQL_OUT"
log "Planned ALTERs: $COUNT"
log "SQL file: $SQL_OUT"
if (( COUNT > 0 )) && (( APPLY == 1 )); then
log "Applying..."
mysql "${MYSQL_ARGS[@]}" < "$SQL_OUT"
log "Done."
fi
rm -f "$TMP_MAP" 2>/dev/null || true
Code language: PHP (php)
Changez les chemins selon vos besoins. Lorsque l’on lance le script, il crée le fichier /root/alter-wp-users-to-caching_sha2.sql
. Inspectez-le et si tout vous semble correct, vous pouvez le relancer avec --apply
pour appliquer les changements à la base de données automatiquement :
cd /home/scripts/
./migrate-wp-users-to-caching-sha2.sh --apply
Il ne vous reste plus qu’à redémarrer MySQL :
service mysql restart
Conclusion
Vous venez de mettre à jour MySQL vers la version 8.4 et de modifier vos utilisateurs MySQL pour qu’ils utilisent désormais le plugin caching_sha2_password
, qui est la norme pour les versions les plus récentes. Tout cela améliore la stabilité du serveur de base de données et nous prépare sereinement pour la prochaine version de MySQL.
Vous imaginez un projet WordPress ou WooCommerce ? Je vous accompagne à chaque étape pour concrétiser vos ambitions, avec rigueur et transparence.