只读事务默认不生成Undo日志,但对用户创建的临时表(CREATE TEMPORARY TABLE)执行INSERT/DELETE/UPDATE时,会分配事务ID并生成对应insert或update undo log,以保障其原子性与回滚能力。

只读事务默认不产生Undo日志,但一旦对用户创建的临时表(CREATE TEMPORARY TABLE)执行增删改,就会触发Undo日志生成。
只读事务产生Undo日志的唯一场景
MySQL 的 START TRANSACTION READ ONLY 事务本身不会分配事务 ID,也不会写 Undo 日志——前提是它真的“只读”。但有一个例外:当它操作用户级临时表时,InnoDB 会把它当作读写事务对待。
- 临时表必须是显式创建的:
CREATE TEMPORARY TABLE t_tmp (...),不是 EXPLAIN 中出现的Using temporary那类内部临时表 - 操作必须是 DML:
INSERT INTO t_tmp、DELETE FROM t_tmp、UPDATE t_tmp - 第一次执行上述任一语句时,InnoDB 才分配事务 ID,并初始化 Undo Log segment
- 后续对该临时表的所有改动都会写入对应的
insert undo log或update undo log
为什么临时表是个例外
因为用户临时表的数据生命周期仅限于当前 session,且允许在只读事务中修改——这本质上打破了“只读”的语义边界。InnoDB 不可能为这类操作提供物理快照或复制行,只能靠 Undo Log 实现原子性与回滚能力。
- 没有 Undo Log,
ROLLBACK就无法清理已插入到临时表中的数据 - 临时表虽不参与 MVCC(其他事务看不见它),但仍需事务隔离保障自身一致性
- InnoDB 统一用 Undo Log 管理所有 DML 的回滚逻辑,不为临时表单独开后门
常见误判和排查方式
看到 SHOW ENGINE INNODB STATUS 里有活跃的 Undo Log,却没找到明显 DML?很可能是被忽略的临时表操作。
- 检查是否执行过
CREATE TEMPORARY TABLE+INSERT/UPDATE/DELETE - 查
information_schema.INNODB_TRX表,看TRX_ISOLATION_LEVEL是REPEATABLE READ还是READ COMMITTED,但更关键的是看TRX_ROWS_MODIFIED是否 > 0 - 用
SELECT * FROM performance_schema.events_statements_history WHERE SQL_TEXT LIKE '%temp%'回溯近期语句 - 注意:
SELECT ... INTO TEMPORARY TABLE也会触发 Undo Log,因为它隐含 INSERT
真正容易被忽略的点在于:临时表操作看似“无关紧要”,但它会让一个标称只读的事务实质上进入 InnoDB 的完整事务路径——包括事务 ID 分配、Undo Log 分配、redo log 联动写入。一旦忘记清理这些临时表或未显式 ROLLBACK,就可能拖住 Purge 线程,让 undo tablespace 持续增长。


















