mysql大版本升级前必须确认5件事:确认真实版本、检查myisam表并转innodb、验证用户认证插件兼容性、运行mysqlcheck检查不兼容项、执行含物理文件的完整备份。

MySQL 大版本升级前必须确认的 5 件事
不能直接 apt upgrade mysql-server 或替换 RPM 包——大版本升级(如 5.7 → 8.0)不是补丁更新,底层数据字典、默认认证插件、SQL 模式都变了,跳过校验大概率导致服务起不来或数据不可读。
-
mysqld --version和SELECT VERSION();确认当前真实版本(有些镜像里mysql --version显示客户端版本,会误判) - 检查是否用了
MyISAM表——8.0 虽仍支持,但已废弃,mysql_upgrade不再修复其索引损坏,必须先转成InnoDB - 确认所有用户密码不是用
mysql_native_password以外的插件(如caching_sha2_password在旧客户端可能连不上,尤其 PHP 7.4 以下、Navicat 旧版) - 运行
mysqlcheck -u root -p --all-databases --check-upgrade,它比人工扫INFORMATION_SCHEMA更准,能提前暴露不兼容的 JSON 字段、隐藏列等 - 备份不是“导出 SQL”,必须包含
mysqldump --all-databases --routines --triggers --events --single-transaction+ 原始ibdata1和ib_logfile*的物理备份(用于回滚)
8.0 升级后登录失败:caching_sha2_password 是真凶
升级完启动正常,但应用连不上,错误是 Plugin caching_sha2_password could not be loaded 或 Authentication plugin 'caching_sha2_password' cannot be loaded——这不是 MySQL 没装好,是客户端不认新默认插件。
- 临时解法(仅调试):
ALTER USER 'xxx'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd'; FLUSH PRIVILEGES; - 长期方案:PHP 用
mysqli_options($link, MYSQLI_OPT_SSL_MODE, MYSQLI_SSL_DISABLED)配合新版驱动;Java JDBC 连接串加?serverTimezone=UTC&allowPublicKeyRetrieval=true&useSSL=false - 别改全局
default_authentication_plugin:它只影响新建用户,已有用户密码哈希方式不变,改了反而让部分用户无法登录
mysql_upgrade 不再可用:8.0.16+ 必须用 mysqld --upgrade
执行 mysql_upgrade 报错 Command not found 或 This command is deprecated——没错,它从 8.0.16 开始被移除。升级逻辑已合并进 mysqld 启动流程,手动调用只会白忙。
- 正确做法:停掉老实例,用新
mysqld二进制启动,加上--upgrade=FORCE参数(首次启动必须加,否则跳过系统表检查) - 路径要对:确保
--datadir指向原数据目录,且新mysqld有该目录的读写权限(常见坑:SELinux 未重标标签,ls -Z看 context 是否还是mysqld_db_t) - 日志里搜
Upgrading system tables和Checking for insecure default user accounts,这两行出现才代表升级逻辑真正跑完了
字符集与排序规则变更引发的隐性故障
应用没报错,但模糊查询变慢、ORDER BY 结果乱序、LIKE '%中文%' 查不到——大概率是 utf8mb4_0900_as_cs 排序规则生效了,它比旧的 utf8mb4_general_ci 严格得多,大小写、重音、宽度都参与比较。
- 查当前库默认规则:
SELECT DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'your_db'; - 降级兼容(不推荐长期):
ALTER DATABASE your_db CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - 更稳妥:在 SQL 层显式指定规则,比如
WHERE name COLLATE utf8mb4_unicode_ci = 'ABC',避免依赖库级默认值 - 注意:修改库规则不会自动改表字段的
COLLATE,得单独ALTER TABLE t MODIFY c VARCHAR(100) COLLATE utf8mb4_unicode_ci;
最麻烦的不是升级动作本身,是那些没写在文档里的隐性依赖:某个定时任务用 SELECT * FROM mysql.user 解析权限,8.0 里这个表结构全变了;又或者监控脚本靠 SHOW VARIABLES LIKE 'max_connections' 判断负载,而 8.0 新增了 max_connections 动态变量和 max_connections 系统变量两个同名不同源的值——这些细节不逐项核对,上线后问题会漏出来,而且很难归因。











