MySQL通过undo log实现事务回滚和MVCC,修改前的数据被记录在undo log中,用于事务回滚时恢复旧值、提供一致性读及崩溃恢复;INSERT回滚执行DELETE,UPDATE回滚写入原值,DELETE回滚则恢复记录;MySQL 8.0起undo log独立存储于undo表空间,事务提交后由purge线程在无事务需要时清理,避免长时间大事务导致空间占用。

MySQL 使用 undo log 来实现事务的回滚和多版本并发控制(MVCC)。当一个事务对数据进行修改时,MySQL 会把修改前的数据保存到 undo log 中。如果事务需要回滚,系统就可以利用这些旧值将数据恢复到事务开始前的状态。
undo log 的作用
undo log 主要用于:
• 记录数据修改前的状态,支持事务回滚• 提供一致性读取,配合 MVCC 实现非锁定读(如 SELECT)
• 在事务崩溃后恢复时,用于撤销未提交的更改
事务回滚时如何使用 undo log
当执行 ROLLBACK 命令或事务异常终止时,MySQL 会从 undo log 中读取对应记录的旧版本数据,并按相反顺序执行逆操作来还原变更。
具体过程如下: • 对于 INSERT 操作:MySQL 会从 undo log 获取主键,然后执行 DELETE 操作删除这条记录• 对于 UPDATE 操作:undo log 中保存了被修改字段的原始值,MySQL 将这些值重新写回对应行
• 对于 DELETE 操作:这实际上是“标记删除”,undo log 存储的是完整记录内容,回滚时将其恢复为正常状态
例如,假设有一个事务更新了一条用户余额记录:
UPDATE accounts SET balance = 1000 WHERE id = 1;
在执行该语句前,MySQL 会把原 balance 值(比如 500)写入 undo log。如果后续调用 ROLLBACK,InnoDB 引擎就会读取这个旧值并重新设置回去。
undo log 的存储位置
在 MySQL 8.0 之前,undo log 存储在共享表空间(ibdata1)中。从 MySQL 8.0 开始,undo log 可以独立管理,默认位于 undo tablespaces 中,路径通常是数据目录下的 undo_001、undo_002 等文件。
你可以通过以下参数查看或配置:
• innodb_undo_directory:指定 undo 表空间存放目录• innodb_undo_tablespaces:定义 undo 表空间数量
• innodb_max_undo_log_size:控制单个 undo 文件最大大小
自动清理与 purge 机制
一旦事务提交,undo log 并不会立即删除。它需要保留一段时间,因为可能还有其他事务正在读取这个历史版本(MVCC 需要)。只有当确认没有事务再需要这些快照时,purge 线程才会真正清除对应的 undo log 数据。
长时间运行的事务会导致 undo log 无法释放,占用磁盘空间。因此建议避免大事务,及时提交或回滚。
基本上就这些。undo log 是 InnoDB 实现事务原子性和隔离性的关键组件,理解其工作机制有助于优化数据库性能和排查问题。










