delete不释放磁盘空间;truncate/drop也不缩回ibdata1或.ibd文件;optimize table仅在innodb_file_per_table开启时可回收独立.ibd空间,否则无效。

MySQL删完数据,磁盘空间没释放?这是正常现象
直接说结论:DELETE 只是标记行删除,不回收物理空间;哪怕 TRUNCATE 或 DROP 表,InnoDB 的表空间文件(ibdata1 或独立 .ibd)也往往不会自动缩回。你看到的“删了 100GB 数据但磁盘没少”,不是误操作,是 InnoDB 的设计使然。
OPTIMIZE TABLE 真的能缩表文件吗?看存储引擎和文件类型
OPTIMIZE TABLE 对 InnoDB 表的实际效果取决于是否启用了 innodb_file_per_table:
- 开启时(推荐且默认):会重建该表的独立
.ibd文件,真正释放未用空间并写入新紧凑文件 —— 磁盘空间可回收 - 关闭时:所有表共用
ibdata1,OPTIMIZE只能整理内部页,完全不缩小ibdata1大小,磁盘空间毫无变化
注意:OPTIMIZE 在执行期间会锁表(ALGORITHM=COPY 模式),大表可能阻塞业务数分钟甚至小时;MySQL 5.6+ 支持 ALGORITHM=INPLACE,但仅适用于部分操作,OPTIMIZE 默认仍走 COPY。
比 OPTIMIZE 更轻量的替代方案:ALTER TABLE ... FORCE
如果你只想触发重建而不带 OPTIMIZE 的语义开销(比如避免日志里一堆“Optimizing”提示),用这个等价命令更干净:
ALTER TABLE `your_table` ENGINE=InnoDB;
它本质就是重建表,行为和 OPTIMIZE TABLE 一致,但更明确表达意图。另外两个实用变体:
-
ALTER TABLE `t` FORCE:隐式重建,语法更短 -
ALTER TABLE `t` ROW_FORMAT=COMPACT;(或DYNAMIC):只要改了行格式,也会触发重建 + 整理碎片
所有这些操作都会产生临时文件,确保磁盘剩余空间 ≥ 当前表大小的 1.2 倍,否则会失败报错:ERROR 1034 (HY000): Incorrect key file for table。
真正要缩 ibdata1?别试了,只能重建实例
如果 innodb_file_per_table=OFF,或者你发现 ibdata1 膨胀到几十上百 GB 且无法收缩 —— 这是 InnoDB 的硬限制:没有在线命令能缩小 ibdata1。试图用 mysqldump 全库导出再导入,是最稳妥的路径,但意味着停机窗口。
容易被忽略的关键点:
-
OPTIMIZE不解决ibdata1膨胀,只对独立.ibd有效 -
innodb_file_per_table必须在建表前开启才对旧表生效;已存在的共享表空间表不会自动迁移 - 频繁
DELETE + INSERT的表,建议定期检查DATA_FREE字段:SELECT DATA_LENGTH, DATA_FREE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t';
碎片不是性能杀手,但长期积累的 DATA_FREE 占比超 25%,就该安排一次重建了。










