必须立刻停写入,设read_only=on,逐级启用innodb_force_recovery(1→6)启动mysql,用mysqldump导出可用数据,成功后删除该参数并重建数据目录,严禁修复旧目录或长期启用该参数。

必须立刻停写入,别删文件、别重装、别跑REPAIR TABLE——InnoDB 表页损坏时,唯一安全路径是用 innodb_force_recovery 逐级启动 + mysqldump 导出 + 重建数据目录。
看到 InnoDB: Database page corruption on disk 就该做什么
这不是警告,是紧急制动信号。MySQL 已在校验时发现某个 16KB 页(可能在 ibdata1、某个 .ibd 文件或系统表空间)内容异常。此时磁盘未必坏、文件未必全损,但继续写入会把还能读的页也拖垮。
- 立刻停止应用写入,设
read_only=ON(如果还能连上) - 不要手动删
.ibd、ibdata1或日志文件 - 不要尝试用
myisamchk或REPAIR TABLE—— InnoDB 不支持 - 不要跳过
innodb_force_recovery=1直接设成 4 或 6
innodb_force_recovery=1 到 =6 怎么选、怎么试
这个参数不是“修复开关”,而是“绕过检查开关”。值越大,跳过的恢复逻辑越多,数据一致性风险越高。官方明确说 =4 起永久禁用写操作,=6 仅允许读取且不保证所有页可访问。
-
innodb_force_recovery = 1:跳过脏页检查,适合单个索引页损坏;多数轻量损坏在此级就能连上 -
=2:禁用 purge thread;若崩溃由后台清理触发,常能启动 -
=3:跳过事务回滚;未提交事务丢失,但已提交数据通常可导出 -
=4及以上:自动启用read_only=ON,且跳过 undo 扫描、redo 应用等关键步骤;只在 1–3 失败时考虑,且必须先在测试环境验证
每次改完配置后必须重启 mysqld,并立刻执行 mysql -u root -e "SELECT 1" 验证是否连得上,再查关键表能否 SELECT COUNT(*) ——不要等到 mysqldump 才发现失败。
mysqldump 导出时遇到 Error 2013 或卡死怎么办
即使启用了 innodb_force_recovery,mysqldump 仍可能在读到损坏页时断连(报 Error 2013: Lost connection)或卡住。这不是配置问题,而是目标表本身有物理页损坏。
- 先用
SHOW TABLE STATUS LIKE 'table_name'查Data_length和Index_length,值为 0 或明显偏小的表大概率已损坏 - 导出时加
--ignore-table=db_name.corrupt_table排除已知坏表,保主干库 - 对关键但损坏的表,尝试分批读:
SELECT * FROM table_name LIMIT 10000 OFFSET 0,观察在哪一批中断,再调整OFFSET绕开(InnoDB 不保证页内行连续,但有时有效) - 避免用
--all-databases一次性导出;分库、分表导出更可控
导完数据后最关键的一步:清掉 innodb_force_recovery 并重建
这个参数只是临时救命开关,绝不能长期开着运行生产服务。它会让 InnoDB 跳过一致性保障机制,后续任何写入都可能放大损坏。
- 导出完成后,必须从
my.cnf中彻底删除或注释掉innodb_force_recovery行 - 停止 MySQL,清空旧数据目录(
datadir),再初始化新实例 - 用
mysqldump导入数据,而不是试图“修复”旧目录 - 导入后务必校验关键表的行数、时间字段和业务逻辑记录,不能只看导入成功与否
最容易被忽略的是:很多人导完就以为结束了,结果忘了删 innodb_force_recovery,或者直接在旧目录上重启服务——这等于把一颗定时炸弹留在线上。











