必须先杀掉trx_state = 'running'且trx_query is null的空闲事务,否则任何参数调整、自动截断或purge加速都无效;需用innodb_trx按trx_started排序定位最老事务,关联processlist确认异常连接,再按状态分步kill,最后手动加大purge_batch_size并等待history list length回落。

必须先杀掉 trx_state = 'RUNNING' 且 trx_query IS NULL 的空闲事务,否则任何参数调整、自动截断或 purge 加速都无效——Undo Log 爆满不是空间问题,是事务生命周期失控的直接结果。
怎么快速定位真正卡住 purge 的长事务
别信 SHOW PROCESSLIST 的 Time 字段,它只反映当前语句执行时长。真正钉死 Undo 的,是那些早已执行完却没提交的连接:
- 运行
SELECT trx_id, trx_started, trx_state, trx_rows_modified, trx_mysql_thread_id FROM information_schema.INNODB_TRX ORDER BY trx_started LIMIT 5;,重点关注trx_started超过 600 秒、trx_state = 'RUNNING'、且trx_query IS NULL的记录 - 用
trx_mysql_thread_id关联information_schema.PROCESSLIST,查HOST、USER、COMMAND和INFO,确认是否是应用异常挂起(比如 Python 进程崩溃但连接未 close) -
trx_rows_modified = 0的只读事务也会阻塞 purge,但危害小;真正危险的是trx_rows_modified > 10000且长时间未提交的写事务
kill 前必须分状态处理,否则可能更糟
盲目 KILL 可能让实例雪上加霜,不同 trx_state 要区别对待:
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
-
trx_state = 'RUNNING'且trx_query IS NULL:极大概率是应用漏了COMMIT或ROLLBACK,可安全KILL对应线程 -
trx_state = 'LOCK WAIT':它被别的事务堵住了,先查INNODB_LOCK_WAITS找出blocking_trx_id,优先干掉上游事务 -
trx_state = 'ROLLING BACK':别动,此时KILL会让回滚更慢、更占 IO,甚至拖垮 purge 线程 - 若
trx_rows_modified > 100000,回滚可能耗时数分钟,KILL前务必评估业务影响
杀完之后怎么让 undo 空间真正释放出来
杀掉源头事务后,HISTORY LIST LENGTH 不会立刻下降,必须手动助推 purge 并安全缩容:
- 检查 purge 进度:
SHOW ENGINE INNODB STATUS\G,关注 “PURGE DONE for trx's n:o - 临时加大清理力度:
SET GLOBAL innodb_purge_batch_size = 10000;(默认 300) - 确认已启用独立 undo 表空间:
SHOW VARIABLES LIKE 'innodb_undo_tablespaces';,值必须 ≥ 2(推荐设为 4) - 开启自动截断:
SET GLOBAL innodb_undo_log_truncate = ON;,再对每个 undo 表空间执行ALTER UNDO TABLESPACE undo_001 TRUNCATE;
为什么 ALTER UNDO TABLESPACE TRUNCATE 总失败
常见失败现象:ERROR 3655 (HY000): Cannot set innodb_undo_001 inactive since there would be less than 2 undo tablespaces left active —— 默认只有 2 个,不够轮换;或者 ALTER ... SET INACTIVE 成功后 TRUNCATE 仍卡住,说明 HISTORY LIST LENGTH 没回落,purge 还没清理完旧段:
- MySQL 8.0 要求至少保留 2 个 active 的 undo 表空间,不能直接删文件或改
ibdata1里的 undo,否则实例无法启动 - 必须先新增第 3 个 undo 表空间:
CREATE UNDO TABLESPACE undo_003 ADD DATAFILE 'undo_003.ibu'; - 再设旧的为 inactive:
ALTER UNDO TABLESPACE undo_001 SET INACTIVE; - 等
HISTORY LIST LENGTH明显下降、状态变为INACTIVE后,再执行TRUNCATE
整个流程顺序不能错:新增 → 设 inactive → 等 purge 推进 → TRUNCATE。跳步必失败,而且所有操作都得在确认无活跃依赖的前提下进行——最容易被忽略的是 purge 是否真跟上了,而不是“看起来 kill 完了”。










