MySQL 8.0 to 8.4 LTS Upgrade Guide — Part 3: Upgrade Execution

Three MySQL upgrade approaches compared — replication-based, in-place, and rolling replica. Step-by-step commands, configuration templates, and time estimates for each method.

Three primary approaches exist for performing the MySQL 8.0 to 8.4 upgrade. Each has different trade-offs for downtime, rollback complexity, and hardware requirements. Use the decision flowchart below to choose the right one for your environment.

Choosing Your Upgrade Approach

ApproachDowntimeRollbackHardwareBest For
Replication-BasedMinutes (cutover only)Instant (redirect to 8.0)Requires extra serverProduction-critical, large datasets
Rolling ReplicaMinutes per nodeUn-upgraded source availableUses existing replicasReplicated topologies
In-PlaceHours (full duration)Restore from backup (hours)No extra hardwareDev/QA, small datasets, budget-constrained
Decision flowchart for selecting the right MySQL upgrade approach based on available hardware and existing topology
Figure 1: Decision flowchart for selecting the right MySQL upgrade approach based on available hardware and existing topology.

Approach 1: Replication-Based Upgrade (Recommended)

The replication-based approach provides minimal downtime, a natural testing period, and a straightforward rollback path. It requires additional hardware.

Replication-based upgrade showing Phase 1 sync via replication and Phase 2 cutover with traffic redirect
Figure 2: Replication-based upgrade — Phase 1 (sync via replication) and Phase 2 (cutover with traffic redirect).

Step-by-Step Procedure

Step 1: Install MySQL 8.4.8 on a new dedicated server.

Step 2: Configure the 8.4 server with cleaned-up my.cnf.

Step 3: Take a consistent backup from the MySQL 8.0 source:

# Using XtraBackup:
xtrabackup --backup --target-dir=/backup/for_84 --user=root --password=<pw>

# Or using mysqldump:
mysqldump --all-databases --single-transaction --routines --triggers \
  --events --source-data=2 > backup_for_84.sql

Step 4: Restore the backup on the MySQL 8.4 server.

Step 5: Set up replication from 8.0 (source) to 8.4 (replica).

For GTID-based replication (recommended):

CHANGE REPLICATION SOURCE TO
  SOURCE_HOST = '8.0_source_ip',
  SOURCE_USER = 'repl_user',
  SOURCE_PASSWORD = 'repl_password',
  SOURCE_AUTO_POSITION = 1,
  GET_SOURCE_PUBLIC_KEY = 1;

START REPLICA;

For binary log position-based replication:

CHANGE REPLICATION SOURCE TO
  SOURCE_HOST = '8.0_source_ip',
  SOURCE_USER = 'repl_user',
  SOURCE_PASSWORD = 'repl_password',
  SOURCE_LOG_FILE = 'binlog.000XXX',
  SOURCE_LOG_POS = XXXXXXX,
  GET_SOURCE_PUBLIC_KEY = 1;

START REPLICA;

Step 6: Monitor replication lag until Seconds_Behind_Source = 0.

Step 7: Run application validation tests against the 8.4 replica.

Step 8: Schedule maintenance window for cutover.

Step 9: During cutover:

  1. Set 8.0 source to read-only to drain writes gracefully:
SET GLOBAL read_only = 1;
SET GLOBAL super_read_only = 1;
  1. Verify 8.4 replica is fully caught up (Seconds_Behind_Source = 0)
  2. Stop replication on the 8.4 server: STOP REPLICA;
  3. Redirect application connections to the MySQL 8.4 server
  4. Verify application functionality with smoke tests

Estimated Time by Phase

PhaseEstimated Hours
Install and configure MySQL 8.43-5
Backup and restore from 8.0 to 8.45-15 (depends on data size)
Setup replication and sync2-4
Monitoring and validation period8-24
Cutover activity2-5
Post-cutover monitoring4-8

Approach 2: In-Place Upgrade

The in-place upgrade replaces MySQL binaries on the same server. This requires less hardware but carries higher risk and longer downtime.

WARNING: In-place upgrades have NO easy rollback. If the upgrade fails, you must restore from backup, which for large datasets can take 10-20+ hours.

In-place upgrade timeline showing each step with estimated duration, point of no return, and rollback path
Figure 3: In-place upgrade timeline showing each step, estimated duration, point of no return, and rollback path.

Step-by-Step Procedure

Step 1: Take full backup (both logical and physical) and verify restore works.

Step 2: Ensure binary log retention covers your rollback window:

SET GLOBAL binlog_expire_logs_seconds = 259200;  -- 3 days

Step 3: Record the current binary log position and GTID state.

Step 4: Stop MySQL 8.0 cleanly:

SET GLOBAL innodb_fast_shutdown = 0;  -- Clean shutdown (CRITICAL)
systemctl stop mysqld

Step 5: Back up the configuration file and data directory:

cp /etc/my.cnf /etc/my.cnf.bak_8037

# Option A: LVM snapshot (preferred for large datasets):
lvcreate --size 100G --snapshot --name mysql_snap /dev/vg0/mysql_data

# Option B: File copy (slower, requires disk space):
cp -a /var/lib/mysql /var/lib/mysql.bak_8037

Step 6: Remove MySQL 8.0 packages:

For Percona Server:

# RHEL/CentOS:
yum remove percona-server-server percona-server-client

# Debian/Ubuntu (use remove, NEVER purge):
apt-get remove percona-server-server percona-server-client

For Oracle MySQL:

# RHEL/CentOS:
yum remove mysql-community-server mysql-community-client

# Debian/Ubuntu (use remove, NEVER purge):
apt-get remove mysql-server mysql-client

CRITICAL: On Debian/Ubuntu, NEVER use apt-get purge instead of apt-get remove. Purge deletes configuration files AND can trigger data directory cleanup, destroying your data. Always use remove and verify /var/lib/mysql is intact before proceeding.

Step 7: Install MySQL 8.4 packages:

For Percona Server repo:

# RHEL/CentOS:
yum install percona-server-server percona-server-common percona-server-client

# Debian/Ubuntu:
apt install -y percona-server-server percona-server-common percona-server-client

dpkg -l |grep percona |grep '8.4'

For Oracle MySQL rpm:

# RHEL/CentOS:
sudo yum install mysql-community-{server,client,client-plugins,icu-data-files,common,libs}-*

rpm -qa | grep mysql

# Debian/Ubuntu:
sudo dpkg -i mysql-{common,community-client-plugins,community-client-core,community-client,client,community-server-core,community-server,server}_*.deb

Step 8: Update my.cnf: remove all deprecated parameters, set explicit defaults.

Step 9: Start MySQL 8.4 with the existing data directory:

systemctl start mysqld

Step 10: Review the error log for upgrade messages and any issues:

tail -500 /var/log/mysql/mysqld.log

The server automatically upgrades the data dictionary and system tables on first start.

CRITICAL: Always set innodb_fast_shutdown = 0 before stopping MySQL 8.0. Using innodb_fast_shutdown = 2 leaves redo logs in a crash-like state. MySQL 8.4 cannot safely process these logs and will refuse to start. Recovery requires a full restore from backup.

Want a DBA team to handle your upgrade?

A MySQL major version upgrade is high-stakes work. If you'd rather have experienced DBAs execute it while you focus on your applications, book a free assessment call.

Book Free Assessment →

Approach 3: Rolling Replica Upgrade

For environments with an existing source-replica replication topology, upgrade replicas first, then failover. This combines the benefits of minimal downtime with no extra hardware requirement.

Rolling replica upgrade showing four stages from initial state through failover and source upgrade
Figure 4: Rolling replica upgrade — four stages from initial state through failover and source upgrade.

Procedure

  1. Upgrade Replica 1: Stop replication, perform in-place upgrade to 8.4 (per the In-Place procedure above), restart replication
  2. Monitor Replica 1 for stability, replication health, and query correctness (24-48 hours)
  3. Upgrade Replica 2 using the same procedure
  4. Once all replicas are on 8.4 and stable, perform a planned failover: promote an 8.4 replica as the new source
  5. Upgrade the old source (now demoted to replica) to 8.4

NOTE: During the rolling upgrade, the un-upgraded source remains your rollback point. If any upgraded replica shows issues, you can remove it from the pool and rebuild. Only after promoting an 8.4 replica to source is the rollback path more complex.

Configuration File Template for MySQL 8.4

Below is a recommended baseline my.cnf template, cleaned of all removed parameters and with explicit values for changed defaults. Adjust all values to match your hardware and workload.

[mysqld]
# ── Basic Settings ──
datadir                = /var/lib/mysql
port                   = 3306
server-id              = 1001
log-error              = /var/log/mysql/mysqld.log

# ── InnoDB (set explicitly to avoid silent default changes) ──
innodb_adaptive_hash_index = OFF     # 8.4 default; set ON only if benchmarks justify
innodb_flush_method        = O_DIRECT # 8.4 default; use fsync for ZFS/NFS
innodb_io_capacity         = 5000     # SSDs: 2000-5000, NVMe: 10000+, HDD: 200
innodb_log_buffer_size     = 64M      # 8.4 default; reduce if memory-constrained
innodb_page_cleaners       = 4

# ── Binary Logging ──
binlog_expire_logs_seconds = 259200   # 3 days; set to cover rollback window

# ── Authentication ──
# Transitional: uncomment to temporarily allow legacy auth during migration
# mysql_native_password = ON

# ── REMOVED in 8.4 - DO NOT INCLUDE ──
# default_authentication_plugin  (use authentication_policy)
# master_info_repository         (always TABLE)
# relay_log_info_repository      (always TABLE)
# binlog_transaction_dependency_tracking
# expire_logs_days               (use binlog_expire_logs_seconds)
# avoid_temporal_upgrade
# show_old_temporals

Part 3 Quick Checklist

Continue the Series

  1. ← Part 2: Upgrade Testing
  2. Part 3: Upgrade Execution (You Are Here)
  3. Part 4: Rollback and Post-Upgrade Validation →
M

Mughees — ReliaDB

ReliaDB is a specialist DBA team for PostgreSQL and MySQL performance, high availability, and cloud database optimization. More about ReliaDB →