未开启事务时InnoDB是否会记录undo log和redo log?
InnoDB 层面不存在完全脱离事务上下文的数据操作场景,你认知里的“未开启事务”本质只是没有手动启动显式长事务,只要执行了数据修改操作,无论是否手动开启事务,undo log 和 redo log 都会正常记录。
先澄清一个普遍认知误区
很多人觉得“没写BEGIN/START TRANSACTION就是没开事务”,这个理解是错的:
- InnoDB 所有对数据的读写操作都必须运行在事务框架内。MySQL 默认开启
autocommit配置,这种模式下你每执行一条 DML 语句,InnoDB 会自动给这条语句分配独立事务,语句执行完立刻自动提交;如果关闭了autocommit,就算你没手动写开启事务的语句,执行第一条 DML 时也会自动启动事务,直到你手动执行COMMIT/ROLLBACK才会结束事务。 - 所谓的“未开启事务”,只是没有手动声明跨多语句的显式事务而已,底层的事务机制从来不会停止运行。
两类日志的记录规则和是否手动开事务没有关联
Redo Log
Redo Log 是实现 WAL 预写机制、保障崩溃后已提交数据不丢失的核心组件,它的触发记录条件非常明确:只要事务执行过程中修改了内存中的数据页,就会先写对应的 Redo Log 到日志缓冲区。
不管这个事务是你手动开启的跨多语句事务,还是系统自动创建的单语句自动提交事务,规则完全一致。举个最常见的场景:你在 autocommit 开启的状态下执行UPDATE user SET age = 20 WHERE id = 1;,没有手动写任何事务相关语句,执行过程中照样会先把数据页的修改操作写入 Redo Log Buffer,事务提交时按照innodb_flush_log_at_trx_commit参数的配置刷到磁盘,完全不会跳过记录流程。
Undo Log
Undo Log 承担两个核心作用:一是支撑事务异常时的回滚操作,保证事务原子性;二是存储数据的历史版本,支撑 MVCC 多版本一致性读。它的触发条件同样是执行数据修改操作,和事务是否手动开启没有关系。
还是以上面那条单语句 UPDATE 为例,InnoDB 在真正修改数据前,一定会先把修改前的旧版本数据写入 Undo Log:一方面如果语句执行过程中出现错误(比如唯一键冲突、实例中途宕机),可以靠 Undo Log 把已经完成的部分修改回滚,保证语句级原子性;另一方面就算这条语句执行提交完成,后续如果有更早启动的一致性读事务需要访问这条记录的旧版本,也会通过 Undo Log 版本链找到对应历史数据。
唯一不记录两类日志的场景
只有执行纯只读操作的时候(比如不加锁的普通SELECT语句),无论是否开启事务,都不会写入 Undo Log 和 Redo Log——毕竟没有对任何数据产生修改,自然不需要记录回滚、崩溃恢复相关的日志。
内容的提问来源于stack exchange,提问作者choxsword

