可查询INFORMATION_SCHEMA.INNODB_TABLESPACES获取Undo表空间基础状态,执行SELECT NAME, SPACE_TYPE, FILE_NAME, FILE_SIZE, ALLOCATED_SIZE, STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE SPACE_TYPE = 'Undo',其中STATE为active表示正在使用,inactive表示已停用待截断。

查 information_schema.innodb_tablespaces 看表空间基础状态
MySQL 8.0 中,Undo 表空间信息不暴露在 performance_schema 或事务级视图中,而是集中存于 information_schema.innodb_tablespaces。它能告诉你每个 Undo 表空间的文件名、大小、状态,但**不直接反映“当前事务”占用了多少**——因为 Undo 是按回滚段(rseg)动态分配、跨事务复用的,没有一对一映射。
执行以下语句获取当前所有 Undo 表空间快照:
SELECT NAME, SPACE_TYPE, FILE_NAME, FILE_SIZE, ALLOCATED_SIZE, STATE FROM information_schema.INNODB_TABLESPACES WHERE SPACE_TYPE = 'Undo';
注意字段含义:
-
FILE_SIZE:文件系统上该 .ibu 文件的总大小(字节),由操作系统决定 -
ALLOCATED_SIZE:InnoDB 当前已从该文件中分配出去、用于存放 Undo 记录的实际页数换算值(通常 ≈FILE_SIZE,除非刚 truncate 过) -
STATE:为active表示正在被 Purge 线程和新事务使用;inactive表示已停用,等待自动截断
用 INFORMATION_SCHEMA.FILES 验证物理文件路径与大小
INNODB_TABLESPACES 的 FILE_NAME 字段有时显示相对路径或别名(如 undo_001),无法直接对应磁盘文件。此时需结合 INFORMATION_SCHEMA.FILES 查真实路径:
SELECT FILE_NAME, TABLESPACE_NAME, TOTAL_EXTENTS, EXTENT_SIZE FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE = 'UNDO LOG';
该结果中的 FILE_NAME 是绝对路径(如 /data/mysql/data/undo_001.ibu),可配合系统命令验证:
-
ls -lh /data/mysql/data/undo_*.ibu—— 看实际文件体积是否与FILE_SIZE一致 -
du -h /data/mysql/data/undo_*.ibu—— 排除稀疏文件干扰,确认真实磁盘占用
如果两者差异大(比如 FILE_SIZE 显示 16M,du 显示 71G),说明该 Undo 表空间已被撑大且尚未被截断,背后大概率存在长事务或未提交事务拖住了 oldest active read view。
定位“谁在拖住 Undo 清理”:查活跃事务与读视图
真正影响 Undo 空间能否回收的,不是“当前事务写了多少 Undo”,而是**最老的活跃读视图(oldest active read view)是否释放**。这个视图由最早未结束的事务(包括只读事务)持有。
关键查询如下:
SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id, trx_query FROM information_schema.INNODB_TRX ORDER BY trx_started ASC LIMIT 5;
重点关注:
-
trx_state = 'RUNNING'且trx_started时间极早(比如几小时甚至几天前)→ 极可能是元凶 -
trx_query IS NULL但trx_state = 'ACTIVE'→ 可能是空闲连接未断开,或应用层开启事务后忘了 commit/rollback - 搭配
SHOW PROCESSLIST看对应线程是否处于Sleep状态,进一步确认是否连接泄漏
注意:INNODB_TRX 不显示只读事务(如带 START TRANSACTION READ ONLY 的),但这类事务同样会阻止 Undo 清理。若怀疑,可用 SELECT * FROM performance_schema.threads WHERE TYPE = 'FOREGROUND' AND PROCESSLIST_COMMAND = 'Sleep' 辅助排查长时间空闲连接。
为什么不能精确到“单个事务占了多少 Undo”
Undo Log 在 InnoDB 内部以回滚段(rseg)为单位组织,每个 rseg 可服务多个并发事务,事务的 Undo 记录写入是追加+复用的,且会被 Purge 线程异步清理。这意味着:
- 没有 per-transaction 的 Undo 字节数统计字段(
INNODB_TRX里没有类似undo_bytes_used的列) - 即使你 kill 掉一个大事务,其 Undo 也不会立刻释放,而是等 Purge 线程后续扫描并截断整个 undo file
-
innodb_max_undo_log_size控制的是单个 Undo 表空间触发截断的阈值,不是单事务限额
所以,运维中真正要盯的不是“某个事务占了多少”,而是“有没有事务卡太久”,以及 “innodb_undo_log_truncate 是否开启 + innodb_purge_rseg_truncate_frequency 是否设得够低”。否则,就算你看到 ALLOCATED_SIZE 持续上涨,也找不到具体是哪个 SQL 导致的——它只是表象,根因永远在事务生命周期管理上。


















