开放问答
MySQL 8.0 大表 .ibd 膨胀到 500GB,OPTIMIZE TABLE 跑不动,有没有可落地的收缩方案
该问题的正文、回答与评论。
提问者 陈景行-242 · 状态 open
MySQLInnoDBibd膨胀OPTIMIZE TABLE空间回收
背景
生产环境 MySQL 8.0.36,InnoDB,一张订单流水表 t_order_flow 约 3.2 亿行,.ibd 文件 528GB,SHOW TABLE STATUS 显示 Data_length 约 78GB——也就是约 450GB 是历史 DELETE 后未回收的空间。业务方按月归档,每月 DELETE 一批,累计约 18 个月,DELETE 后从不做任何收缩动作。
现象
- 磁盘水位告警,剩余空间不到 200GB,再撑 2 个月就要爆;
- 业务侧硬约束:不能锁表、不能长时间停写、不能影响在线查询 P99(当前 P99 < 120ms);
- 这台实例上没有足够的空闲磁盘再放一份 500GB 的临时表。
已尝试(都失败/被叫停)
ALTER TABLE t_order_flow ALGORITHM=COPY, LOCK=NONE:跑了 40 分钟被叫停——临时表要再占 500GB+,磁盘水位直接顶到 92%;OPTIMIZE TABLE t_order_flow:本质就是 COPY 算法,同上;pt-online-schema-change --alter "ENGINE=InnoDB":跑了 2 小时,临时表空间还在涨,按当前速率估计 8 小时以上,业务侧不接受这个窗口;- 改按月
PARTITION BY RANGE:需要重建表,同样面临 COPY 空间峰值问题; DROP INDEX大索引再ADD INDEX想借机回收:实测对.ibd大小几乎无影响(回收的只是索引页,数据页不动)。
期望得到的答案形态(任选其一即可,最好带真实案例)
- 一个不额外占 500GB 空间的在线收缩方案,给出可复现步骤(命令、参数、顺序);
- 或:MySQL 8.0 下有没有「在线、低资源」的方式把
.ibd收缩回Data_length附近(比如innodb_file_purge调优、undo log 清理节奏等),请讲清楚原理与限制; - 或:如果只能走重建,如何用最小代价(时间窗口、磁盘峰值、对在线 P99 的影响)完成——包括 pt-osc 的 chunk size、
--max-lag、限速参数、临时表空间如何规划,请给一组你线上跑过的参数; - 或:这类「长期 DELETE 不收缩」的表,设计上有没有更合理的替代方案——分区 +
DROP PARTITION、冷热分离到对象存储(如 S3/OSS + 元数据表)、按租户/时间分库等,请给一个选型对比(维度:实现成本、查询改造、空间回收效率、运维复杂度)。
欢迎贴你线上跑过的真实案例,最好带参数与耗时;纯理论推演也欢迎,但请标注「未在生产验证」。
评论
暂无评论。