负责的一个系统中,有张表占用了约 260GB。因为业务合规要求,表中的数据已经删除了一半左右,但磁盘占用没有随之明显下降。当时磁盘剩余空间约为 20%,我们准备利用一次系统升级窗口整理这张表。
整个过程约花了 2 小时 40 分钟,将表的大小缩减到约 130GB。期间业务提前恢复,磁盘占用也一度升到 93%。相比最后释放了多少空间,这些过程中的变化更值得说明。
为什么删除数据后,文件没有明显变小
对于 InnoDB,删除记录后,部分空间可以留在表空间内部供后续写入使用,但这不等于文件系统立即获得同样大小的可用空间。能否通过重建把空间归还给操作系统,还与表空间类型等条件有关。
当时考虑过 OPTIMIZE TABLE、重建表,以及创建新表后复制数据几种办法。它们不能仅按命令长短比较:需要考虑结构是否完整保留、额外空间、锁等待、执行时间和业务读写。
例如,CREATE TABLE new_table SELECT * FROM old_table 不会自动复制原表的索引,不能将它视为完整克隆表结构的方法。对于 InnoDB,OPTIMIZE TABLE 会映射到重建表的操作。MySQL 8.0 对普通 InnoDB 表支持在线 DDL,但准备和提交阶段仍需要短暂的排他锁,含全文索引等情况还可能改用表复制。具体的锁行为和限制需要按实际数据库版本、表结构及配置确认。
当时的操作经过
当时选择的方案是将旧表改名并整理,同时创建同名新表承接可能恢复的业务。操作时间线如下:
| 时间 | 发生的事情 |
|---|---|
| 18:00 | 计划停止服务 |
| 18:20 | 实际停止服务 |
| 18:30 | 将旧表改名,创建同名新表,随后进行整理 |
| 18:50 | 业务提前恢复,有新请求进入 |
| 21:00 | 磁盘使用率由整理前约 80% 升至 93% |
| 21:10 | 整理完成,磁盘使用率降至约 63% |
| 21:15 | 回并新表数据,并恢复原表名 |
最初的切表逻辑是:
-- 切表逻辑示意,省略具体建表字段和索引。
ALTER TABLE t_invoke RENAME t_invoke_bak;
CREATE TABLE t_invoke ...;
改名后,整理针对的是 t_invoke_bak,业务则使用新建的 t_invoke。这个分工可以承接提前恢复的请求,但也让后续的数据回并成为整个流程的关键。
旧表由约 260GB 缩减到约 130GB,整理阶段约耗时 2 小时 40 分钟。重建过程可能需要额外文件和日志空间,因此不能只盯着最终释放的容量,也要估算过程中的峰值占用,不能用“最终会省下一半空间”来判断当前剩余空间是否足够。
恢复表名之前,先解决数据一致性
当时恢复表名的逻辑是:
-- 当时的操作顺序;回并到切换期间必须停止相关写入。
INSERT INTO t_invoke_bak SELECT * FROM t_invoke;
DROP TABLE t_invoke;
ALTER TABLE t_invoke_bak RENAME t_invoke;
这段操作最容易忽略的是回并和切换之间的数据变化。
首先,复制完成后到删除新表之前,如果仍有业务写入,新数据就可能被删除。即使这段时间很短,也不能靠“找个业务空挡”保证一致性;需要明确停止相关写入、等待在途事务结束,并确认没有后台任务继续操作。
其次,直接插入是否成立,要看数据变化方式。如果新表重置了自增起点,主键可能与旧表冲突;如果业务会修改或删除旧记录,仅复制新表里的记录也不能表达所有变化。所以,使用这种做法前必须确认业务是否只有新增、主键是否冲突,以及是否需要处理更新和删除,不能只复制一次数据就认定回并完成。
最后,先删除再改名会留下业务表名不存在的窗口,也立即丢掉了一份可用于核对的数据。MySQL 支持单条 RENAME TABLE 交换多个表名,在满足相关条件时原子完成,但这只能处理表名切换,不能代替停写、增量回并和校验。外键、触发器以及应用对表的依赖也需要单独确认。
将空间回收组织成完整的维护流程
- 记录数据库版本、表空间类型、表结构、索引和相关业务读写方式,先在测试环境验证选定方案。
- 准备可恢复的备份,确认数据文件、临时目录和日志所在磁盘的空间;依据实际重建方式估算峰值占用,不套用固定空闲百分比。
- 确认是否确有必要临时切表。若需要,事先定义新旧数据的主键分配、更新删除处理和回并规则。
- 在回并与最终切换前停止相关写入,排空在途操作;明确列名进行数据处理,并检查记录数、关键字段和业务结果,而不只看 SQL 是否执行成功。
- 切换后验证应用读写和后台任务。保留用于核对与回退的数据,待确认完成后再清理;切换后如果已经产生新写入,回退同样需要处理这些变化。
这次经历最有价值的教训,是维护窗口可能变化,而数据一致性必须有明确机制保证。释放磁盘空间只是结果之一,能解释数据如何完整保留、失败如何恢复,才算把维护流程交代完整。