根本原因是大事务执行中持续写undo log压垮i/o和buffer pool,而非回滚动作本身;优化须从sql行为(如加where、拆分批量)和事务生命周期(及时提交、杀空闲长事务)入手,而非调参。

大事务导致Undo Log性能开销飙升,根本原因不是“回滚慢”,而是事务执行过程中持续写入Undo Log已压垮I/O和buffer pool;优化必须从SQL行为和事务生命周期入手,而非调参。
为什么大事务一跑就卡,回滚更慢
MySQL在UPDATE/DELETE每一行时就同步写一条undo record,不等事务结束。一个更新50万行的事务,会生成50万条undo记录,全部刷盘、占buffer pool、拉长版本链——这阶段IO和内存压力就已经拉满。后续回滚只是“读取并应用”这些早已存在的日志,真正拖慢的是前期积累,不是回滚动作本身。
- 现象:执行中
iostat -x 1看到%util == 100%、await > 20ms;SHOW ENGINE INNODB STATUS\G里History list length持续超5000 - 误区:以为KILL能立刻释放资源——实际KILL后仍要同步处理完当前page的undo,可能更久
- 关键点:
TRX_ROWS_MODIFIED高 +TRX_STARTED早 = 真正元凶,查INFORMATION_SCHEMA.INNODB_TRX比看配置重要十倍
用WHERE精确过滤,避免全表UPDATE触发海量Undo
全表更新UPDATE t SET a = 1等于给每行都记一条undo record,不管字段是否真变。哪怕只改一个常量,Undo体积也和行数线性正相关。
- 正确做法:加明确
WHERE条件,例如UPDATE t SET a = 1 WHERE status = 'pending' AND id BETWEEN ? AND ? - 字段窄一点:只更新必要列,避免
UPDATE t SET a=1,b=2,c=3,...全字段赋值(即使值没变,InnoDB仍记完整前镜像) - 替代方案:对清空类操作,优先用
TRUNCATE TABLE或DROP PARTITION,它们不走Undo,直接释放段
拆分大事务为小批量,控制每次Undo写入量
把单次百万行更新拆成1000行/批,每批提交,可让Undo Log生成节奏可控、及时被purge线程回收,避免单次爆发式写入。
- 示例SQL循环结构:
BEGIN; UPDATE t SET ... WHERE id BETWEEN ? AND ?; COMMIT;,用应用层控制?范围 - 配合
innodb_max_undo_log_size设为128M~256M(即134217728~268435456),确保单个undo表空间不会“一枝独大” - 必须开启
innodb_undo_log_truncate=ON,否则truncate机制不触发;但注意它默认每128秒检查一次,不是实时收缩 - 别碰
innodb_undo_logs(5.7已废弃)或盲目调innodb_purge_batch_size——purge线程行为和回滚无直接关系
长事务不杀,所有优化都是白忙
一个trx_state = 'RUNNING'且trx_query IS NULL的事务,会钉住所有早于它的undo log,purge线程完全无法清理——此时调再小的innodb_max_undo_log_size也没用。
- 每5分钟跑一次检测SQL:
SELECT trx_id, trx_state, trx_started, TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) AS duration_sec, trx_rows_modified, SUBSTRING(trx_query, 1, 80) AS trx_query_truncated FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 600; - 重点杀三类:
trx_state = 'RUNNING'且无查询(连接池泄漏)、trx_rows_modified > 10000且运行超5分钟、trx_state = 'LOCK WAIT'但blocking事务可查到 - KILL前务必确认状态:
trx_state = 'ROLLING BACK'时别动,否则会让purge更卡;History list length > 10000时批量KILL需加SLEEP(0.2)防雪崩
最易被忽略的一点:Undo Log膨胀从来不是磁盘空间告急才出事,而是从第一个长事务挂起那一刻,MVCC版本链就开始变长、SELECT语句开始变慢——问题在读多写少的业务里往往滞后暴露,等发现时已积重难返。











