innodb_trx表不提供undo大小字段,因其设计仅反映事务状态而非实时undo空间消耗;需结合长事务(trx_state='running'且trx_started超10分钟)、sleep线程及history list长度>5000三者交叉验证undo挤压情况。

查 INNODB_TRX 只能看状态,别指望它返回 Undo 大小
直接执行 SELECT * FROM information_schema.INNODB_TRX 会返回 trx_id、trx_state、trx_started、trx_mysql_thread_id 和 trx_query 等字段,但表里压根没有 undo_size 或类似字段。这不是遗漏,是 InnoDB 的设计决定:Undo 段由后台异步管理,空间分配和复用不与单个事务强绑定,无法实时映射为一个字节数。
常见误判是把 trx_rows_modified 当成 Undo 占用——它只反映修改行数。一次含 TEXT 字段的 UPDATE 可能生成几十 KB Undo;而 10 万行纯整型更新可能才占 2MB。这个值只能辅助估算下限,不能当作实际占用。
交叉验证三要素,才能判断 Undo 是否真在被挤压
真正要定位“这个未提交事务是否正在拖垮 Undo”,得同时满足以下三点:
-
TRX_STATE = 'RUNNING'且trx_started早于当前时间 10 分钟以上(NOW() - INTERVAL 600 SECOND) - 该事务对应的线程在
PROCESSLIST中COMMAND = 'Sleep'且TIME很大(说明应用端挂起,既没COMMIT也没ROLLBACK) - 全局
History list length持续 > 5000(通过SHOW ENGINE INNODB STATUS\G查,说明 purge 被阻塞)
单独看任一指标都容易误判。比如 trx_state = 'LOCK WAIT' 的事务本身不产 Undo,但它卡住上游事务,间接导致 History list 堆积。
用 performance_schema 追踪内存与 I/O 关联消耗
未提交事务本身不直接吃内存,但它会让线程长期持有锁结构、字典缓存、回滚段指针等资源,这些会体现在 performance_schema.memory_summary_by_thread_by_event_name 和 events_statements_history_long 中。
先确保内存监控已启用:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'memory/%';
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME IN ('global_instrumentation', 'thread_instrumentation');
然后查具体线程内存占用:
SELECT thread_id, user, event_name, sys.format_bytes(CURRENT_NUMBER_OF_BYTES_USED) AS memory_used
FROM performance_schema.memory_summary_by_thread_by_event_name
WHERE CURRENT_NUMBER_OF_BYTES_USED > 1024*1024
AND thread_id IN (
SELECT THREAD_ID FROM performance_schema.threads
WHERE PROCESSLIST_ID IN (
SELECT trx_mysql_thread_id FROM information_schema.INNODB_TRX
WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 600
)
);
KILL 前必须看 trx_state 和 purge 状态
直接 KILL 12345 风险很高。必须分情况处理:
-
trx_state = 'RUNNING'且trx_query IS NULL:事务空闲中,极大概率是应用没调COMMIT或ROLLBACK,可安全KILL -
trx_state = 'LOCK WAIT':它正卡在等锁,得先查INNODB_LOCK_WAITS找出 blocking 事务,优先干掉上游 -
trx_state = 'ROLLING BACK':别动,等它自己结束;此时innodb_fast_shutdown = 0重启也无效,只会延长恢复时间
如果 SHOW ENGINE INNODB STATUS 里 “History list length” 超过 10000,说明 purge 已严重滞后,批量 KILL 会雪上加霜,建议加 SLEEP(0.2) 间隔执行。
Undo 膨胀不是孤立现象,它总是和 Sleep 连接、MDL 锁排队、purge 滞后咬合在一起。查 INNODB_TRX 是起点,但只盯着这一个视图就动手,大概率治标不治本。











