mysql 8.0升级必踩四大兼容性雷区:认证插件默认改用caching_sha2_password致老客户端连接失败;sql_mode启用strict_trans_tables和only_full_group_by引发插入与查询报错;字符集默认utf8mb4导致中文乱码及排序异常;系统表结构重构使直接导入mysql库崩溃。

升级前不逐条核对不兼容改动,大概率启动失败、连不上库、查询报错或数据乱码——这不是概率问题,是MySQL 8.0的默认行为变更直接触发的确定性故障。
default_authentication_plugin 默认值变了
5.7 默认用 mysql_native_password,8.0 切到 caching_sha2_password。老客户端(如 PHP 7.4 前的 mysqlnd、JDBC 5.x、Navicat 12)根本识别不了,连接只报 Access denied 或 Authentication plugin 'caching_sha2_password' cannot be loaded,日志里还不提示插件问题。
- 临时解法:在
[mysqld]段加default_authentication_plugin=mysql_native_password,但仅影响新建用户 - 已有用户必须手动改:
ALTER USER 'user'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd'; - 注意:该插件在 MySQL 8.4 已被彻底移除,不能长期依赖
sql_mode 默认启用 STRICT_TRANS_TABLES
原来插入空字符串到 NOT NULL 字段能成功,升级后直接报 ERROR 1364 (HY000): Field doesn't have a default value。更常见的是 ONLY_FULL_GROUP_BY 导致 GROUP BY 查询失败,错误类似 Expression #2 of SELECT list is not in GROUP BY clause。
- 别全局关掉
ONLY_FULL_GROUP_BY,先检查业务 SQL 是否真依赖隐式分组逻辑 -
STRICT_TRANS_TABLES无法禁用,只能修正应用层插入逻辑(补默认值、改字段为 NULL、加校验) - 导出视图或存储过程时,8.0 的语法校验更严,5.7 导出的
CREATE VIEW可能含隐式排序,导入会失败
字符集与排序规则默认值不向下兼容
8.0 默认 character_set_server=utf8mb4、collation_server=utf8mb4_0900_ai_ci,但旧表若没显式声明字符集,仍按 5.7 的 latin1 或 utf8(即 utf8mb3)存数据——结果就是中文插入报 Incorrect string value,ORDER BY 结果突变,甚至 Illegal mix of collations。
- 配置必须显式补全:
character-set-server=utf8mb4和collation-server=utf8mb4_unicode_ci(比_0900_ai_ci兼容性更好) - 导出要用
mysqldump --default-character-set=utf8mb4,否则 dump 文件里还是CHARSET=utf8 - 存量表要批量转换:
ALTER TABLE tbl CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
系统表结构和权限模型彻底重构
mysql.user 表字段重设计(password → authentication_string,新增 account_locked),且整个 mysql 库从 MyISAM 改为 InnoDB 只读视图。直接导入 5.7 的 mysql 库会导致 mysqld 启动崩溃,或权限丢失。
- 绝对不要用
mysqldump --all-databases;只导业务库:mysqldump --databases myapp_db - 所有权限操作必须走 SQL:
CREATE USER、GRANT、ALTER USER,禁止INSERT INTO mysql.user -
'user'@'localhost'和'user'@'127.0.0.1'在 8.0 是两个独立账号,连不上常因 host 匹配错位,不是密码问题
最易被忽略的是:这些改动不是“可选适配”,而是启动、连接、查询三个环节的硬性门槛。比如漏掉 local_infile=ON,LOAD DATA LOCAL INFILE 就直接报错;残留 query_cache_type,mysqld 根本启不来;rank 作为列名撞上 8.0 保留字,查询就抛 ERROR 1064。每个点都得实打实验证,不能靠“应该没问题”跳过。











