开放问答
3 亿行表按 create_time 批量删除,批大小 5000 还是 5 万?锁与 purge 的取舍怎么定量
该问题的正文、回答与评论。
提问者 陈知远-212 · 状态 open
MySQLInnoDB批量删除pt-archiverpurge锁等待
【背景】MySQL 8.0.32 / InnoDB,单库 32C/128G,innodb_buffer_pool_size=64G。日志明细表 log_event 约 3 亿行,PK=id(自增),索引 idx_ct (create_time) 单列。业务要求每天 02:00 清理 30 天前数据,估算单次需删除 2000 万~4000 万行,窗口 2 小时。
【现象】目前用 pt-archiver 按 PK 切批,每批 5000 行,批间 sleep 20ms。跑完一轮约 1h50m,但期间:
- 二级索引 idx_ct 的叶子页持续有 X-lock 排队,业务读 P99 从 8ms 涨到 45ms(监控可见行锁等待曲线);
- history list length 从 200 爬到 8 万后回落,purge 线程 CPU 占 15%;
- binlog 单文件峰值 400MB,从库延迟峰值 12s(可接受)。
【已尝试】
- 批大小调到 2 万行:锁等待缓解(批次数少了),但单事务内 undo 量变大,history list 峰值到 25 万,purge 跟不上,P99 反弹到 80ms;
- 改用二级索引 idx_ct 走 range 删除而不是 PK 切批:EXPLAIN 显示走 idx_ct 但每行还要回表拿 PK,单批耗时反而 +60%;
- 开启 innodb_purge_threads=8:history list 峰值降了,但没有根治。
【想问】
- 在"锁等待时长 × 批次数"和"单批 undo 量 × purge 压力"之间,有没有一套可定量的选型公式或经验阈值?我现在的直觉是批大小应该在 1 万~3 万之间,但没有依据;
- 对于"必须按 create_time 删"的场景,是先按 idx_ct 扫出 PK 列表再按 PK 分批删(两次 IO),还是直接 range 删(一次 IO 但回表)更划算?各自的临界条件是什么;
- 有没有比 pt-archiver 更适合这种"大窗口、大批量、低侵入"场景的工具或写法?
期望回答能给出:可复现的压测方法(怎么在测试库模拟 3 亿行 + 并发读)、批大小的定量选择依据、以及你团队实际跑下来的参数组合。
评论
暂无评论。