REPAIR TABLE EXTENDED 必须全表扫描,因 MyISAM 的 .MYI 文件不存校验和与行偏移信息,索引严重错乱时只能丢弃索引树、逐行读取 .MYD 重建索引,过程绕过缓存、触发大量磁盘寻道与写放大,I/O 成主要瓶颈。

MyISAM修复为什么必须全表扫描
因为 .MYI 文件不存校验和、也不记录每行在 .MYD 中的物理偏移是否有效。索引块损坏或 delete-link 链断裂时,MySQL 无法局部修复逻辑一致性,只能丢弃整个索引树,再逐行读取 .MYD 重建——这不是“修”,是“重做”。
这个过程绕过所有缓存机制,直接调用 pread()/pwrite(),且重建的 B-tree 索引写入会频繁触发块分裂和重分配,造成严重写放大。
磁盘 I/O 是瓶颈,不是 CPU 或内存
实测中,一块 SATA SSD 上修复 50GB MyISAM 表,iowait 常超 90%,而 CPU idle 仍在 60% 以上。关键原因有:
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
-
.MYD是顺序存储,但修复时按索引插入顺序随机访问 → 大量磁盘寻道 - 临时文件(如
repair_xxx.MYI)与原文件在同一分区 → 读写竞争加剧 -
myisam_recover_options=BACKUP,FORCE会触发自动修复,每次查询命中损坏表都加独占锁并重扫全表 → 锁等待叠加 I/O 延迟
REPAIR TABLE EXTENDED 和 USE_FRM 的开销差异
EXTENDED 模式至少还会跳过部分 header 校验;而 USE_FRM 完全忽略原有 .MYI 和 .MYD 的内部状态,强制从头开始:
- 对每个索引字段重复解析同一行(比如联合索引
(a,b,c)就要提取三次字段值) - 全文索引重建需额外分词、倒排、压缩,CPU 和 I/O 双重压力陡增
- 全程单线程,无法利用多核
最容易被忽略的三个事实
很多人以为加大 key_buffer_size 或换更快 CPU 就能提速,其实完全无效:
- 修复过程不走 MySQL 缓存路径,
key_buffer_size对它没影响 -
innodb_flush_log_at_trx_commit=1这类 InnoDB 参数在 MyISAM 修复中纯属干扰项 - 哪怕
myisamchk -r返回 OK,也只代表文件结构可加载,不代表数据字段没错位、主键没重复、UTF-8 字节没截断










