myisam表空间是多文件,由.frm(表结构)、.myd(数据)、.myi(索引)三个独立文件组成,无共享表空间概念,删表即直接删除这三个文件。

MyISAM 表空间是单文件还是多文件?
MyISAM 引擎把一张表拆成三个物理文件:.frm(表结构)、.MYD(数据)、.MYI(索引)。没有统一的“表空间”概念,也不存在共享表空间一说。每个表独占一组文件,删表就是直接删这三个文件。
常见误区是以为 innodb_file_per_table=OFF 时 MyISAM 也会进系统表空间——不会,它压根不走 InnoDB 那套逻辑。
-
.MYD文件默认用动态行格式,插入/删除频繁时容易产生碎片,OPTIMIZE TABLE实际就是重建.MYD+.MYI - 如果磁盘上看到大量小
.MYD文件但data_length很小,大概率是没做定期优化,碎片率已超 40% - 迁移 MyISAM 表时必须三文件一起拷,只复制
.frm会导致 Error 1033 (HY000): Incorrect information in file: ‘xxx.MYI‘
InnoDB 的 ibdata1 和独立表空间怎么选?
关键看 innodb_file_per_table 配置:ON 时每张表一个 .ibd 文件;OFF 时所有表数据和索引都挤进共享表空间 ibdata1(可能还有 ibdata2 等)。
生产环境几乎都该设为 ON。OFF 模式下最头疼的是:即使删掉几十 GB 的大表,ibdata1 文件体积也不会缩小,因为空间不会返还给文件系统。
- 从 OFF 切到 ON 不会自动迁移旧表,需逐个执行
ALTER TABLE t ENGINE=InnoDB -
.ibd文件可直接用cp或xtrabackup --copy-back拷贝,但必须保证 mysql 已执行FLUSH TABLES t WITH READ LOCK或停机 - 误删
.ibd后仅剩.frm,无法通过CREATE TABLE LIKE恢复数据——InnoDB 元数据在ibdata1里,没它就找不到数据页位置
如何查看某张表实际占用的磁盘空间?
别只看 information_schema.TABLES 里的 data_length 和 index_length,那只是引擎估算值。真实大小得看文件系统:
SELECT table_name, engine, round((data_length + index_length) / 1024 / 1024, 2) AS size_mb FROM information_schema.TABLES WHERE table_schema = 'db_name' AND table_name = 't';
然后对比磁盘上对应文件:
- MyISAM:
ls -lh /var/lib/mysql/db_name/t.MYD - InnoDB(
innodb_file_per_table=ON):ls -lh /var/lib/mysql/db_name/t.ibd - InnoDB(
innodb_file_per_table=OFF):ls -lh /var/lib/mysql/ibdata1—— 此时单表空间不可见
两者差异超过 10% 就说明有明显碎片或未刷新的脏页。
truncate table 为什么比 delete 快,又为什么不能回滚?
TRUNCATE TABLE 是 DDL 操作,InnoDB 会直接释放整张表的数据页,重置 .ibd 文件大小(或清空 ibdata1 中对应段),不写 undo log,也不触发触发器。
而 DELETE FROM t 是 DML,逐行标记删除、写 undo log、维护 MVCC 版本链——即使加了 WHERE 1=0,开销也远大于 truncate。
- MyISAM 下
TRUNCATE实际等价于DROP TABLE+CREATE TABLE,会重建.MYD和.MYI - InnoDB 下
TRUNCATE后自增 ID 重置为 1,但DELETE不会 - 事务中执行
TRUNCATE会隐式提交当前事务,之后不能再ROLLBACK—— 这点常被忽略,尤其在存储过程中混用时
InnoDB 表空间管理的核心其实是“段(segment)→ 区(extent)→ 页(page)”三级结构,但日常运维真正卡住人的,往往就是 ibdata1 膨胀后无法收缩、.ibd 文件权限错乱导致启动失败、或者误以为 OPTIMIZE TABLE 能回收 ibdata1 空间。这些地方不翻源码也得摸清行为边界。