innodb页损坏需通过innodb_force_recovery导出数据而非repair table;先确认引擎、查错误日志定位损坏页,再逐级启用innodb_force_recovery(1-6),启动后立即mysqldump导出,最后手动修复自增id和外键。

Check Table 报 “Database page corruption” 是 InnoDB 页级损坏的明确信号
这不是索引错位或临时锁表问题,而是数据页(.ibd 文件中某个 16KB 页)校验和不匹配、页头损坏或链表断裂。MySQL 在 CHECK TABLE 中返回 Msg_text 含 Database page corruption 或 failed file read of table,基本可判定为物理页损坏——此时 SELECT 可能仍能返回部分行,但任何涉及该页的 WHERE、ORDER BY、JOIN 或后续写入都可能触发崩溃。
InnoDB 表遇到页损坏,别碰 REPAIR TABLE
REPAIR TABLE 对 InnoDB 表直接报错 Storage engine for the table doesn't support repair,不是权限或语法问题,是引擎根本不提供该能力。强行执行不仅浪费时间,还会掩盖真实线索(比如错误日志里本有 page no 12345 is corrupted,但被命令失败掩盖)。必须换路径:
- 先确认引擎:
SHOW CREATE TABLE your_table;看是否为ENGINE=InnoDB - 查错误日志定位具体页:
sudo tail -n 200 /var/log/mysql/error.log | grep -i "corrupt\|page.*[0-9]" - 若 MySQL 已无法启动,说明损坏影响到系统表空间(
ibdata1或关键系统页),需优先启用innodb_force_recovery
页损坏后还能读数据?用 innodb_force_recovery 导出是唯一可行路径
只要 MySQL 还能启得动(哪怕只读),就别删表、别重建、别信“在线修复工具”。目标只有一个:把还能读出来的数据捞出来。步骤严格按顺序来:
- 停应用写入,设 MySQL 实例为
read_only=ON - 在
/etc/my.cnf的[mysqld]段加一行:innodb_force_recovery = 1,然后重启服务 - 如果启不动,逐级提高到
2、3……最高到6(每次改完必须重启,且=4起会禁用 INSERT/UPDATE/DELETE) - 能连上后立刻导出:
mysqldump --single-transaction --routines --triggers your_db your_table > backup.sql - 导出成功后,注释掉
innodb_force_recovery并重启——它仅用于抢救,绝不能长期开启
修复后导入,外键和自增 ID 很可能不一致
从 mysqldump 导入的数据是逻辑快照,不带原始页结构。这意味着:
-
AUTO_INCREMENT值不会继承原表,可能从 1 开始或跳变,应用插入前需手动ALTER TABLE ... AUTO_INCREMENT = N - 外键约束不会自动重建,
mysqldump默认不导出FOREIGN KEY定义(除非加--skip-triggers --skip-routines外显指定),导入后要检查并手动补全 - 二级索引与聚簇索引的一致性靠导入过程重建,但若原表已有逻辑不一致(如事务中断导致部分行未写入二级索引),dump 时就已漏掉,无法回溯
真正难处理的从来不是“怎么修”,而是“修完谁来验证这 27 万行数据里有没有静默丢掉那 3 行”。页损坏一旦发生,备份是否可用、日志是否完整、应用层是否有幂等兜底,这些比命令本身重要得多。











