看到database page corruption on disk错误应立即停写入,而非删文件;此时数据未必全丢,需先定位损坏页,再从innodb_force_recovery=1逐级尝试启动并用mysqldump导出数据,成功后必须重建数据目录而非修复旧目录。

看到Database page corruption on disk错误就停服务,别急着删文件
这条错误意味着 InnoDB 检测到某个 .ibd 或系统表空间页(比如 ibdata1)校验失败,无法继续启动。此时 MySQL 会直接 abort,但**不代表数据全丢了**——只要磁盘物理没坏、页损坏不集中,多数情况能抢救出大部分数据。关键动作是:立刻停止写入尝试,先确认损坏范围,再决定 innodb_force_recovery 从哪一级开始试。
innodb_force_recovery=1 到 =6 的实际差异和启动顺序
参数值不是“越高越好”,而是按需递增。低值只绕过轻量恢复逻辑,高值会永久跳过事务回滚、redo 前滚等关键步骤,可能让数据处于不一致状态。真实场景中建议从 1 开始逐级试,每次修改后重启 mysqld 并立刻验证能否连上、能否 SELECT 出关键表:
-
1:跳过脏页检查,允许读取未损坏的页;适合单个索引页损坏 -
2:禁用 purge thread 和 master thread;若崩溃由后台清理触发,这个值常能启动 -
3:跳过事务回滚;此时未提交事务会被丢弃,但至少能导出已提交数据 -
4及以上:从 5.7.3 起自动设为read_only=ON,且会永久修改数据文件(如跳过 undo 扫描或 redo 应用),仅在1–3失败时考虑
注意:innodb_force_recovery 启用后,所有写操作(INSERT/UPDATE/DELETE/DROP)都会被拒绝,mysqldump 是安全的,但 mysqlpump 在某些版本可能因元数据锁失败,优先用 mysqldump。
导出数据时遇到 Error 2013 或表跳过怎么办
即使设置了 innodb_force_recovery,mysqldump 仍可能在读到损坏页时断连(报 Error 2013: Lost connection)或卡住。这不是配置错了,而是目标表本身有页损坏:
- 用
SHOW TABLE STATUS查看各表的Data_length和Index_length,异常小或为 0 的表大概率已损坏 - 导出时加
--ignore-table=db_name.corrupt_table排除已知坏表,先保主干数据 - 对关键但损坏的表,可尝试
SELECT * FROM table_name LIMIT 10000分批查,观察在哪一行中断,再用LIMIT+OFFSET绕开坏页(InnoDB 不保证页内行连续,但有时有效) - 避免用
--all-databases一次性导出;分库、分表导出更可控
导完数据后必须清掉 innodb_force_recovery 再重建
这个参数只是临时救命开关,**绝不能长期开着运行生产服务**。它会让 InnoDB 跳过一致性保障机制,后续任何写入都可能放大损坏。正确收尾流程是:
- 确认所有需要的数据已导出(建议校验 SQL 文件头尾和行数)
- 停掉 MySQL:
systemctl stop mysql - 删除或重命名原数据目录(如
/var/lib/mysql),保留一份备份 - 注释或删掉配置文件中的
innodb_force_recovery行 - 清空
ib_logfile*和ibdata1(如果用了独立表空间,.ibd文件可不删,但首次启动仍建议全新初始化) - 重启 MySQL,再用
mysql导入 SQL 文件
最容易被忽略的一点:很多人导完数据就直接改回配置重启,结果 MySQL 因残留的损坏页再次崩溃——**必须重建干净的数据目录,而不是“修好”旧目录**。











