UndoLog页被锁定本身不直接导致CheckPoint延迟,根因是长事务阻塞purge线程导致undo记录无法清理。通过Historylistlength超万且增长、PURGEPROCESSED停滞、事务ID与清理ID差距扩大可判断。定位需查最老活跃事务及其undo段与purge线程状态。
先给结论:Undo Log页被锁定本身并不直接导致CheckPoint延迟,真正卡住进程的,是长事务阻塞了purge线程,导致undo记录无法清理,进而拖慢CheckPoint推进。怎么判断?看这三个指标的联动:History list length超过10000还在涨、PURGE PROCESSED数值不动、Trx id counter和Purged up to的差距越拉越大——这就是典型的purge卡死症状。

长期稳定更新的攒劲资源: >>>点此立即查看<<<
CheckPoint延迟的根因,不是“Undo页被锁”这个动作本身,而是InnoDB推进CheckPoint时,需要刷脏页、回收undo log空间。如果undo页被一个还在跑的长事务死死拽着,purge线程就没法清理旧undo记录,CheckPoint自然卡在那里了——说白了,是undo log purge堵车,不是锁车。
盯住SHOW ENGINE INNODB STATUS里PURGE部分的几个关键数字:
History list length要是超过10000,尤其还在持续增长——说明undo log堆积得像没清理的垃圾站,purge完全跟不上。PURGE PROCESSED长时间不更新,或者增速慢得像蜗牛——purge线程基本处在“我不干了”的状态。Trx id counter和Purged up to的差值越来越大——事务ID嗖嗖地往上跳,但purge就是追不上,undo空间根本没法复用。这时候就算你把innodb_max_purge_lag设成0也没用,因为buffer pool里一堆“逻辑上可以刷、物理上不能丢”的undo相关脏页,CheckPoint只能干等着。
不是所有事务都来掺和——真正搞得purge动弹不得的,是那些让undo record没法安全回收的场景:
TRX_STATE = RUNNING,而且TRX_STARTED时间远早于现在)innodb_lock_wait_timeout设得特别低,但应用层不回滚也不提交,结果事务就那么悬着SELECT ... FOR UPDATE或UPDATE后,忘了COMMIT或ROLLBACK,一直占着坑READ COMMITTED但没关autocommit,执行完DML就跑了——事务没提交,purge也没法动顺带提醒一句:MySQL 8.0+默认开启innodb_undo_log_truncate = ON,但truncate触发条件是history list length足够小。如果purge卡死,truncate永远等不到那一天。
别只盯着INNODB_TRX看,要联动查三张表:
SELECT * FROM information_schema.INNODB_TRX ORDER BY TRX_STARTED ASC LIMIT 1;SELECT * FROM information_schema.INNODB_UNDO_LOGS WHERE TRX_ID = ;(需要从TRX_ID反查)SELECT * FROM performance_schema.threads WHERE NAME LIKE '%purge%';,看看PROCESSLIST_STATE是sleeping还是waiting for undo log如果发现某个事务的TRX_MYSQL_THREAD_ID对应的应用连接已经断了,但事务状态还是RUNNING——恭喜,你遇到了线上最常见的purge阻塞根源:客户端异常退出,事务没清理。
不过,查到问题只是第一步,真正棘手的是“查到后不敢KILL”。强行KILL一个正在写大量undo的事务,会触发同步回滚,搞不好比让它自然跑完还慢。最稳妥的办法是先联系业务确认那个事务能否中断,再决定是KILL掉还是等它自己结束。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述