必须用mysqlsh的util.checkforserverupgrade()做5.7→8.0升级前检查,它能全面扫描字符集、认证插件、保留关键字等兼容性问题;mysqlcheck仅校验表结构,无法识别跨版本语义变更。

util.checkForServerUpgrade() 是唯一值得信任的前置检查入口,其他工具(比如 mysqlcheck --check-upgrade)只校验表结构,对字符集、认证插件、保留字等关键兼容性问题完全无感。别跳过这步,否则启动失败或半夜告警是大概率事件。
怎么用 mysqlsh 做真实有效的升级前检查
不是装个 mysql-shell 就能跑,必须匹配目标版本(如 8.0.42),且连接方式要稳定:
- 用 socket 连接比 TCP 更可靠:
./mysqlsh -uroot -p -S /tmp/mysql.sock -e "util.checkForServerUpgrade()" - 加
configPath参数让检查覆盖配置项:util.checkForServerUpgrade({'configPath': '/etc/my.cnf'}) - 输出重定向到文件后,重点盯
ERROR级条目——比如Usage of utf8mb3 charset或Column name 'rank' is a reserved keyword,这些必须改完才能继续 - 报告里出现
caching_sha2_password plugin not supported by client,说明你的应用驱动太老,得确认mysql-connector-java ≥ 8.0.13或PyMySQL ≥ 0.10.0
为什么不能直接覆盖 /usr/local/mysql 目录
硬覆盖二进制包会埋下三类隐形雷:
-
mysqld二进制里硬编码了旧路径(查readelf -d bin/mysqld | grep RUNPATH),导致找不到库而启动失败 - 旧
my.cnf里残留query_cache_type、explicit_defaults_for_timestamp等已废弃参数,日志只报unknown variable,排查极慢 - SELinux 上下文被破坏(尤其 CentOS 7),
chcon -R --reference=/var/lib/mysql /usr/local/mysql才能救回来
in-place 升级启动失败的头号原因
不是数据坏了,而是启动时卡在 “Starting MySQL” 或秒退,常见于:
- 没删 MyISAM 表:8.0 默认禁用 MyISAM 引擎,
SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE ENGINE = 'MyISAM'查出来就得先ALTER TABLE ... ENGINE=InnoDB - 系统库
mysql下有自定义表名撞了新系统表(比如叫roles、role_edges),必须重命名或删掉 - 权限不对:
/var/lib/mysql目录属主不是mysql:mysql,或datadir路径下有孤儿.frm文件(删掉对应表或修复再试) - 没设认证插件:
default_authentication_plugin=mysql_native_password必须显式写进[mysqld]段,否则老客户端连不上
升级后第一分钟该验证什么
进程起来了 ≠ 数据库就绪,以下四条命令缺一不可:
-
SELECT VERSION(), @@sql_mode;—— 确认是8.0.x且含ONLY_FULL_GROUP_BY -
SHOW VARIABLES LIKE 'default_authentication_plugin';—— 返回caching_sha2_password?立刻建兼容用户:CREATE USER 'app'@'%' IDENTIFIED WITH mysql_native_password BY 'xxx'; -
SELECT * FROM performance_schema.replication_applier_status_by_coordinator;—— 开了复制的话,这里必须是APPLYING状态 -
SELECT COUNT(*) FROM mysql.user;—— 如果结果为 0 或报错,说明系统表升级失败,得回退重试
真正容易被忽略的是:升级不是“替换二进制 + 启动成功”就结束了,mysql 库里的表结构、performance_schema 的初始化、甚至 information_schema 的视图逻辑,都在首次启动时动态重建——这个过程无声无息,但一旦出错,后续所有权限、监控、备份都会异常。











