mysql 8.0.16+ 报 data dictionary initialization failed、my-010020 或 er_dd_version_installed,表明数据字典元数据已断裂,系统库 mysql 表结构未挂载;mysql_upgrade 已被移除,强行运行会加剧混乱;真正有效修复路径只有两条:一是用同版本干净实例导出 mysql 库结构并替换原系统表文件,二是重建数据字典后导入逻辑备份。

MySQL 8.0.16+ 升级后报 Data Dictionary initialization failed、MY-010020 或 ER_DD_VERSION_INSTALLED,说明数据字典元数据已断裂,不是“升级没做完”,而是系统库 mysql 的表结构(如 tables、columns)根本没挂载上。别跑 mysql_upgrade——它在 8.0.16+ 已被彻底移除,强行运行只会让问题更糟。
确认是不是真损坏,还是残留文件导致的假性失败
很多“字典损坏”其实是升级时没清理干净造成的。重点检查 /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*被手动替换过)?这类操作会破坏字典初始化顺序
看到 MY-010020 就停服务,别碰 --skip-grant-tables
MY-010020 和 ER_DD_VERSION_INSTALLED 本质相同:InnoDB 在 srv_start() 阶段调用 dd::bootstrap::initialize_dd() 失败。此时数据字典不可用,任何 DML/DDL 都可能写入脏页或触发崩溃:
-
--skip-grant-tables只跳过权限检查,无法修复缺失的字典表结构;强行UPDATE mysql.user会失败,因为底层表已不可直接操作 - 错误日志里若出现
Table 'mysql.user' doesn't exist或Incorrect information in file: './mysql/user.sdi',才是真字典损坏信号 - 若日志是
Address already in use或unknown variable 'skip-grant-tables',那就不是字典问题,得查端口、配置语法或 SELinux
真正有效的修复路径只有两条
所有“在线修复”方案(比如改配置、删单个文件、重跑工具)在 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→ 启动后立即用备份恢复业务库
复杂点在于:Windows 路径必须统一用正斜杠(C:/ProgramData/MySQL/MySQL Server 8.0/Data),混用反斜杠会导致 Failed to find valid data directory;LSN 不一致时,删 #innodb_redo 目录比调高 innodb_force_recovery 更有效——后者在 8.0 中只用于导出,不是修复手段。











