MySQL InnoDB 紧急修复指南

字数: 309 · 阅读: 2 分钟 · 访问: -

一、什么是 innodb_force_recovery?

当 InnoDB 引擎因为损坏、undo/redo 异常、元数据不一致而无法启动时,你可以使用:

innodb_force_recovery = <0~6>

让 MySQL “带病启动”,然后尽快把数据导出来。

它不是修复器,它是:

给你一次只启动、不执行危险操作的机会,让你把数据抢救出来。


二、六个等级:从温柔到残酷

innodb_force_recovery 有 0–6 共七个值(0 为正常模式), 越高越危险,越可能导致数据丢失。

下面我做一份你可以直接贴到办公桌前的表:

等级含义风险常见场景
0正常无风险MySQL 正常恢复或不需要强制
1跳过后台清理(最安全)极低崩溃恢复失败、InnoDB 卡住
2禁止主线程运行,跳过一些后台任务undo 回滚卡死
3关闭 redo 日志应用(危险)中高redo 损坏,无法启动
4忽略 undo 日志(很危险)undo 损坏、无法回滚事务
5禁止检查线程、跳过大部分恢复很高数据字典存在问题
6跳过绝大多数 InnoDB 处理(灾难级)极高最后孤注一掷的方式

请记住:3 以上就是“带血的刀”,必须谨慎。 6 是“最后的绝唱”。启动起来但不要对其做任何写入。


三、什么时候该用?判断标准很简单

如果你看到:

MySQL 启动失败,错误日志出现:

  • InnoDB: corruption
  • InnoDB: redo log is corrupted
  • InnoDB: unable to find tablespace
  • InnoDB: invalid undo
  • Got signal 6/11
  • Data Dictionary corruption

那么,你需要它。

但记住:

目标不是“修”,而是“能启动,然后导出数据”。


四、常见故障 → 应该用哪个等级?

下面是实战经验总结,非常好用。


① 场景:InnoDB 崩溃恢复卡住(常见)

错误示例:

InnoDB: Starting crash recovery...
InnoDB: Stuck in apply redo log

建议使用:1 或 2

它会跳过一些后台清理,让你顺利启动。


② 场景:redo log 损坏

错误示例:

InnoDB: redo log corrupted

建议使用:3

因为 3 会绕过 redo 应用。

⚠ 注意: 启动后数据可能不一致,但你能 dump。


③ 场景:undo log 损坏

错误示例:

InnoDB: Invalid undo log

建议使用:4

它会跳过 undo 回滚。


④ 场景:数据字典(Data Dictionary)坏了

错误示例:

InnoDB: Data Dictionary corruption

✔ 使用:5 或 6

这是最糟糕的情况,可能需要导出残余表结构并重建实例。


五、操作流程(最关键部分)

第一步:修改 MySQL 配置文件

在 my.cnf 中加入:

[mysqld]
innodb_force_recovery = 1

根据实际情况换 1-6。


第二步:启动 MySQL

systemctl start mysqld

service mysql start

第三步:立刻导出数据库(最重要的动作)

导出全库

mysqldump -u root -p --all-databases > full_dump.sql

导出指定数据库

# 单个数据库
mysqldump -u root -p dbname > db_$(date +%T).sql

# 多个数据库
mysqldump -u root -p --databases db1 db2 db3 > dbs_$(date +%T).sql

导出单表

mysqldump dbname table_name > table.sql

这是你“救命”的关键步骤。


第四步:尝试修复 MySQL

# 查看所有表状态
CHECK TABLE db.table;

# 查看 InnoDB 状态(非常重要)
SHOW ENGINE INNODB STATUS\G

# * 哪个表空间损坏
# * 哪个 index 出问题
# * 哪个事务卡住

# 检查所有数据库的表
mysqlcheck -uroot -p --all-databases --check

# 如果发现问题,尝试修复
mysqlcheck -uroot -p --all-databases --repair

# 或者针对特定数据库
mysqlcheck -uroot -p --repair <database_name>

# 恢复单表 .ibd 文件(file_per_table = ON)

ALTER TABLE table_name DISCARD TABLESPACE;
ALTER TABLE table_name IMPORT TABLESPACE;

第五步:重建数据实例

  • 如果修复失败,你需要重建数据实例。
# 创建新实例
mysqld --initialize-insecure --user=mysql

# 启动新实例
systemctl start mysqld

# 导入全库
mysql < full_dump.sql

导航 文章 分类 标签