What's New in MySQL 8.0 for Administrators
MySQL 8.0.11 went GA and I've been poking at it on a couple of test boxes since the release candidates. Everyone writes about window functions and CTEs. I care more about what changes when you have to run the server: the data dictionary, persisted config, roles, the new default authentication plugin, and defaults that bite if you aren't expecting them.
The transactional data dictionary
Until 5.7, table metadata lived in .frm files plus a mix of mysql.* MyISAM tables. 8.0 stores all of it in InnoDB tables inside the mysql schema. Consequences you will notice:
- No more
.frmfiles in the data directory; you cannot recover a table definition by copying one. - DDL is atomic: an
ALTER TABLEorDROP TABLEthat crashes halfway is rolled back cleanly instead of leaving an orphaned.ibd. information_schemaqueries are much faster because they read dictionary tables instead of opening every table file.mysql_upgradeis still required after an in-place upgrade from 5.7 to migrate the dictionary (it becomes automatic in later releases, but not in 8.0.11).
Check the server and dictionary state after an upgrade:
SHOW VARIABLES LIKE 'version%';
SELECT table_name, engine FROM information_schema.tables WHERE table_schema = 'mysql' AND engine <> 'InnoDB';
The second query should return no rows apart from the general_log and slow_log CSV tables.
SET PERSIST
You can now change a global variable and have it survive restarts without touching the config file:
SET PERSIST max_connections = 500;
SET PERSIST_ONLY innodb_buffer_pool_size = 8589934592; -- for read-only variables, applied at next restart
SELECT * FROM performance_schema.persisted_variables;
Values are written to mysqld-auto.cnf in the data directory and read after my.cnf, so they override it. RESET PERSIST max_connections; removes one. Handy for pushing the same change everywhere via SQL. I'm a bit wary of it, though: when a setting doesn't match my.cnf, someone will forget to look in mysqld-auto.cnf.
Roles
Privileges can finally be grouped:
CREATE ROLE 'app_rw', 'app_ro';
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'app_rw';
GRANT SELECT ON shop.* TO 'app_ro';
CREATE USER 'shopapp'@'10.0.1.%' IDENTIFIED BY 'strong-password';
GRANT 'app_rw' TO 'shopapp'@'10.0.1.%';
SET DEFAULT ROLE ALL TO 'shopapp'@'10.0.1.%';
Without SET DEFAULT ROLE, a role is granted but not active until the session runs SET ROLE. That trips up almost everyone the first time. SHOW GRANTS FOR 'shopapp'@'10.0.1.%' USING 'app_rw'; shows the effective privileges.
caching_sha2_password is the new default
New accounts use caching_sha2_password instead of mysql_native_password. It's more secure, but many client libraries don't support it yet, and this will be your first support ticket. If applications fail to connect after the upgrade, put the old plugin back as default until the clients catch up:
[mysqld]
default_authentication_plugin = mysql_native_password
Or per account:
ALTER USER 'shopapp'@'10.0.1.%' IDENTIFIED WITH mysql_native_password BY 'strong-password';
Existing accounts migrated from 5.7 keep their plugin, so this only concerns accounts you create afterwards.
Defaults that changed
Several defaults are different:
character_set_serverisutf8mb4with collationutf8mb4_0900_ai_ci. Tables created on 5.7 keep their collation, but joins between oldutf8mb4_general_cicolumns and new ones can produceIllegal mix of collationserrors.- The query cache is removed entirely.
query_cache_typeandquery_cache_sizeinmy.cnfmake the server refuse to start; delete them. explicit_defaults_for_timestampisON.innodb_undo_log_truncateisON, and undo logs live in separate tablespaces by default.log_error_verbositydefaults to 2 (no notes), and the error log format changed to include a subsystem tag.innodb_dedicated_server = ONmakes the server sizeinnodb_buffer_pool_size,innodb_log_file_sizeandinnodb_flush_methodautomatically from the machine's RAM. Only use it on hosts that run nothing else.
Smaller things I like
- Invisible indexes:
ALTER TABLE orders ALTER INDEX idx_status INVISIBLE;hides an index from the optimizer without dropping it, so you can test whether it is needed and turn it back on instantly. - Descending indexes are real now (
KEY (created_at DESC)), which helpsORDER BY a ASC, b DESCqueries. information_schemaviews are backed by the dictionary, andSHOW CREATE TABLEoutput is always consistent with what the server actually has.- Resource groups let you pin threads to CPUs and set priorities:
CREATE RESOURCE GROUP batch TYPE=USER VCPU=4-7 THREAD_PRIORITY=10;. GRANTcan no longer create users at all;NO_AUTO_CREATE_USERwas removed fromsql_modebecause it is now the only behavior.
Testing an upgrade
Before an in-place upgrade run the checker in MySQL Shell against the 5.7 instance:
mysqlsh --js root@db01:3306
mysql-js> util.checkForServerUpgrade()
It lists removed variables, reserved-word conflicts (RANK, GROUPS, SYSTEM, and others became reserved), old temporal types and partitioned tables without a native InnoDB partition handler. Fix everything it reports before you start.
Notes
- In-place upgrade works from 5.7 only. A 5.6 server must go through 5.7 first.
- There is no downgrade from 8.0 to 5.7. Take a full backup before upgrading and keep the 5.7 binaries around.
- Older
mysqldumpclients cannot dump an 8.0 server correctly because of the changedmysqlschema; use the 8.0 client tools. mysql.userno longer contains thepassword_last_changed-era workarounds; scripts that readmysql.userdirectly should switch toinformation_schema.USER_PRIVILEGESorSHOW GRANTS.
My view: atomic DDL, persisted variables and roles matter more to me than the SQL features. I'd still wait for a couple of point releases before touching production.