Ubuntu Server : migration vers MySQL 8.4 LTS

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 vers caching_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) et mysqlpump (préférez mysqldump 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 sur FLOAT/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 et ALLOW_NONEXISTENT_DEFINER remplacent l’ancien SET_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 sur FLOAT/DOUBLE dans votre schéma et corrigez.
  • Passez un coup d’œil à vos my.cnf : supprimez default_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 || trueCode 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.

Discutons de votre projet ensemble »

Matt

Développeur certifié WordPress & WooCommerce chez Codeable, administrateur système et enseignant-chercheur, je mets mon expertise au service de vos projets web.

Ma priorité : des sites performants, fiables et sécurisés, pensés pour offrir la meilleure expérience utilisateur. J’accompagne chaque client avec écoute et pédagogie, pour transformer vos idées en solutions concrètes et durables.

Profitez de solutions WordPress et WooCommerce sur-mesure, pensées pour optimiser durablement votre site.
Explorez les leviers pour booster l’impact de votre site web.

Opinions