首页/数据/数据库速查/MVCC 与 purge 滞后(history list length)
性能与调优57 条

MVCC 与 purge 滞后(history list length)

MVCC 靠 undo 保留旧版本:长事务不结束则旧版本无法回收(purge 滞后),undo 表空间膨胀、查询变慢;看 History list length 与 undo 占用预警。

数据库速查数据更新于 2026-10-13

MVCC 与 purge 滞后是什么

InnoDB 用多版本并发控制:修改数据时把旧版本写进 undo,让读事务能看到自己快照时刻的数据。代价是旧版本必须等到没有事务再需要它们才能清理,这个动作叫 purge。一旦有长事务或长时间未提交的只读事务挂着,purge 就追不上,history list 持续增长、undo 表空间膨胀、磁盘告警接连出现,查询也会因为要遍历更长的版本链而变慢。

基本信息

适用版本MySQL 5.7 / 8.0(8.0 的 undo 表空间默认独立文件)
核心指标History list length(SHOW ENGINE INNODB STATUS 的 TRANSACTIONS 段)
相关视图information_schema.INNODB_TRX、INNODB_TABLESPACES
常见诱因长事务、长时间未提交的只读事务、大批量单事务加载
症状undo 表空间增长、磁盘告警、查询逐渐变慢
治理方向找出并结束老事务,把大事务拆成小批次提交

典型使用场景

  • 磁盘突然告警排查:确认增长来自 undo 表空间而非业务数据
  • 查询莫名变慢:版本链变长导致回滚段读取成本上升
  • 定时任务排查:批处理单事务跑几十分钟,把 purge 拖住
  • 报表与导出场景:长只读事务同样阻止旧版本回收
  • 监控建设:把 history list 长度纳入日常指标而不是等磁盘报警

观测命令

观测命令
-- 历史版本链表长度:持续增长即为 purge 滞后
SHOW ENGINE INNODB STATUS\G          # TRANSACTIONS 段的 History list length

-- 未提交事务清单,按开始时间排序找出最老的
SELECT trx_id, trx_state, trx_started, trx_rows_locked, LEFT(trx_query, 60)
FROM information_schema.INNODB_TRX ORDER BY trx_started;

-- undo 表空间占用
SELECT NAME, FILE_SIZE FROM information_schema.INNODB_TABLESPACES
WHERE NAME LIKE 'innodb_undo%';

-- 是否有长事务对应的连接
SELECT id, user, host, time, state, LEFT(info, 60) FROM information_schema.PROCESSLIST
WHERE time > 300 ORDER BY time DESC;

治理动作

治理动作
-- 1) 先定位最老事务对应的会话,再评估影响面
SELECT trx_mysql_thread_id, trx_started FROM information_schema.INNODB_TRX ORDER BY trx_started LIMIT 5;

-- 2) 确认是失控事务后再终止(大事务回滚本身会消耗 IO)
KILL 12345;

-- 3) 批处理改为小批次提交,控制单事务耗时
-- DELETE FROM big_table WHERE created_at < '2025-01-01' LIMIT 2000;  -- 循环执行

-- 4) 只读长任务放到从库或使用可关闭快照的方式执行

指标对照

指标正常范围异常含义
History list length数百以内(视写入量)持续增长说明有事务阻止清理
INNODB_TRX 最老事务时长秒级到分钟级小时级说明有长事务悬挂
undo 表空间占用稳定或小幅波动持续上涨伴随磁盘告警
trx_rows_locked与业务行数匹配异常大表示锁范围过宽或条件未走索引
只读事务同样拖住 purge:REPEATABLE READ 下开始一个只读事务后不提交,快照会一直有效,旧版本无法回收;报表、导出类任务应放到从库执行,或使用能在每次查询后释放快照的方式。
发现 undo 膨胀就扩容磁盘只是续命:根源是长事务不除,purge 依旧追不上,最终会同时遇到磁盘写满与查询性能下降两个问题;应当先降低单事务时长,再评估 undo 表空间回收方式。

易错点

  • 只看磁盘占用不看 history list 趋势:发现时 undo 已增长到几十 GB,回收窗口被压缩
  • 把 purge 滞后当磁盘问题扩容:根源长事务未除,问题必然复发
  • 批处理用单事务处理百万行:undo 暴涨、锁范围大、回滚代价高,应分批提交
  • 应用侧开启事务后忘提交(连接池里的悬挂事务):purge 长期停滞,排查定位困难
  • 直接对生产库执行大规模回滚段收缩操作:需充分评估版本与维护窗口,风险高

数据来源与参考

  • MySQL 8.0 Reference Manual: InnoDB Multi-Versioning
  • MySQL 8.0 Reference Manual: InnoDB Purge

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌