mysql存储引擎如何实现数据表空间管理_mysql数据存储解析

1次阅读

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

mysql存储引擎如何实现数据表空间管理_mysql数据存储解析

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 文件可直接用 cpxtrabackup --copy-back 拷贝,但必须保证 mysql 已执行 FLUSH TABLES t WITH READ LOCK 或停机
  • 误删 .ibd 后仅剩 .frm,无法通过 CREATE TABLE LIKE 恢复数据——InnoDB 元数据在 ibdata1 里,没它就找不到数据页位置

如何查看某张表实际占用的磁盘空间?

别只看 information_schema.TABLES 里的 data_lengthindex_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 空间。这些地方不翻源码也得摸清行为边界。

text=ZqhQzanResources