mysql 5.7 实例升级至 8.0 前需满足:版本≥5.7.9(推荐5.7.44)、mysql库全为innodb引擎、无损坏.frm文件、通过mysqlsh util.checkforserverupgrade扫描无error项,并排除手动改系统表、非法时间值、大小写混用、废弃参数等隐性元数据问题。

检查 MySQL 5.7 实例是否满足 8.0 数据字典升级前提
MySQL 8.0 的数据字典已彻底从 MyISAM 表(.frm 文件)迁移到 InnoDB 表,这意味着所有系统表(如 mysql.tables、mysql.columns)都变成事务性对象,且不再允许直接操作文件。如果你的 5.7 实例还残留 MyISAM 系统表、或存在损坏的 .frm 文件、或使用了早期 5.7.x(如低于 5.7.9)版本,升级会直接失败或卡在 mysql_upgrade 阶段。
必须确认以下几点:
- 当前 5.7 版本 ≥
5.7.9;生产环境强烈建议先升到5.7.44(官方最终版)再升 8.0 - 运行
SELECT ENGINE, COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'mysql' GROUP BY ENGINE;,确保结果中没有MyISAM—— 若有,说明系统表未被正确初始化或曾被手动修改 - 执行
mysqlcheck --all-databases --check-upgrade,重点看是否报错Table is read only或Incorrect definition of table mysql.xxx
用 mysqlsh 的 util.checkForServerUpgrade 做元数据扫描
这是目前最可靠、覆盖最全的元数据兼容性检查方式。它不依赖旧版 mysql_upgrade,而是模拟 8.0 启动时对数据字典的加载逻辑,能提前暴露 mysql 库结构异常、字段类型越界、索引定义冲突等底层问题。
操作前需准备:
- 下载与目标 8.0 版本一致的
mysql-shell(如升 8.0.34 就用mysql-shell-8.0.34),不能混用低版本 shell - 确保 5.7 实例处于只读状态(
SET GLOBAL read_only = ON;),避免检查中途写入导致状态不一致 - 命令示例:
./mysqlsh -uroot -S /tmp/mysql.sock -e "util.checkForServerUpgrade({outputFormat: 'JSON'})"
重点关注输出中的 "error" 类型项,例如:
{"description": "Data dictionary upgrade required", "error": "The data dictionary must be upgraded before upgrading to MySQL 8.0."}
这类提示不是警告,是硬性阻断项,必须修复后才能继续。
警惕那些“看不见”的元数据破坏点
很多团队升级失败,不是因为大表 DDL 或字符集问题,而是某些看似无害的操作在 5.7 里被容忍,却在 8.0 数据字典校验中触发 panic。典型场景包括:
- 手动修改过
mysql.user表结构(比如加字段、改类型),8.0 启动时会拒绝加载该表 - 用老版
mysqldump导出再导入过系统库(尤其是mysql库),导致create_time/update_time字段值非法(如为'0000-00-00 00:00:00') - 启用了
lower_case_table_names=0但实际存在大小写混用的库名/表名,在 5.7 中可运行,8.0 数据字典初始化阶段会因元数据路径解析失败而中止 - 使用了已被移除的系统变量(如
query_cache_type)在my.cnf中配置,虽不影响 5.7 启动,但 8.0 初始化时读取mysql.server_cost等新系统表前会先校验配置,报错退出
升级后验证数据字典是否真正就位
完成 in-place 升级并启动 8.0 后,别急着切流量。数据字典迁移不是“启动成功”就等于完成,它分两阶段:第一阶段是服务启动时自动重建系统表结构;第二阶段是首次访问 information_schema 或执行 DDL 时填充元数据缓存。容易忽略的是后者 —— 如果你没做任何 DDL 或查询系统视图,INFORMATION_SCHEMA 仍可能返回空或旧数据。
快速验证方法:
- 执行
SELECT COUNT(*) FROM performance_schema.table_handles;—— 在 8.0 中该表应可查且有记录,5.7 中不存在此表 - 运行
SHOW CREATE TABLE mysql.columns;,确认引擎为InnoDB,且字段含hidden、column_key等 8.0 新字段 - 尝试创建一个不可见索引:
CREATE INDEX idx_name ON t1(name) INVISIBLE;,若报错Unknown syntax,说明数据字典未生效或版本识别错误
真正的难点不在升级动作本身,而在于 5.7 长期运行中积累的“隐性元数据偏差”——它们平时不报错,却会在 8.0 启动那一刻集中爆发。别信日志里的 “Server startup complete”,要亲手查几条关键元数据 SQL 才算落地。











