在数据库事务管理中,Undo Log 和 Redo Log 是两种关键日志,用于保障事务的 原子性 和 持久性。它们的作用是确保数据库在出现崩溃、断电、宕机等故障时,能够进行恢复操作,从而保障数据一致性和完整性。它们通常用于支持事务的 ACID 特性中的 原子性 和 持久性。下面将分别介绍 Undo Log 和 Redo Log 的原理、实现机制、以及它们的作用。
Undo Log 是回滚日志,它的作用是在事务发生异常或主动回滚时,用于撤销已执行的操作,确保数据库数据能够回到事务开始前的状态,保证事务的 原子性。
INSERT
、UPDATE
、DELETE
)时,数据库会将修改前的记录保存在 Undo Log 中。例如:
UPDATE
操作,事务会记录修改前的数据值。ROLLBACK
),数据库会使用 Undo Log 将被更新的数据恢复到原始值。逻辑日志:Undo Log 是一种逻辑日志,记录的是逻辑上的修改操作。它并不会直接记录每次操作的物理存储修改,而是记录修改前的数据。
链表结构:InnoDB 存储引擎会为每条记录维护一条 Undo Log 记录,并以链表的方式串联起来。如果事务需要回滚,MySQL 会沿着 Undo Log 链表进行逐条回滚,直到恢复到事务开始时的状态。
Undo Log 的类型
:
INSERT
操作,Undo Log 记录的是“删除”操作,因为如果事务回滚,需要撤销插入的数据。DELETE
操作,Undo Log 记录的是“插入”操作,用来恢复被删除的数据。UPDATE
操作,Undo Log 记录的是修改前的旧值,用来恢复原来的值。假设有一条 UPDATE
语句:UPDATE user SET balance = balance + 100 WHERE id = 1;
。在修改 balance
之前,数据库会将 id = 1
用户的原始 balance
值存储在 Undo Log 中。如果事务回滚,系统会从 Undo Log 中恢复 balance
的原始值。
Redo Log 是重做日志,主要用于恢复已经提交的事务,确保数据库的 持久性(Durability)。当数据库发生崩溃时,Redo Log 可以帮助恢复已经提交但尚未写入磁盘的数据。
例如:
INSERT
、UPDATE
或 DELETE
操作时,数据库会先将修改记录写入 Redo Log。当事务提交时,系统会将 Redo Log 刷入磁盘,保证数据不会丢失。假设执行一条 UPDATE
语句:UPDATE user SET balance = balance + 100 WHERE id = 1;
。当事务提交时,MySQL 会将修改后的 balance
值写入 Redo Log,并将 Redo Log 刷入磁盘。如果系统在修改完成后立刻崩溃,虽然数据页未刷新,但 MySQL 可以通过 Redo Log 在重启时恢复提交的事务。
对比项 | Undo Log | Redo Log |
---|---|---|
作用 | 记录数据的旧值,用于回滚事务 | 记录数据的修改,用于恢复已提交的事务 |
日志类型 | 逻辑日志,记录逻辑操作 | 物理日志,记录数据页的物理修改 |
实现机制 | 链表结构,逐条回滚 | 固定大小的循环写机制,WAL 策略 |
使用场景 | 事务回滚、多版本并发控制(MVCC) | 崩溃恢复、保证数据持久性 |
何时写入磁盘 | 修改数据时记录,但无需立即写入磁盘 | 事务提交时必须写入磁盘 |
涉及的 ACID 特性 | 原子性、隔离性 | 持久性 |
在实际的业务系统中,Undo Log 和 Redo Log 是支撑 MySQL 数据库事务和恢复机制的基础。Undo Log 主要用于撤销未完成或回滚的事务操作,而 Redo Log 则用于保证已提交的事务在系统崩溃时能够得到恢复。