TechEarl

How to Upgrade MySQL 8.0 to 8.4 LTS

MySQL 8.4 is the new LTS branch through April 2032. The 8.0 to 8.4 upgrade is much smaller than 5.7 to 8.0, but removed options and the new authentication_policy variable still bite. Full procedure with rollback.

Ishan KarunaratneIshan Karunaratne⏱️ 10 min readUpdated
Upgrade MySQL 8.0 to 8.4 LTS: removed deprecated options, authentication_policy variable, mysql_native_password disabled by default, in-place upgrade procedure.

MySQL 8.4 became the new Long Term Support (LTS) release in April 2024. Oracle's release cadence changed: 8.0 was effectively a perpetual rolling release with 50+ point versions over 6 years, and 8.4 LTS is the first of the new "LTS every two years, Innovation in between" model. Support for 8.4 LTS runs through April 2032. The 8.0 to 8.4 upgrade is much smaller than the 5.7 to 8.0 jump, but Oracle used the major-version boundary to actually remove deprecated features. The standout: default_authentication_plugin is gone, replaced by authentication_policy, and mysql_native_password is disabled by default. Below is the full procedure with the breaking changes that matter, the new system variables, and how to roll back.

How do I upgrade MySQL 8.0 to 8.4 LTS?

The upgrade is a five-step procedure on a self-hosted box. First, run mysqlsh -- util check-for-server-upgrade --target-version=8.4.0 to scan for deprecated-and-now-removed features in your schema and config. Second, take a full logical backup with mysqldump --all-databases --single-transaction --master-data=2. Third, replace the apt source from 8.0 to 8.4, stop MySQL, install the 8.4 packages, and start MySQL 8.4 against the existing data directory (in-place upgrade). Fourth, replace any removed system variables in my.cnf (the big one is default_authentication_pluginauthentication_policy). Fifth, re-enable mysql_native_password if you have legacy clients you can't update, since 8.4 disables it by default. The actual binary swap is under 5 minutes; planning around the auth-policy change is what takes time.

Jump to:

What changed between 8.0 and 8.4

The 8.0 → 8.4 boundary is the first time Oracle has actually removed long-deprecated 8.0 features rather than just warning about them. The headlines:

ChangeImpact
default_authentication_plugin removedReplace with authentication_policy
mysql_native_password disabled by defaultRe-enable explicitly, or move clients to caching_sha2_password
default_password_lifetime removedUse password_lifetime per-user clause instead
Several --skip-* startup options removedUse the explicit positive form (e.g., bind_address instead of --skip-networking)
query_cache_* everything removedThe query cache was disabled in 8.0 but the variables remained for compatibility. Now they're gone — remove from my.cnf
Group Replication: minimum supported MySQL version is now 8.0.27Older 8.0.x in the group must upgrade first
Caching SHA-2 password is the only defaultNew users always land on caching_sha2_password
New mysql_native_password plugin is disabled by defaultMust opt back in if needed

On the upside, 8.4 also adds features without removing anything else load-bearing: vector data types (with VECTOR functions), better binary log compression, improved performance for analytic workloads. None of those are breaking.

Pre-flight: upgrade checker and backup

Run the upgrade checker. The MySQL Shell version is the more thorough one:

bash
mysqlsh -- util check-for-server-upgrade \
    '{"user":"root","host":"localhost","password":"YOUR_PASSWORD"}' \
    --target-version=8.4.0 \
    --output-format=JSON

Errors must be fixed before the upgrade. Warnings should be reviewed but rarely block.

Take a full logical backup:

bash
mysqldump \
    --all-databases \
    --single-transaction \
    --master-data=2 \
    --routines \
    --triggers \
    --events \
    --hex-blob \
    | gzip > mysql-8.0-pre-8.4-$(date +%Y%m%d-%H%M).sql.gz

The same backup-everything principle applies as in the 5.7 to 8.0 migration. The data dictionary doesn't change in shape from 8.0 to 8.4 the way it did from 5.7 to 8.0, but it does get rewritten on startup. Rollback after the first 8.4 start requires the dump.

The in-place upgrade

bash
# 1. Stop MySQL 8.0
sudo systemctl stop mysql

# 2. Replace apt source from 8.0 to 8.4 LTS
wget https://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.deb
sudo dpkg -i mysql-apt-config_0.8.32-1_all.deb
# (select MySQL 8.4 LTS in the config dialog)
sudo apt update

# 3. Install 8.4 (keeps existing /var/lib/mysql)
sudo apt install -y mysql-server

# 4. Start it
sudo systemctl start mysql

# 5. Tail the error log during first start
sudo tail -f /var/log/mysql/error.log

8.4 detects the older data directory on first start and runs the upgrade automatically. Same integrated mysql_upgrade flow that 8.0.16+ introduced.

Removed system variables

The single most common upgrade failure is MySQL refusing to start because of an unknown system variable in my.cnf. The full list of variables removed in 8.4:

Removed in 8.4Replacement
default_authentication_pluginauthentication_policy
default_password_lifetimeper-user PASSWORD EXPIRE INTERVAL N DAY
query_cache_* (all)(no replacement — cache is gone)
skip_networkingbind_address='127.0.0.1' or similar
skip_name_resolveskip_name_resolve (kept; just listing as it's adjacent)
binlog_transaction_dependency_tracking (deprecated)(set via binlog_format=ROW defaults)
Group Replication: group_replication_recovery_complete_atremoved
expire_logs_daysbinlog_expire_logs_seconds (8.0 also had this)

Before starting 8.4, grep your my.cnf:

bash
grep -E "^(default_authentication_plugin|default_password_lifetime|query_cache|skip_networking|expire_logs_days)" \
    /etc/mysql/mysql.conf.d/*.cnf /etc/mysql/my.cnf 2>/dev/null

Every hit is something you need to either remove or replace before starting MySQL 8.4. If MySQL refuses to start after the upgrade, the error log will name the offending variable.

The authentication_policy change

The new authentication_policy variable controls which plugins are valid for new users and what the default is. In 8.0 you had:

ini
# 8.0 style
[mysqld]
default_authentication_plugin = caching_sha2_password

In 8.4 you have:

ini
# 8.4 style
[mysqld]
authentication_policy = 'caching_sha2_password,'

The policy is a comma-separated list of up to three plugin slots: the default, then optional second-factor, then optional third-factor. The trailing comma is significant: it means "no second factor required." For most installations the value is 'caching_sha2_password,' and that's it.

For multi-factor setups (since 8.0.27):

ini
# Force MFA: caching_sha2_password + authentication_webauthn for second factor
authentication_policy = 'caching_sha2_password,authentication_webauthn,'

The empty third slot means a third factor is optional. To make it required, name a plugin.

Re-enabling mysql_native_password

This is the new-in-8.4 friction. mysql_native_password is disabled by default. Existing accounts using it continue to authenticate, but you cannot create a new account with it and the server doesn't accept it for password changes unless you opt back in:

ini
[mysqld]
# 8.4: re-enable the legacy plugin for newly-created users
mysql_native_password = ON
authentication_policy = 'mysql_native_password,'

Then restart MySQL. This is the right answer when you have legacy PHP / Python / Node.js clients that don't speak caching_sha2_password and updating the client driver isn't possible in the same maintenance window.

The long-term answer is to update the clients. See the client driver support matrix in the 5.7 to 8.0 migration for the version requirements; the same matrix applies to 8.4. mysql_native_password is currently scheduled for removal in a future LTS, so the clock is real.

Verify the upgrade

After 8.4 starts cleanly:

sql
-- Server version
SELECT VERSION();
-- → 8.4.0 (or whichever 8.4.x you installed)

-- Confirm the LTS marker
SELECT @@version_comment;

-- Authentication policy
SHOW VARIABLES LIKE 'authentication_policy';
SHOW VARIABLES LIKE 'mysql_native_password';

-- User plugin distribution
SELECT plugin, COUNT(*) FROM mysql.user GROUP BY plugin;

-- New 8.4 vector functions exist
SELECT VECTOR_DIM(STRING_TO_VECTOR('[1,2,3]'));
-- → 3

Run application smoke tests next. A common gotcha: web apps that use stored credentials in the format mysql_native_password may silently fail authentication on newly-created users until you re-enable the legacy plugin or update them to the new plugin.

Rollback

8.4 rewrites the system schema on first start. Rollback to 8.0 is not supported through the binary path. The only rollback is restore from the pre-upgrade logical dump:

bash
sudo systemctl stop mysql
sudo apt remove --purge mysql-server
# Re-install 8.0 packages from the old apt source
sudo dpkg -i mysql-apt-config_0.8.29-1_all.deb  # select 8.0
sudo apt update && sudo apt install -y mysql-server
sudo systemctl stop mysql
sudo rm -rf /var/lib/mysql
sudo mysqld --initialize-insecure --user=mysql
sudo systemctl start mysql
gunzip < mysql-8.0-pre-8.4-*.sql.gz | mysql -u root

A logical restore at scale takes hours. Test the upgrade on a replica or staging copy before touching the primary.

What to do next

After 8.4 is up:

External references:

FAQ

TagsMySQLMySQL 8.4MySQL 8.0UpgradeLTSDatabase Administration
Share
Ishan Karunaratne

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years across software, Linux systems, DevOps, and infrastructure — and a more recent focus on AI. Currently Chief Technology Officer at a tech startup in the healthcare space.

Keep reading

Related posts

Full migration from MySQL 5.7 to 8.0: prerequisites, mysqlcheck dry-run, in-place upgrade, authentication-plugin caching_sha2_password switch, and rollback.

How to Migrate from MySQL 5.7 to 8.0 (Step-by-Step)

MySQL 5.7 has been past its EOL since October 2023. Here is the migration to 8.0: prerequisites, dry-run with mysqlcheck, in-place upgrade, the authentication-plugin change that breaks old clients, and rollback if it goes sideways.

Macro photograph of a printed spreadsheet ledger on a dark slate desk, neat columns of numbers in monospaced print, single warm side lamp grazing the page edge

How to Export a MySQL Table to CSV

Export a MySQL table to CSV using SELECT INTO OUTFILE, mysqldump --tab, the mysql client with a piped redirect, or a no-privilege one-liner that works on hosts where FILE is disabled.