Undo Log页被锁定本身不直接导致CheckPoint延迟,而是长事务阻塞purge线程,使undo记录无法清理,进而拖慢CheckPoint推进;确认依据是History list length > 10000且持续增长、PURGE PROCESSED停滞、Trx id counter与Purged up to差值扩大。
CheckPoint延迟本身不是直接由“Undo Log页被锁定”引起,而是因为InnoDB在推进CheckPoint时需刷脏页、回收undo log空间,而undo页若正被活跃事务(尤其是长事务)长期持有,会导致purge线程无法清理旧undo记录,进而阻塞CheckPoint推进——本质是undo log purge卡住,而非undo页“被锁”这一动作本身造成延迟。
关键看innodb_purge_lag和innodb_purge_lag_history是否持续偏高,再结合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,CheckPoint也会因buffer pool中大量“逻辑上可刷但物理上不能丢”的undo相关脏页而变慢。
不是所有事务都影响purge,真正卡住的是那些让undo record无法被安全回收的事务:
TRX_STATE = RUNNING且TRX_STARTED时间远早于当前)innodb_lock_wait_timeout但应用层未正确处理回滚,导致事务悬停SELECT ... FOR UPDATE或UPDATE后长时间不COMMIT或ROLLBACK
READ COMMITTED但未关闭autocommit,执行DML后忘记提交注意:innodb_undo_log_truncate = ON在MySQL 8.0+默认启用,但仅当history list length足够小时才触发truncate;若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或等待其自然结束。