MySQL三大日志详解:Undo Log、Redo Log和Binlog的作用与工作机制
前言
MySQL
中的Undo Log、Redo Log
和Binlog
是保障数据库事务安全、数据一致性和高可用性的核心组件。它们分工明确,协同工作,但各自有不同的设计目标和实现机制。
Undo Log:保障事务原子性与 MVCC 的基石
作用
Undo Log
主要用于事务回滚以及实现多版本并发控制(MVCC
)。在事务执行过程中,当进行诸如INSERT、UPDATE、DELETE
等写操作时,数据库会将修改前的数据副本记录在Undo Log
中。这样一来,如果事务执行过程中出现异常或者用户主动执行ROLLBACK
操作,数据库可以依据Undo Log
中的记录,将数据恢复到事务开始前的状态,从而保证了事务的原子性,即事务中的所有操作要么全部成功执行,要么全部不执行。
同时,在MVCC
场景下,当一个事务对数据进行修改时,其他事务在读取数据时,若读取的行被锁定,就可以从Undo Log
中获取该行数据在之前版本的状态,实现非阻塞读,提升数据库的并发性能。
工作机制
根据操作类型,Undo Log
可分为Insert Undo Log
和Update Undo Log
:
Insert Undo Log
用于INSERT
操作的回滚,它主要记录新插入记录的主键信息,回滚时只需依据该主键删除对应的记录即可。Update Undo Log
则用于UPDATE
和DELETE
操作的回滚,它会记录被修改记录的旧值,即修改前的完整数据行。在回滚时,使用旧值覆盖当前值,以还原数据。
Undo Log
存储在InnoDB
的Undo Tablespace
中,其管理通过Rollback Segment
(回滚段)来实现。每个Rollback Segment
包含多个Undo Log Slot
,用于存储Undo Log
记录。
- 事务启动时,会以轮询的方式从
Rollback Segment
中分配空闲的Slot
。 - 事务提交后,
Slot
并不会立即释放,对于INSERT
生成的TRX_UNDO_INSERT
类型日志,事务提交后可立即释放;而对于UPDATE/DELETE
生成的TRX_UNDO_UPDATE
类型日志,由于MVCC
可能仍需访问其历史版本,所以需保留至所有快照读不再引用,之后这些Slot
中的Undo Log
会被加入History List
,由后台Purge
线程异步清理。 - 当事务回滚时,
InnoDB
会按照相反顺序处理Undo Log
记录。对于Update Undo Log
,执行更新操作,用旧值覆盖当前值,从而完成数据的回滚。在快照读时,InnoDB
通过ReadView
,依据隔离级别和事务ID
,从Undo Log
中读取历史版本数据,而非最新数据。Purge
线程则负责在Undo Log
记录不再被任何事务的ReadView
引用时,对其进行清理,回收空间。
Redo Log:确保事务持久性的关键
作用
Redo Log
主要用于确保事务的持久性。当事务提交时,MySQL
并不会立刻将所有修改的数据刷新到磁盘,因为磁盘I/O
操作相对较慢,这样会严重影响性能。而是先将修改内容记录到 Redo Log
中,之后再异步地将数据写入磁盘。即使在数据库发生崩溃、断电等故障时,只要Redo Log
存在,系统在重启后就可以依据Redo Log
中的记录,重新应用已提交事务的修改,保证已提交事务的数据不会丢失,从而实现事务的持久性。
工作机制
InnoDB
采用Write-Ahead Logging
(WAL
)机制,即先写日志,再写磁盘。每次事务提交时,InnoDB
会先将Redo Log
写入磁盘,而后再逐步将实际修改的数据写入磁盘。在执行INSERT、UPDATE
或DELETE
操作时,数据库会首先将修改记录写入Redo Log
缓存。当事务提交时,系统会将Redo Log
缓存中的内容刷入磁盘上的Redo Log
文件。
Redo Log
文件通常以循环的方式使用,当一个Redo Log
文件写满后,会切换到下一个文件继续写入。InnoDB
存储引擎中,Redo Log
的写入操作是顺序的,这相较于随机写磁盘,大大提高了写入性能。在系统运行过程中,InnoDB
会定期将Redo Log
中的修改应用到数据页,并将脏页(即被修改但还未写入磁盘的数据页)刷新到磁盘。
当数据库崩溃后重启,MySQL
会进入恢复阶段。首先,进行Redo
前滚阶段,通过Redo Log
恢复已提交事务的数据页;然后,扫描未提交事务的Undo
日志,并按日志序列号(LSN
)逆序执行补偿操作,例如将INSERT
操作补偿为DELETE
操作,UPDATE
操作还原为修改前的状态,从而确保数据库的数据一致性。
Binlog:数据备份、恢复与复制的利器
作用
Binlog
(二进制日志)主要有两个重要作用。其一,用于数据库的点时间恢复。通过记录数据库执行的所有写操作,在需要时可以根据Binlog
中的记录,将数据库恢复到指定时间点的状态。其二,在主从复制架构中,Binlog
起着关键作用。主库将自身执行的写操作记录到Binlog
中,从库通过读取主库的Binlog
,并在本地重放这些操作,从而实现与主库的数据同步,保证主从库数据的一致性。
工作机制
Binlog
记录的并非所有SQL
语句,而是包含了已执行的SQL
语句(增、删、改)的反向信息。例如,DELETE
操作在Binlog
中对应的是反向插入操作;UPDATE
操作对应的是更新前后的版本信息;INSERT
操作对应的是DELETE
和INSERT
操作。通过使用 mysqlbinlog
工具解析Binlog
,可以清晰地看到这些记录。
当一个事务提交时,该事务中的每一条SQL
语句(一个事务可能对应多条SQL
语句)都会以特定格式记录在Binlog
中。与Redo Log
不同的是,Redo Log
在事务开始后就逐步写入磁盘,而Binlog
是在事务提交时一次性写入。Binlog
的默认保留时间由expire_logs_days
参数设置,超过该时间的非活动日志文件会被自动删除。
在主从复制过程中,主库会将Binlog
发送给从库,从库接收后,按照Binlog
中的记录顺序,在本地依次执行相应的SQL
操作,从而使从库的数据与主库保持一致。这种方式使得MySQL
的主从复制架构能够高效地实现数据的同步与备份,为数据的高可用性和灾难恢复提供了有力支持。
关联与协同工作
事务处理过程中的协同
当一个事务开始执行,Undo Log
率先发挥作用,以UPDATE
操作为例:
- 在对数据进行修改前,数据库会将原始数据记录到
Undo Log
中,为事务回滚提供依据,保障事务的原子性。同时Redo Log
也开始记录事务执行过程中对数据的修改操作,将其写入 Redo Log` 缓存。 - 随着事务推进,每一个写操作产生的变化,不仅记录在
Redo Log
缓存中,还会在Binlog
中有所体现。Binlog
在事务提交时,将事务涉及的SQL
语句(增、删、改)以特定格式记录下来。当事务提交时,InnoDB
会先将Redo Log
缓存中的内容刷入磁盘上的Redo Log
文件,确保已提交事务的修改不会因系统崩溃丢失,实现事务持久性; - 随后,
Binlog
也将事务记录写入文件,完成事务在二进制日志层面的记录。而Undo Log
中的记录在事务提交后,对于INSERT
类型日志可能会立即释放相关资源,对于UPDATE/DELETE
类型日志,因MVCC
需求会保留一段时间,直至不再被引用后由Purge
线程清理。 - 在并发事务场景下,
Undo Log
实现的MVCC
机制,使得读取操作可以从Undo Log
获取数据历史版本,避免对正在修改的数据加锁,提升并发性能。与此同时,Redo Log
持续记录事务修改,Binlog
也记录着事务的写操作,三者协同保证并发事务处理的正确性和高效性。
流程图
故障恢复时的协作
当MySQL
数据库遭遇崩溃、断电等故障后重启,Redo Log
和Undo Log
会紧密配合完成数据恢复工作。
- 首先,数据库进入
Redo
前滚阶段,通过Redo Log
恢复已提交事务的数据页,将数据库状态恢复到故障发生前已提交事务修改后的状态。 - 接着,数据库会扫描未提交事务的
Undo
日志,并按日志序列号(LSN
)逆序执行补偿操作。例如,将未提交事务中的INSERT
操作补偿为DELETE
操作,UPDATE
操作还原为修改前的状态,以此确保数据库的数据一致性。在这一过程中,Redo Log
和Undo Log
相互配合,Redo Log
恢复已提交事务,Undo Log
回滚未提交事务,二者共同保证数据库在故障恢复后数据的完整性和一致性。
而Binlog
在故障恢复中,主要用于基于时间点的恢复。如果数据库因误操作等原因需要恢复到某个特定时间点的状态,可以通过解析Binlog
,获取从数据库备份时间点到指定时间点之间的所有写操作记录,在恢复的数据库实例上重放这些操作,从而将数据库恢复到指定时间点的状态。
主从复制中的配合
在MySQL
主从复制架构中,Binlog
是主从库数据同步的核心。主库在执行写操作时,将这些操作记录到Binlog
中,从库通过I/O
线程连接主库,获取主库的Binlog
日志,并将其保存在从库的中继日志(Relay Log
)中。
从库的SQL
线程读取中继日志中的内容,并在本地依次执行相应的SQL
操作,实现与主库的数据同步。在这一过程中,Redo Log
和Undo Log
同样发挥着重要作用。从库执行中继日志中的 SQL
操作时,如同在本地执行事务,Redo Log
记录着这些操作对数据的修改,保障从库事务的持久性;Undo Log
则用于处理可能的事务回滚,确保从库数据的一致性。
例如,当从库执行一个UPDATE
操作时,Redo Log
记录该操作的修改,Undo Log
记录修改前的数据版本,若事务执行过程中出现异常,可通过Undo Log
回滚事务;而Binlog
则作为主从库数据同步的桥梁,源源不断地将主库的写操作传递给从库。
总结
理解这三大日志之间的协同关系,有助于数据库管理员更好地进行数据库管理、性能优化和故障排查,也能让开发人员在设计和开发数据库应用时,充分利用数据库特性,构建出更加稳定、可靠、高效的应用系统。
本文地址:https://www.yitenyun.com/272.html