5000 万订单表清理 3000 万历史数据(不影响线上)落地方案
目录
一、前置准备 & 风险评估(必做)
1. 数据与表结构摸底
2. 备份(底线)
3. 环境隔离与权限
二、核心方案:分批限流删除(主流最优方案,零业务影响)
方案思路
1. 关键参数设计(通用参考)
2. 具体 SQL 逻辑(基于自增主键 id + 时间)
(1)基础分页删除(推荐,最稳定)
(2)纯时间分页(无自增主键,用订单号 / 索引)
3. 执行载体(三种选择,按架构选)
方式 1:Shell 脚本 + MySQL 客户端(运维常用,简单无侵入)
方式 2:Java/Python 后台程序(业务侧可控,可加熔断)
方式 3:数据库定时事件(不推荐)
三、进阶优化(高并发 / 大集群必备)
1. 主从架构专项处理
2. 大表优化:先归档再删除(超千万级终极方案)
3. 禁止行为(红线)
四、分阶段执行节奏(3000 万条参考耗时)
五、监控 & 应急兜底
1. 实时监控指标
2. 应急方案
六、删除后收尾工作
七、长期方案(避免再次出现大表)
总结最简落地版(快速复述)
核心原则:禁止直接DELETE大批量数据、避开业务高峰、分批删除、限流、锁最小化、兜底回滚、全程监控,适配 MySQL 常规架构,分前置评估→分批删除执行→收尾优化三阶段。
一、前置准备 & 风险评估(必做)
1. 数据与表结构摸底
- 确认时间字段:依赖
create_time/order_time作为删除条件,确保该字段建有单列索引(无索引会全表扫,严重堵库)。 - 表信息:引擎默认 InnoDB、是否有主键(必须有自增 ID / 订单号主键,分批依据主键)、有无外键、触发器、关联业务视图 / 定时任务。
- 业务口径:确认「1 年前数据」时间边界,核对 3000 万条数据量级,避免误删有效数据。
- 流量评估:区分业务低峰期(凌晨 00:00–06:00 优先执行),记录日常 QPS、CPU、磁盘 IO 阈值。
2. 备份(底线)
- 方式 1(优先):物理备份(xtrabackup)整表 / 整库备份,速度快、不锁业务。
- 方式 2:逻辑备份历史数据(单独导出 1 年前数据),备份后再删除,满足合规溯源。
- 禁止:删除完成后再备份。
3. 环境隔离与权限
- 线上主库禁止手动直连大批量操作,通过后台脚本 / 定时任务执行;
- 读写分离架构:优先在从库做数据校验、预演,再到主库执行。
二、核心方案:分批限流删除(主流最优方案,零业务影响)
方案思路
利用主键 + 时间范围分页小批量删除,每次只删少量行,控制事务大小、行锁范围、IO 压力,循环执行,全程不阻塞线上读写。
为什么不用
DELETE FROM 表 WHERE 时间<xxx? 大批量 DELETE 会:长事务、大量 undo 日志、行锁范围大、主从延迟飙升、IO 打满、线上查询超时。
1. 关键参数设计(通用参考)
- 单批次删除行数:每次 100~500 行(根据数据库性能微调,高配库最大不超 1000);
- 批次间隔:50~200ms(限流,削峰 IO、主从延迟);
- 执行窗口:仅凌晨低峰运行,白天停止,规避业务流量。
2. 具体 SQL 逻辑(基于自增主键 id + 时间)
(1)基础分页删除(推荐,最稳定)
-- 循环执行,直到无满足条件数据 DELETE FROM order_table WHERE create_time < '2025-06-07 00:00:00' AND id > ? LIMIT 500; -- 单批行数执行逻辑:
- 记录上一轮最大
id,避免重复扫描全表; - 每次只删 500 条,短事务、锁范围极小;
- 每执行一轮,
sleep 100ms限流。
(2)纯时间分页(无自增主键,用订单号 / 索引)
DELETE FROM order_table WHERE create_time < '2025-06-07 00:00:00' ORDER BY create_time ASC LIMIT 500;3. 执行载体(三种选择,按架构选)
方式 1:Shell 脚本 + MySQL 客户端(运维常用,简单无侵入)
配合while循环 + 休眠,低峰定时执行,示例逻辑:
# 伪逻辑:循环删除,每次500条,间隔100ms while true; do affected=$(mysql -e "DELETE FROM order_table WHERE create_time < '2025-06-07' LIMIT 500;" | wc -l) if [ $affected -eq 0 ]; then break; fi sleep 0.1 # 限流 done方式 2:Java/Python 后台程序(业务侧可控,可加熔断)
- 增加开关、暂停 / 终止接口,突发业务上涨可立刻停删;
- 监控数据库指标,CPU/IO/ 主从延迟超标自动休眠;
- 记录执行日志、已删除条数,便于对账。
方式 3:数据库定时事件(不推荐)
仅纯运维库使用,线上业务库禁用,异常难以紧急终止。
三、进阶优化(高并发 / 大集群必备)
1. 主从架构专项处理
- 主库分批删除,从库会同步 binlog,必然产生主从延迟;
- 监控从库延迟:延迟 > 3s 自动加大
sleep间隔,或临时暂停; - 严禁在延迟过高时继续执行。
2. 大表优化:先归档再删除(超千万级终极方案)
如果该订单表日常查询极频繁,单纯分批删除仍有 IO 压力,采用归档分离:
- 新建归档表
order_history_archive,结构和原表一致; - 分批迁移历史数据(
INSERT ... SELECT + LIMIT)到归档表; - 迁移完成后,再分批删除原表数据;
- 归档表可冷备份、下线、迁移至低成本存储(OSS / 冷数据库)。
优势:原表频繁访问的热数据完全不受影响,IO 压力拆分。
3. 禁止行为(红线)
- 不执行
DELETE 不带 LIMIT全量删除; - 不执行
TRUNCATE(清空全表,锁表、丢数据、无法回滚); - 不在业务高峰、大促、报表时段执行;
- 不关闭 binlog(主从集群会数据不一致);
- 不一次性加大批次量(>1000 行风险陡增)。
四、分阶段执行节奏(3000 万条参考耗时)
以每批 500 行、间隔 100ms计算:
- 总批次:60000 轮
- 纯执行 + 休眠耗时:约 1.67 小时
结合人为停顿、指标监控,分 2~3 个凌晨窗口跑完,不单日一次性跑完,留缓冲。
- 第一晚:试运行(删 100 万条),观察 CPU、IO、主从延迟、线上接口响应;
- 第二晚:批量执行大部分数据;
- 第三晚:收尾清理剩余数据。
五、监控 & 应急兜底
1. 实时监控指标
数据库:CPU、内存、磁盘 IO、连接数、慢查询、主从延迟; 业务:接口响应时间、报错率、QPS。
2. 应急方案
- 线上业务异常:立刻停止删除脚本 / 程序,无需回滚,分批删除可断点续跑;
- 误删数据:依赖前置备份恢复;
- 出现死锁 / 锁等待:调小单批行数、加大休眠间隔。
六、删除后收尾工作
- 表空间回收:InnoDB 大批量删除后会产生碎片,数据文件不自动缩小。
- 低峰执行:
ALTER TABLE order_table FORCE;或 轻量重建表(根据碎片率选择); - 碎片率高建议:分批做完删除后,择机做表重建优化查询性能。
- 低峰执行:
- 统计核对:比对删除前后数据量,确认 3000 万历史数据清理完成;
- 归档数据处置:归档表定期冷备,按需下线。
七、长期方案(避免再次出现大表)
- 表分区:按时间分区(月 / 年分区),后续清理历史数据直接
DROP PARTITION,毫秒级完成,无 IO 压力; - 冷热数据分离:热订单存主库,N 个月前数据自动归档至历史库;
- 定时清理:配置月度小批量清理任务,避免数据堆积到千万级。
总结最简落地版(快速复述)
- 先全量备份,核对时间条件与索引;
- 凌晨低峰执行,主键 + LIMIT 小批量删除(500 行 / 批),批次间休眠限流;
- 全程监控数据库与业务指标,异常立即暂停;
- 清理完成后整理表碎片;
- 长期改用时间分区表根治大表清理问题。
