索引未丢失而是元数据与B+树结构脱节,需用ALTER TABLE t FORCE强制重建并执行ANALYZE TABLE更新统计信息,再通过SHOW INDEX、EXPLAIN和唯一性插入验证修复效果。
SHOW INDEX 显示索引存在,但 EXPLAIN 中 key 为 NULL、type 是 ALL——这不是索引丢了,是元数据与 B+ 树物理结构脱节了。备份还原后必须重建,否则优化器永远“看不见”真实索引能力。
MySQL 的查询优化器不看 SHOW INDEX 输出,它依赖两样东西:Cardinality(来自 ANALYZE TABLE)和 .ibd 文件中真实的 B+ 树页布局。物理备份(如直接拷贝 .ibd)或未加 --single-transaction 的 mysqldump 还原后,常见问题包括:
Cardinality 全为 0 或 NULL,哪怕表有百万行ibd 文件里 LSN 断层、未提交事务残留,导致 InnoDB 启动时跳过部分页校验SHOW INDEX 读的是数据字典(.frm 或 mysql.innodb_table_stats),而执行计划走的是内存中加载的页结构ALTER TABLE ... FORCE 比 ENGINE=InnoDB 更可靠ALTER TABLE t ENGINE=InnoDB 是隐式重建,它会尝试复用旧 .ibd 的页结构;一旦还原时已有轻微损坏(比如页校验失败、LSN 不连续),MySQL 就会静默跳过异常页,新索引树不完整。
ALTER TABLE t FORCE 则完全不同:它等价于 DROP + CREATE + INSERT SELECT,强制全量重刷所有数据页和索引页,绕过所有缓存和旧页解析逻辑。
REPAIR TABLE 更可控ANALYZE TABLE t,否则优化器继续用旧统计信息FORCE——单写 ENGINE=InnoDB 在多数还原失效场景下无效ALTER TABLE 重建索引MyISAM 的索引完全独立存在 .MYI 文件中。ALTER TABLE 只改 .frm 和重写 .MYD,根本不碰 .MYI。遇到 Incorrect key file for table 错误,必须用 REPAIR TABLE:
CHECK TABLE t;若报 record delete-link chain broken,必须加 EXTENDED
REPAIR TABLE t EXTENDED 会逐行扫描 .MYD 并重建 .MYI,但耗时长、IO 高SELECT @@tmpdir 指向空间充足的路径(临时文件 t.TMD 大小 ≈ 原索引文件 ×2)FLUSH TABLES 或重启 MySQL,否则缓存中的旧索引描述符仍在生效SHOW INDEX
重建不是“让命令不报错”,而是让查询真正变快。必须三步验证:
SHOW INDEX FROM t 确认 Cardinality 已非零(且与实际行数量级匹配)EXPLAIN SELECT * FROM t WHERE indexed_col = ?,确认 key 列显示索引名、type 不是 ALL
INSERT INTO t (indexed_col) VALUES (existing_value),确认报 Duplicate entry 而不是成功插入最容易被忽略的是最后一步:很多重建操作看似成功,但唯一性约束没恢复,后续业务就埋雷了。