innodb 删除数据不释放磁盘空间,因其仅标记记录为可复用,不自动归还页内空闲空间给操作系统;必须通过 alter table 或 optimize table 重建表才能真正收缩文件。

为什么删了数据,磁盘空间却不释放?
这是 InnoDB 表最常被误解的现象:执行 DELETE FROM t WHERE ... 后,du -sh /var/lib/mysql/xxx/ 看到的文件大小几乎不变。原因不是 MySQL “忘了回收”,而是 InnoDB 的删除只是“打标记”——把记录标记为可复用(purge 队列里等后续清理),但页内空闲空间不会自动归还给操作系统,更不会收缩 ibdata1 或独立表空间文件(.ibd)。
MyISAM 则不同:它的 .MYD 文件在 DELETE 后会真正截断或复用,配合 OPTIMIZE TABLE 能较干脆地回收磁盘空间。
- InnoDB 必须靠
ALTER TABLE t ENGINE=InnoDB或OPTIMIZE TABLE t触发重建表(本质是创建新表 + 拷贝有效行 + 交换),才能真正释放空洞、压缩文件 - 这个操作会加元数据锁(MDL),阻塞写入;在线 DDL(如
ALGORITHM=INPLACE)仅适用于部分场景,不是所有版本都默认支持 - 如果启用了
innodb_file_per_table=0,所有表共用ibdata1,那OPTIMIZE根本无效——空间永远无法还给系统
MyISAM 和 InnoDB 的空间行为差异在哪?
核心区别在「存储组织方式」:
MyISAM 是堆表(heap table),数据按插入顺序堆放,索引和数据分离;InnoDB 是聚簇索引表,主键即数据,非主键索引叶子存主键值。这直接导致空间管理逻辑完全不同。
- MyISAM 的
.MYI索引文件可被REPAIR TABLE或OPTIMIZE TABLE紧凑化;.MYD数据文件也能被重写压缩 - InnoDB 的页内碎片(page fragmentation)靠
innodb_page_cleaner异步处理,但跨页空洞只能靠重建表;且每页默认 16KB,即使只存几字节,也占满一页 - MyISAM 不支持事务,没有 undo log、redo log,因此无日志文件膨胀问题;InnoDB 的
ib_logfile*和 undo 表空间(ibdata1或独立undo_001)也会持续增长,尤其长事务未提交时
什么时候该换引擎?别只看“删不删得干净”
单纯为了“删完立刻瘦下来”,就切到 MyISAM 是危险的妥协。2026 年绝大多数生产环境已不该再用 MyISAM——它不支持行锁、崩溃恢复弱、无 MVCC、无法热备份(mysqldump 锁全表)。
- 若业务以高频写入+随机删除为主(如日志归档、消息队列中间表),优先确认是否真需要 InnoDB 的事务保障;否则可考虑
TokuDB(高压缩比、支持事务)或ROCKSDB(Percona Server 支持),它们对 delete 空洞更友好 - 若必须用 InnoDB,确保
innodb_file_per_table=1(默认已开启),避免ibdata1无限膨胀;同时定期监控information_schema.INNODB_SYS_TABLESPACES中FILE_SIZE与ALLOCATED_SIZE的差值,判断空洞率 - 对只读或低频更新的大表(如维表、配置快照),可设为
ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8,实测压缩率常达 50%~70%
一个安全又省事的空间回收流程
不要直接跑 OPTIMIZE TABLE ——它在大表上可能锁数小时。推荐分三步走:
- 先查空洞程度:
SELECT DATA_LENGTH, INDEX_LENGTH, DATA_FREE FROM information_schema.TABLES WHERE TABLE_SCHEMA='db' AND TABLE_NAME='t';,若DATA_FREE> 20%DATA_LENGTH,才值得优化 - 用
pt-online-schema-change(PT-OSC)替代原生命令:pt-online-schema-change --alter "ENGINE=InnoDB" D=db,t=t --execute,全程不锁表(依赖触发器,需确保从库延迟可控) - 优化后检查:
ls -lh /var/lib/mysql/db/t.ibd确认文件变小;再查SHOW TABLE STATUS LIKE 't'\G,确认Data_free接近 0
最后提醒一句:InnoDB 的空间回收从来不是“删完就完”,它是和 purge 线程、buffer pool 命中率、甚至 binlog format 都挂钩的链式反应——盯着单个指标容易误判。











