MySQL 8.4 is the first long-term support release under Oracle's new release model, and since MySQL 8.0 reached end of life in April 2026 it is the version to be on. For most applications the upgrade from 8.0 is uneventful: the SQL is the same, the drivers are the same, the data files upgrade in place. What breaks is at the edges. Accounts using mysql_native_password cannot log in until the plugin is switched back on, because 8.4 disables it by default. Scripts using CHANGE MASTER TO, SHOW SLAVE STATUS, FLUSH HOSTS, mysqlpump or expire_logs_days fail, because they were removed. And a handful of InnoDB defaults changed - mostly for the better on fast storage, with one that small servers should override.
This guide covers the release model first, because it changes how you plan upgrades, then every change likely to affect an application or an administrator, then how to check a database before moving it.
LTS and Innovation releases#
Until 8.0, MySQL shipped one series for years and added features in patch releases: 8.0.x gained EXPLAIN ANALYZE at 8.0.18, hash joins at 8.0.18, innodb_redo_log_capacity at 8.0.30. That made "8.0" a moving target - two servers both called MySQL 8.0 could behave differently.
From 8.1 onwards, Oracle split releases into two tracks:
| Track | Versions | Cadence | Support | Changes within the series |
|---|---|---|---|---|
| Innovation | 8.1, 8.2, 8.3, 9.0, 9.1 and on | About quarterly | Until the next Innovation release | New features, removals, behaviour changes |
| LTS | 8.4, then a later 9.x | About every two years | Around eight years in total | Bug and security fixes only |
An LTS series is meant to be boring. 8.4.1, 8.4.2 and so on contain fixes, not new features or changed defaults, so a patch update should not change how your application behaves. Oracle lists 8.4 as supported until 2032, with premier support for the first five years of that. Innovation releases are for people who want new features early and are prepared to upgrade every few months; for a production application database, LTS is the sensible default.
The practical consequence is that features introduced in 8.1 to 8.3 arrive in 8.4 all at once, and so do the removals that the Innovation releases made along the way. That is why 8.0 to 8.4 has more breaking changes than a version number of 0.4 suggests.
Authentication: mysql_native_password is off#
This is the change that stops applications connecting.
mysql_native_password, the SHA-1-based plugin that was the default until 8.0, was deprecated in 8.0. In 8.4 it is still present but disabled by default. An account created with it exists, but logins fail until the server starts with:
[mysqld]mysql_native_password=ONThe same switch is available on the command line as --mysql-native-password=ON. It is a start-up option, not something an application user can change, and in MySQL 9.0 the plugin is removed entirely, so turning it back on buys time rather than solving anything. The real fix is to move accounts to caching_sha2_password, the default since 8.0:
-- Find accounts still on the old pluginSELECT user, host, plugin FROM mysql.userWHERE plugin = 'mysql_native_password';-- Move one; the password must be set again because the hash format differsALTER USER 'app'@'%' IDENTIFIED WITH caching_sha2_password BY 'the-password';Before doing that, check that the application's driver supports caching_sha2_password. Anything released in the last several years does: PHP's mysqlnd, Node's mysql2, PyMySQL, mysqlclient, Connector/J 8 and later, MySqlConnector for .NET. The original Node mysql package does not, nor do MySQL 5.7-era command-line clients. A client that cannot do it fails with Authentication plugin 'caching_sha2_password' cannot be loaded; one that can, but connects without TLS, needs the server's RSA public key or a TLS connection on first login - MySQL remote connections explains that behaviour.
Two smaller authentication changes: the default_authentication_plugin variable was removed (its job is done by authentication_policy, which also governs multi-factor authentication), and the authentication_fido plugins were removed in favour of authentication_webauthn.
Removed statements, options and tools#
Anything here that appears in a script, a configuration file or an ORM's admin tooling fails on 8.4. Most were deprecated during 8.0 with warnings.
| Removed | Use instead |
|---|---|
CHANGE MASTER TO, MASTER_* options | CHANGE REPLICATION SOURCE TO, SOURCE_* options |
START SLAVE, STOP SLAVE, RESET SLAVE | START REPLICA, STOP REPLICA, RESET REPLICA |
SHOW SLAVE STATUS, SHOW SLAVE HOSTS | SHOW REPLICA STATUS, SHOW REPLICAS |
SHOW MASTER STATUS, SHOW MASTER LOGS | SHOW BINARY LOG STATUS, SHOW BINARY LOGS |
RESET MASTER, PURGE MASTER LOGS | RESET BINARY LOGS AND GTIDS, PURGE BINARY LOGS |
FLUSH HOSTS | TRUNCATE TABLE performance_schema.host_cache |
expire_logs_days | binlog_expire_logs_seconds |
default_authentication_plugin | authentication_policy |
--ssl, --admin-ssl, have_ssl, have_openssl | --tls-version, --admin-tls-version |
--skip-host-cache | --host-cache-size=0 |
mysqlpump | mysqldump or MySQL Shell dump utilities |
mysql_upgrade | Nothing; the server upgrades itself at start-up |
mysql_ssl_rsa_setup | Nothing; the server generates certificates itself |
binlog_transaction_dependency_tracking | Nothing; writeset tracking is always used |
AUTO_INCREMENT on FLOAT/DOUBLE columns | An integer column |
The replication syntax change catches monitoring scripts more than replication setups. A health check that runs SHOW SLAVE STATUS every minute and greps for Seconds_Behind_Master now gets a syntax error, and in SHOW REPLICA STATUS the column is Seconds_Behind_Source. Status variables like Com_show_slave_status were removed with them.
FLUSH HOSTS matters to anyone who has met Host is blocked because of many connection errors. The TRUNCATE replacement needs the DROP privilege on that table, which root has; mysqladmin flush-hosts still works and uses it internally.
Also removed: the --old and --new options, --language, avoid_temporal_upgrade and show_old_temporals, LOW_PRIORITY with LOCK TABLES ... WRITE, the keyring_file and keyring_encrypted_file plugins (replaced by components), INFORMATION_SCHEMA.TABLESPACES, and support for weak TLS ciphers - 8.4 accepts only ciphers with forward secrecy and authenticated encryption on TLS 1.2 and 1.3.
New InnoDB and server defaults#
8.4 changed a set of InnoDB defaults to suit modern hardware - NVMe storage and many cores - rather than the spinning disks the old ones were written for. Unless you set these explicitly, your server behaves differently after upgrading.
| Variable | 8.0 | 8.4 |
|---|---|---|
innodb_io_capacity | 200 | 10000 |
innodb_io_capacity_max | at least 2000 | twice innodb_io_capacity |
innodb_log_buffer_size | 16M | 64M |
innodb_flush_method (Linux) | fsync | O_DIRECT where supported |
innodb_use_fdatasync | OFF | ON |
innodb_adaptive_hash_index | ON | OFF |
innodb_change_buffering | all | none |
innodb_buffer_pool_instances | 8 (1 if under 1 GB) | Calculated; 1 if 1 GB or less |
innodb_doublewrite_pages | innodb_write_io_threads (4) | 128 |
innodb_read_io_threads | 4 | Half the logical CPUs, at least 4 |
innodb_purge_threads | 4 | 1 up to 16 logical CPUs, else 4 |
innodb_numa_interleave | OFF | ON |
temptable_max_ram | 1G | 3% of memory, between 1 and 4 GB |
temptable_use_mmap / temptable_max_mmap | ON / 1G | OFF / 0 |
Most of these are improvements you get for free. O_DIRECT stops InnoDB double-caching pages in the operating system's cache. The higher I/O capacity lets background flushing keep up with fast storage. Turning off the adaptive hash index and change buffering removes two features that often caused contention and rarely paid off on modern workloads; if a specific read-heavy workload benefited, they can be turned back on.
The one to watch on a small server is temptable_max_ram. Its 8.4 default is never below 1 GB, which on a 1 or 2 GB server allows in-memory temporary tables to claim half the machine or all of it. Cap it - InnoDB tuning for small servers has numbers by plan size. innodb_dedicated_server, if you use it, no longer sets innodb_flush_method, and sizes the redo log from CPU count rather than memory.
Schema and privilege changes#
Foreign keys must reference unique keys. restrict_fk_on_non_standard_key defaults to ON, so creating a foreign key that references a non-unique index or only part of a key fails with ER_WARN_DEPRECATED_NON_STANDARD_KEY. Existing foreign keys of that kind survive the upgrade with warnings; new ones need the referenced columns to be a primary key or unique index, or the variable turned off.
Wildcards in database grants are deprecated. GRANT ... ON a database name containing % or _ still works as a pattern, but those characters are expected to become literals in a future release. Grant per database.
New privileges. FLUSH_PRIVILEGES (just for FLUSH PRIVILEGES; holders of RELOAD get it on upgrade), OPTIMIZE_LOCAL_TABLE, TRANSACTION_GTID_TAG, and SET_ANY_DEFINER with ALLOW_NONEXISTENT_DEFINER, which replace SET_USER_ID for creating objects with someone else as definer. That last change affects restores: a dump whose views and routines name a definer other than you needs SET_ANY_DEFINER to load as written. MySQL users and privileges covers definers in more detail.
Identifiers with more than one `$`. An unquoted identifier containing two or more dollar signs is a syntax error since 8.1. Rare, but it breaks loudly when it happens.
On the positive side, 8.4 brings the Innovation-era features with it: histograms that can be set to update automatically with ANALYZE TABLE, GTID tags for grouping transactions, and a mysql client that can disable its system shell escape with --system-command=OFF.
Checking a database before you upgrade#
MySQL Shell's upgrade checker inspects a running 8.0 server and reports everything that will be a problem on the target version: removed options in use, accounts on deprecated plugins, foreign keys on non-unique keys, reserved words used as identifiers, and more.
$ mysqlsh root@old-server:3306 -- util check-for-server-upgrade --target-version=8.4.6Run it with an account that can read the configuration and the mysql schema, read every error and warning, and fix what it reports on the old server first. The upgrade paths it supports:
| From | To 8.4 | How |
|---|---|---|
| 8.0 (recent patch) | Yes | In place, or dump and load |
| 8.1-8.3 Innovation | Yes | In place |
| 5.7 | Not directly | Upgrade to 8.0 first, or dump and load |
| 8.4.x | 8.4.y | In place; downgrades within the 8.4 series are supported too |
In-place means stopping the old server and starting the new binaries on the same data directory; the server upgrades its data dictionary and system tables itself at first start. On a hosted database, where the provider runs the server, the equivalent is a logical dump of your databases loaded into an 8.4 server - which is also how you move between hosts, covered in migrating MySQL to a new host. A logical dump also skips the 5.7-to-8.0 hop, since MySQL 8.4 loads a 5.7 dump directly in most cases; the exceptions are mostly reserved words and zero dates under strict mode.
An upgrade, step by step#
For a self-managed server, the in-place route from 8.0 looks like this. Each step has a reason, and skipping one is how upgrades turn into restores.
- Get to a recent 8.0 patch first. Upgrading from 8.0.40-something is better tested than from 8.0.20, and the late 8.0 patches warn about most of what 8.4 removes. Read the error log after that restart for deprecation warnings: each one is a future failure.
- Run the upgrade checker against the running server and fix everything it reports as an error. Warnings deserve a look too; they include accounts on
mysql_native_password. - Clean the configuration. Remove the options listed above, and decide deliberately about the changed InnoDB defaults: if you had tuned
innodb_io_capacityfor your storage, your value stays; if you never set it, it jumps from 200 to 10000. - Take a full backup you have restored at least once. A logical dump is the one that lets you go back to 8.0 if you must, because an in-place upgrade cannot be reversed by starting the old binaries - the data dictionary has been upgraded.
- Shut down cleanly. With
innodb_fast_shutdownat its default of 1 a clean shutdown is fine; setting it to 0 first makes InnoDB finish purge and merge work before stopping, which some people prefer before a major upgrade. - Install 8.4 and start it on the same data directory. Watch the error log: the server upgrades the data dictionary, then the system schema, and reports when it is ready for connections. On a large instance with many tables this takes a while; do not interrupt it.
- Test the application, including logins for every account, the scheduled jobs, and any monitoring that runs administrative statements. The failures in this upgrade are almost all in the edges, not in the queries.
On a hosted database you do not do steps 5 and 6 yourself, and the route is a dump from the old server loaded into a new 8.4 one. Steps 1 to 4 and 7 still apply, and the upgrade checker can be pointed at your old server from any machine with MySQL Shell. When the application works against a rehearsal copy loaded from the dump, the cut-over is a configuration change.
What does not change#
For the application, most things. SQL syntax for queries and DML is the same. utf8mb4 with utf8mb4_0900_ai_ci remains the default. Window functions, common table expressions, JSON functions, EXPLAIN ANALYZE, invisible and functional indexes all behave as in late 8.0. ORMs that supported 8.0 support 8.4; the ones to check are those that issue replication or administration statements, and those pinned to an old driver.
The checklist, in order: upgrade the drivers, move accounts off mysql_native_password, remove removed options from configuration, replace removed statements in scripts and monitoring, run the upgrade checker, then rehearse the move on a copy and run the application's test suite against it.
FAQ#
Is MySQL 8.0 still supported?
No. MySQL 8.0 reached end of life in April 2026 and no longer receives fixes, including security fixes, from Oracle. Some cloud providers sell paid extended support for it, but the supported free path is 8.4 LTS.
Should I use MySQL 8.4 or a 9.x Innovation release?
For a production application, 8.4 LTS. Innovation releases are supported only until the next one, roughly a quarter, so staying on one means upgrading several times a year through releases that may remove things. Use 9.x to test what is coming, and move to the next LTS when it arrives.
Can I still use mysql_native_password on 8.4?
Only if the server is started with mysql_native_password=ON, which needs control of the server's configuration. Even then it is a stopgap: MySQL 9.0 removed the plugin. Move the account to caching_sha2_password and upgrade any driver that cannot handle it.
Will my 8.0 dump load into MySQL 8.4?
Almost always, yes. A logical dump from 8.0 loads into 8.4 without changes in the vast majority of cases. Watch for definer clauses naming accounts that do not exist on the new server, and for SET @@GLOBAL lines that need privileges an ordinary user lacks; mysqldump backup and restore covers both.
Do I need to run mysql_upgrade after upgrading?
No - and on 8.4 you cannot, because it was removed. Since 8.0.16 the server upgrades its own system tables and data dictionary at start-up, controlled by the --upgrade option, which defaults to doing whatever is necessary.




Comments
Completely anonymous: no account, no email, no cookie. We store the name you type, the text and the time - nothing else. Links are limited and markup is not rendered.