在 MySQL 运维场景中,我们经常会遇到大表数据清理的需求。有同学咨询:某 MySQL 5.7 环境下有一张 62G 的大表weblog,其对应的ibd数据文件大小为 62G,

现在需要通过delete from weblog where url like '%/show'删除 url 以/show结尾的记录,执行完成后weblog.ibd会变小吗?服务器磁盘空间会被释放吗?这篇文章就来详细拆解这个问题,同时给出对应的解决方案。
一、核心结论先行
weblog.ibd文件大小不会变小 :执行DELETE语句删除部分数据后,ibd文件的物理大小不会有任何缩减,依然会保持 62G 左右。- 磁盘空间不会被释放给操作系统 :被删除的数据占用的磁盘空间,不会返还给服务器的文件系统(无法通过
df -h看到磁盘可用空间增加)。 - 空间会被 MySQL 标记为 "空闲空间" 内部复用 :这些被释放的空间会被 InnoDB 引擎标记为空闲(free space),后续当这张
weblog表有新数据插入、更新时,InnoDB 会优先复用这部分空闲空间,而不会立即申请新的磁盘空间。
二、为什么 DELETE 操作无法缩小.ibd 文件、释放磁盘?
要理解这个问题,首先要搞清楚 InnoDB 引擎对数据存储和DELETE操作的处理机制,核心原因有两点:

1. InnoDB 的 "空间复用" 机制(不主动回收物理文件)
InnoDB 的ibd文件(存储表的数据和索引)一旦创建并扩展后,就不会主动收缩物理文件大小 。这是 InnoDB 的设计特性:当执行DELETE语句删除记录时,它并不会将这些记录对应的磁盘块从ibd文件中移除,也不会对ibd文件进行 "截断" 操作,只是在数据字典中标记这些磁盘块为 "空闲可用"。
简单来说,ibd文件就像一个已经被撑大的纸箱,DELETE操作只是把纸箱里的部分物品拿走,但纸箱本身的大小不会变小,空出来的位置可以用来放新的物品(新数据),但纸箱不会自动收缩成更小的尺寸。

2. DELETE 操作的 "行级删除" 特性(不释放物理磁盘块)
DELETE语句在 InnoDB 中是行级删除操作,它只针对满足条件的行进行逻辑删除:
- 对于非聚簇索引:标记索引记录为删除状态,不会立即清理索引页;
- 对于聚簇索引(InnoDB 默认主键为聚簇索引):标记数据行为删除状态,释放的行空间同样标记为空闲,供后续同表的数据插入复用。
整个过程中,ibd文件对应的物理磁盘块没有被释放,文件系统层面依然认为这部分空间被ibd文件占用,因此磁盘可用空间不会增加。
补充说明:如果是**DROP TABLE(删除整张表)或TRUNCATE TABLE(清空整张表** ),则会直接删除ibd文件或重建空的ibd文件,此时磁盘空间会被释放,但这两种操作不适用于 "删除部分数据" 的场景。
三、如何真正缩小.ibd 文件、释放磁盘空间?
如果删除部分数据后,需要将空闲空间释放给操作系统,同时缩小ibd文件大小,针对 MySQL 5.7 的weblog表,有以下两种可行方案,各有优劣,可根据业务场景选择。
方案一:OPTIMIZE TABLE 命令(简单直接,有锁表风险)
1. 命令用法
针对weblog表,执行以下命令即可:
-- 针对InnoDB表,OPTIMIZE TABLE 本质是 ALTER TABLE ... FORCE,会重建表
OPTIMIZE TABLE weblog;
2. 工作原理
OPTIMIZE TABLE对于 InnoDB 表,会执行以下操作:
- 创建一张与原表
weblog结构完全一致的临时表; - 将原表中未被删除的有效数据,逐条复制到临时表中;
- 删除原表的
ibd文件,将临时表重命名为weblog; - 重建原表的所有索引,生成新的
ibd文件(大小仅为有效数据的占用空间)。
通过这个过程,原有的空闲空间被彻底清理,ibd文件会缩小,释放的磁盘空间会返还给操作系统。
3. 注意事项(重点)
- 锁表风险 :执行期间,
weblog表会被施加写锁(阻塞所有 INSERT、UPDATE、DELETE 操作),如果表很大(62G),执行时间会很长(几小时甚至更久),会严重影响线上业务; - 磁盘空间要求:执行过程中需要额外的磁盘空间,用于存储临时表和索引,至少需要预留与原表有效数据相当的磁盘空间(避免磁盘满);
- 性能消耗:重建表和索引会消耗大量的 CPU、IO 资源,可能会影响数据库其他业务的正常运行,建议在业务低峰期(如凌晨)执行。
四、总结与最佳实践建议
- DELETE 操作的本质 :仅做逻辑删除,标记空闲空间供内部复用,不缩小
ibd文件,不释放磁盘给操作系统; - 空间释放的核心思路 :必须通过 "重建表" 的方式,清理空闲空间,生成新的
ibd文件; - 线上业务选型建议 :
- 非核心业务、可接受锁表:选择
OPTIMIZE TABLE,操作简单;
- 非核心业务、可接受锁表:选择
- 预防大于治理 :对于
weblog这类日志表,建议提前规划分表策略(如按天 / 按月分表),避免单表过大,后续清理数据时只需删除整个分表,效率更高,且无需担心锁表和磁盘空间问题。