Purge线程积压的根本原因是innodb_purge_threads过少,无法及时清理高频UPDATE/DELETE或长事务产生的大量undo log;应设为2~4并同步调大innodb_purge_batch_size至1000~2000,且必须配合关闭长事务、启用innodb_undo_log_truncate及合理配置innodb_max_undo_log_size。

为什么Purge线程会积压?
根本原因是 innodb_purge_threads 太少,而事务提交后产生的 undo log 量远超单个 purge 线程的清理能力。尤其在批量更新、高频小事务(如每秒数千次 UPDATE)、或长期运行的只读事务(阻塞 purge)场景下,purge_queue 长度持续增长,INFORMATION_SCHEMA.INNODB_METRICS 中 innodb_purge_trx_removal_rate 明显低于 innodb_purge_undo_removal_rate,就说明 purge 跟不上。
如何调高 purge 并发度?
MySQL 5.6+ 支持多 purge 线程,但默认仅启用 1 个。必须显式配置:
-
SET GLOBAL innodb_purge_threads = 4;(推荐值:2–4,不建议超过 CPU 核心数) - 同时确认
innodb_purge_batch_size不过小(默认 300,高负载下可设为1000~2000) - 必须写入配置文件生效:
innodb_purge_threads = 3(重启后持久化,仅SET GLOBAL在重启后失效)
注意:innodb_purge_threads 是总 purge 工作线程数,包含协调线程(1 个)+ 工作线程(n-1 个),实际并发清理由后者承担。
哪些操作会让 purge 更难跟上?
不是所有更新都平等。以下行为会显著加重 purge 压力:
- 频繁修改带二级索引的字段(每行变更触发多条 undo 记录)
- 使用
READ COMMITTED或更低隔离级别 + 大量短事务(undo 日志无法被早期 purge) - 存在长事务(哪怕只是
BEGIN后未提交),其trx_id会卡住 purge 的历史版本清理边界 -
innodb_max_purge_lag设得过高(或为 0),失去反压机制,导致 undo 表空间暴涨
查活跃长事务用:SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TIME_TO_SEC(NOW() - trx_started) > 60;
要不要调大 undo 表空间?
增大 innodb_undo_tablespaces 数量(如从默认 0 改为 2~4)能提升 purge I/O 并发性,但前提是启用了独立 undo 表空间(innodb_undo_log_truncate = ON 且 innodb_undo_tablespaces > 0)。否则只是徒增文件数量,无实质帮助。
关键点:
- 先确保
innodb_undo_log_truncate = ON(MySQL 5.7.2+ 默认开启) -
innodb_undo_tablespaces必须是偶数,且 ≥2 才有效果 - 调整后需重启,且不可动态修改
- 配合
innodb_undo_log_truncate的周期(由innodb_max_undo_log_size触发),避免 undo 表空间无限膨胀
真正影响 purge 效率的,从来不是 undo 空间大小,而是 purge 线程能否及时把旧版本标记为可回收 —— 这依赖于并发度、事务活性和隔离级别协同控制。


















