MySQL 5.7 大表删除部分数据:.ibd 文件会变小吗?磁盘会释放吗?

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

现在需要通过delete from weblog where url like '%/show'删除 url 以/show结尾的记录,执行完成后weblog.ibd会变小吗?服务器磁盘空间会被释放吗?这篇文章就来详细拆解这个问题,同时给出对应的解决方案。

一、核心结论先行

  1. weblog.ibd文件大小不会变小 :执行DELETE语句删除部分数据后,ibd文件的物理大小不会有任何缩减,依然会保持 62G 左右。
  2. 磁盘空间不会被释放给操作系统 :被删除的数据占用的磁盘空间,不会返还给服务器的文件系统(无法通过df -h看到磁盘可用空间增加)。
  3. 空间会被 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 表,会执行以下操作:

  1. 创建一张与原表weblog结构完全一致的临时表;
  2. 将原表中未被删除的有效数据,逐条复制到临时表中;
  3. 删除原表的ibd文件,将临时表重命名为weblog
  4. 重建原表的所有索引,生成新的ibd文件(大小仅为有效数据的占用空间)。

通过这个过程,原有的空闲空间被彻底清理,ibd文件会缩小,释放的磁盘空间会返还给操作系统。

3. 注意事项(重点)
  • 锁表风险 :执行期间,weblog表会被施加写锁(阻塞所有 INSERT、UPDATE、DELETE 操作),如果表很大(62G),执行时间会很长(几小时甚至更久),会严重影响线上业务;
  • 磁盘空间要求:执行过程中需要额外的磁盘空间,用于存储临时表和索引,至少需要预留与原表有效数据相当的磁盘空间(避免磁盘满);
  • 性能消耗:重建表和索引会消耗大量的 CPU、IO 资源,可能会影响数据库其他业务的正常运行,建议在业务低峰期(如凌晨)执行。

四、总结与最佳实践建议

  1. DELETE 操作的本质 :仅做逻辑删除,标记空闲空间供内部复用,不缩小ibd文件,不释放磁盘给操作系统;
  2. 空间释放的核心思路 :必须通过 "重建表" 的方式,清理空闲空间,生成新的ibd文件;
  3. 线上业务选型建议
    • 非核心业务、可接受锁表:选择OPTIMIZE TABLE,操作简单;
  4. 预防大于治理 :对于weblog这类日志表,建议提前规划分表策略(如按天 / 按月分表),避免单表过大,后续清理数据时只需删除整个分表,效率更高,且无需担心锁表和磁盘空间问题。
相关推荐
IT 行者1 天前
告别硬编码!Spring Boot 优雅实现 Controller 路径前缀统一管理
数据库·spring boot·python
D_FW1 天前
数据结构第三章:栈、队列与数组
数据结构·算法
小张程序人生1 天前
一篇文章快速入门ShardingJDBC
mysql
福楠1 天前
模拟实现stack、queue、priority_queue
c语言·开发语言·数据结构·c++
曹牧1 天前
Oracle 大表数据分区存储
数据库·oracle
win x1 天前
Redis 持久化
数据库·redis·缓存
budingxiaomoli1 天前
优选算法--链表
数据结构·算法·链表
漫随流水1 天前
leetcode算法(637.二叉树的层平均值)
数据结构·算法·leetcode·二叉树
程序猿20231 天前
MySQL的锁(行锁)
数据库·mysql