Seata的undo_log表膨胀需通过服务端配置server.undo.logSaveDays和server.undo.logDeletePeriod控制自动清理,严禁手动DELETE;InnoDB的Undo Log膨胀则需定位最老活跃事务并终止,再启用innodb_undo_log_truncate机制。

长事务卡住 purge,Undo Log 就会持续膨胀直到磁盘写满——这不是容量问题,是事务生命周期失控。
查哪些事务在拖慢 Undo Log 清理
核心就是定位“最老活跃事务”,它决定了 purge 线程能清理到哪条 Undo 记录。关键不是看有多少事务,而是看哪个事务的 TRX_STARTED 时间最早、且 TRX_STATE 仍是 RUNNING:
-
SELECT TRX_ID, TRX_STARTED, TRX_STATE, TRX_ROWS_MODIFIED, TRX_ISOLATION_LEVEL FROM information_schema.INNODB_TRX ORDER BY TRX_STARTED LIMIT 5;—— 重点关注TRX_STARTED超过 30 分钟的记录 - 搭配
SELECT ID, USER, HOST, DB, COMMAND, TIME, INFO FROM information_schema.PROCESSLIST WHERE ID = [trx_mysql_thread_id];查具体 SQL,常见陷阱是UPDATE ... WHERE ...没加LIMIT或漏了COMMIT - 只读事务(
TRX_ROWS_MODIFIED = 0)也会持有快照,但不会新增 Undo;真正危险的是TRX_ROWS_MODIFIED > 10000还没提交的写事务
用 History list length 判断 purge 是否被堵死
SHOW ENGINE INNODB STATUS\G 输出里找 History list length 行。这个值不是“当前 Undo 大小”,而是“等待被 purge 的记录数”:
- 稳定在
0 ~ 100:正常 - 持续 >
1000:purge 开始滞后 - >
10000且缓慢上涨:大概率有长事务或 purge 线程不足 - 注意:该值不会因
KILL一个事务立刻下降,需等事务回滚完成 + purge 跟进,通常延迟几秒到几分钟
紧急清理前先释放阻塞源
直接 TRUNCATE UNDO TABLESPACE 可能失败,因为 purge 被卡住。必须先清掉源头:
- 终止空闲连接:
SELECT CONCAT('KILL ', ID, ';') FROM information_schema.PROCESSLIST WHERE COMMAND = 'Sleep' AND TIME > 1800;—— 执行结果里的所有KILL命令 - 确认无长事务后,再强制推进 purge:
SET GLOBAL innodb_purge_batch_size = 10000;(加大单次清理量) - 开启自动截断(仅限 MySQL 5.7+ 独立 undo 表空间):
SET GLOBAL innodb_undo_log_truncate = ON;,然后ALTER UNDO TABLESPACE undo_001 TRUNCATE; - 别碰
ibdata1里的共享 undo —— 截断无效,只能重建实例
Seata 的 undo_log 表膨胀要单独处理
这是应用层框架日志,和 InnoDB 的 Undo Log 完全无关,但同样吃磁盘。监控和清理逻辑完全不同:
- 查大小:
SELECT table_name AS `Table`, ROUND(((data_length + index_length) / 1024 / 1024), 2) AS `Size (MB)` FROM information_schema.TABLES WHERE table_schema = 'your_db' AND table_name = 'undo_log'; - 清理依赖服务端配置:
server.undo.logSaveDays=7和server.undo.logDeletePeriod=86400000,改完需重启 Seata Server - 切勿手动
DELETE FROM undo_log—— 可能破坏 AT 模式事务一致性;应通过 Seata 自带的定时任务或调用其清理接口 - 生产建议:把
undo_log表挪到独立数据库实例,避免拖垮业务库
最易被忽略的一点:TRX_ISOLATION_LEVEL = 'REPEATABLE READ' 下,哪怕事务只执行了 SELECT,只要没结束,就会一直持有启动时刻的读视图,间接锁住 Undo。所以“只读事务不危险”是有前提的——它得及时 COMMIT 或 ROLLBACK。


















