MySQL 8.0.16+ 数据字典损坏时,mysql_upgrade已被彻底移除,强行运行会加剧元数据混乱;真正有效修复路径只有两条:一是用同版本干净实例导出mysql库结构并替换原系统表文件,二是重建数据字典后导入逻辑备份。

别跑 mysql_upgrade —— 它在 MySQL 8.0.16+ 已被彻底移除,强行运行只会让数据字典更混乱。
看到 MY-010020 或 ER_DD_VERSION_INSTALLED 就停服务
这两个错误码本质相同:InnoDB 在 srv_start() 阶段调用 dd::bootstrap::initialize_dd() 失败,说明系统库 mysql 的元数据(如 tables、columns)根本没挂载上。不是“升级没做完”,而是数据字典结构已断裂。
- MY-010020 通常伴随启动直接 abort,日志里紧跟着
Data Dictionary initialization failed - ER_DD_VERSION_INSTALLED 多出现在降级或跨大版本迁移后,错误信息里会带具体版本号,比如
Expected DD version: 80032, found: 80025 - 不要用
--skip-grant-tables启动后执行任何 DML 或 DDL —— 此时数据字典不可用,操作可能写入脏页或触发崩溃
先确认是不是残留旧文件导致的假性损坏
很多“字典损坏”其实是升级时没清理干净造成的。重点检查 /var/lib/mysql/mysql/(Linux)或 C:\ProgramData\MySQL\MySQL Server X.Y\data\mysql\(Windows)目录下是否混有旧版残留:
- 存在
proc.frm、help_topic.frm等 .frm 文件?MySQL 8.0+ 已弃用 .frm,这些是 5.7 遗留,必须删除 - 存在
innodb_index_stats.ibd但无对应.sdi文件?说明表空间与数据字典元数据脱钩,不能靠ALTER TABLE ... IMPORT TABLESPACE恢复 - 整个
mysql目录下有非标准文件(如ibtmp1、ib_logfile*被手动替换过)?这类操作会破坏字典初始化顺序
真正有效的修复路径只有两条
所有“在线修复”方案(比如改配置、删单个文件、重跑工具)在 MySQL 8.0+ 数据字典损坏场景下成功率低于 5%,且极易引发二次不可逆损坏。可靠做法只有:
-
路径一(推荐):用同版本干净实例导出系统库结构
启动一个全新未初始化的 MySQL 8.x 实例:
mysqld --initialize-insecure --datadir=/tmp/clean→ 进入后执行:mysqldump --no-data --skip-triggers --skip-routines mysql > mysql_struct.sql→ 停故障实例 → 替换原/var/lib/mysql/mysql/下所有.ibd和.sdi文件(保留ibdata1、ib_logfile*不动)→ 重启 -
路径二(兜底):重建数据字典并导入逻辑备份
仅当无干净实例且有完整
mysqldump备份时可用。停服务 → 删除整个/var/lib/mysql(除ibdata1外)→mysqld --initialize-insecure --datadir=/var/lib/mysql→ 启动 → 手动创建 root 用户 → 导入备份:mysql -u root -p
为什么不能直接删 ibdata1 或用 innodb_force_recovery
ibdata1 里存着数据字典的根页(DD root page),删它等于砍掉字典的树干;而 innodb_force_recovery 只影响用户表恢复流程,对系统库 mysql 的加载完全无效——它压根不走那套 recovery 流程。你在配置里加了 innodb_force_recovery = 1 却还看到 MY-010020,就是这个原因。
最常被忽略的一点:MySQL 9.6.0(2026 年发布)已将外键约束上移至 SQL 层,如果你是从 8.x 升级到 9.6.0,旧版 mysql.foreign_keys 表结构会直接不兼容,此时连“干净实例导出结构”都需用 9.6.0 版本执行,否则导入后仍报错。


















