某客户数据库突然报错: InnoDB: Table 'mysql.innodb_table_stats' not found ,检查发现mysql系统库中的大部分表显示“不存在”。经排查,客户曾误执行 rm ibdata1 和 rm ib_logfile* 命令 ——这正是问题的根源。
在 MySQL 8.0 以下版本中, ibdata1 文件承载着所有 InnoDB 表的数据 ,一旦被删除,所有 InnoDB 表都会在系统中“消失”,尽管物理上的 .frm 和 .ibd 文件可能仍然存在。
通过查看数据目录发现,所有 “不存在”的表都属于 InnoDB 存储引擎。进一步检查操作历史记录,发现了客户删除 ibdata1 和 redo 日志文件的关键记录。
在 MySQL 8.0 之前版本中,InnoDB 使用 共享表空间架构 ,ibdata1 文件是核心数据文件,包含了:
• 所有 InnoDB 表的元数据 • 数据字典信息
• 部分系统表数据
• undo 日志信息
删除 ibdata1 相当于删除了 InnoDB 的“大脑”,系统表虽然物理文件仍在,但 MySQL 服务已无法识别它们。
在开始恢复前,需要确保:
准备好与故障环境 相同版本的 MySQL 安装包
确认有足够的磁盘空间进行操作
备份当前所有数据文件(以防恢复失败)
关键原则: 任何恢复操作前,先备份!
注:其他系统表的恢复步骤与此完全相同
首先备份目标表的物理文件,包括 .frm(表结构)和 .ibd(表数据)文件:
shell> cp gtid_executed* /root/
这是最重要的安全网 ——如果后续操作出错,还可以从这里重新开始。
尝试删除这个 “不存在”的表:
mysql> drop table gtid_executed; ERROR 1051 (42S02): Unknown table 'mysql.gtid_executed'
这个操作会触发 MySQL 自动清理数据目录中的 gtid_executed.frm 文件。然后手动删除对应的 .ibd 文件:
shell> rm gtid_executed.ibd
至此,MySQL 和数据目录中关于这个表的记录都已被清除。
安装一个新的、同版本的 MySQL 实例(可以临时安装在其他目录),然后查看系统表的创建语句:
mysql> show create table mysql.gtid_executed;
系统表的创建语句在不同 MySQL 实例间是 完全一致 的,这是恢复的关键前提。记录下完整的 CREATE TABLE 语句。
在原 MySQL 中执行刚才获取的 CREATE TABLE 语句,重新创建表:
mysql> CREATE TABLE `gtid_executed` ( `source_uuid` char(36) NOT NULL COMMENT 'uuid of the source where the transaction was originally executed.', `interval_start` bigint(20) NOT NULL COMMENT 'First number of interval.', `interval_end` bigint(20) NOT NULL COMMENT 'Last number of interval.', PRIMARY KEY (`source_uuid`,`interval_start`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 STATS_PERSISTENT=0;
创建成功后,数据目录中会生成新的 gtid_executed.frm 和 gtid_executed.ibd 文件。但此时 .ibd 文件是空的,没有数据。
将新创建的表与系统表空间解绑:
mysql> alter table gtid_executed discard tablespace;
执行此命令后,MySQL 会删除数据目录中的 gtid_executed.ibd 文件,但保留表结构定义。
将步骤1中备份的原始 .ibd 文件移回数据目录,并确保文件权限正确:
shell> mv /root/gtid_executed.ibd ./ shell> chown mysql:mysql gtid_executed.ibd
最后一步,将原始数据文件重新绑定到表:
mysql> alter table gtid_executed import tablespace;
执行成功后,表恢复正常,数据完整恢复。
所有受影响的 InnoDB 系统表都可以按照相同的流程恢复:
mysql.innodb_table_stats (存储 InnoDB 表统计信息)
mysql.innodb_index_stats (存储 InnoDB 索引统计信息)
其他所有显示 “不存在”的 InnoDB 系统表
只需将上述流程中的 gtid_executed 替换为对应的表名,重复执行即可。
• 此方法 仅适用于 MySQL 8.0 以下版本
• MySQL 8.0 已改为 每表独立的表空间 ,ibdata 的作用已大大减小
• 不同小版本间的系统表结构 必须完全一致
在移动 .ibd 文件时,必须确保文件所有者和权限正确:
#
查看当前
MySQL
运行用户
shell> ps aux | grep mysqld
#
设置正确权限(假设
MySQL
以
mysql
用户运行)
shell> chown mysql:mysql gtid_executed.ibd shell> chmod 660 gtid_executed.ibd
错误1: Schema mismatch
• 原因:备份的 .ibd 文件与当前表结构不匹配
• 解决:确保从完全相同的 MySQL 版本获取 CREATE TABLE 语句
错误2: Tablespace is missing
• 原因:.ibd 文件路径或权限不正确
• 解决:检查文件是否存在、路径是否正确、权限是否合适
错误3: Row size too large
• 原因:MySQL 配置不一致
• 解决:确保新旧环境的 innodb_page_size 等参数一致
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29956245/viewspace-3117177/ ,如需转载,请注明出处,否则将追究法律责任。