.myd是myisam表的数据文件,存储按插入顺序追加的原始字节流,含删除标记;.myi是索引文件,存b+树结构,叶子节点仅记录.myd中数据行的物理偏移量,二者与.frm配套使用,缺一不可。

MyISAM 的 .MYD 和 .MYI 与 InnoDB 的 .ibd 不是同类文件,不能简单类比为“数据 vs 数据+索引”——它们底层组织逻辑、访问路径、崩溃恢复能力完全不同,混用或迁移会直接导致表不可用。
MyISAM 的 .MYD 和 .MYI 是物理分离的裸数据块
MyISAM 把数据和索引彻底拆开:.MYD 就是一段连续字节流,按插入顺序追加,每行前面带 1 字节删除标记;.MYI 是独立的 B+ 树索引文件,叶子节点只存 .MYD 中的物理偏移量(比如“第 0 号文件,偏移 1280 字节”),不存任何实际数据。
- 删掉
.MYD,SELECT返回空,但SHOW CREATE TABLE仍能查出结构——因为.frm还在 - 只复制
.MYD到另一台机器,哪怕.MYI和.frm都齐全,MySQL 启动时大概率跳过该表,报错Table 'xxx' doesn't exist -
.MYD里没有事务头、回滚指针、隐藏字段,.MYI也不维护 MVCC 版本链——这意味着它无法做崩溃恢复,断电后可能丢最后几条写入
InnoDB 的 .ibd 是自包含的逻辑页容器
.ibd 不是纯数据堆,而是一个由 16KB 页组成的结构化文件:里面同时存聚簇索引(即主键+行数据)、二级索引、undo log 段、insert buffer、甚至部分事务系统信息。每一行数据都自带事务 ID、回滚指针、隐藏的 DB_ROW_ID 和 DB_TRX_ID 字段。
- 即使你删掉
.frm(MySQL 5.7 及更早),只要.ibd完整且 MySQL 能识别其 page header,就有可能用innodb_force_recovery+CREATE TABLE ... LIKE+ALTER TABLE ... IMPORT TABLESPACE恢复数据 -
.ibd文件内所有页通过 space id 和 page no 关联,不是靠外部偏移量寻址,所以支持跨实例迁移(需配套.cfg和严格版本匹配) - 它的写入必须经过 doublewrite buffer 和 redo log 两道保障,崩溃后可前滚恢复,不会出现 MyISAM 那种“数据文件半截写入却无感知”的状态
为什么不能用 cp .MYD .MYI 替代 mysqldump 或 ALTER TABLE ... ENGINE=InnoDB?
因为 .MYD/.MYI 是引擎私有二进制格式,没有公开文档定义其 record layout、index node 结构或 checksum 算法;而 .ibd 虽也未完全公开,但其页结构(page type、space id、checksum)已被逆向多年,Percona、Facebook 工具链(如 innodb-tools)能解析部分内容。
- 试图用
dd截取.MYD中某段字节“提取某几行”,大概率读出乱码——字段长度、NULL 标志位、变长字段偏移表全藏在.frm和内存 parser 里 - 把 MyISAM 表转成 InnoDB,不能只改文件后缀或移动文件,必须走 SQL 层:要么
ALTER TABLE t ENGINE=InnoDB(重建全表),要么mysqldump导出再导入(逻辑转换) - MySQL 8.0 默认禁用 MyISAM,
SHOW ENGINES中MyISAM的SUPPORT字段若为DISABLED,连.MYD/.MYI都不会生成——此时磁盘上根本看不到这两个文件
真正容易被忽略的是:MyISAM 的 .MYD 和 .MYI 在服务器重启后是否能被加载,不仅取决于文件存在,还依赖 myisam_recover_options 配置和 .MYI 头部校验和是否通过;而 .ibd 的可用性则绑定在 redo log 是否完整、doublewrite buffer 是否被破坏——两者的“损坏判定逻辑”不在同一维度上。











