MySQL 的 undo log、redo log、bin log

58 阅读5分钟

MySQL 的日志系统是其可靠性和持久性的关键组成部分,主要包括三种重要的日志:undo log(撤销日志)、redo log(重做日志)和binlog(二进制日志)。这三种日志在功能和实现上各有不同,下面将详细介绍它们。

image.png

Undo Log(撤销日志)

基本概念

  • 定义:undo log是InnoDB存储引擎的一种日志,用于记录事务执行过程中对数据的修改记录,以便在事务回滚或数据库崩溃恢复时撤销未提交的事务。
  • 存储位置:存储在系统表空间的回滚段(rollback segment)中。

主要功能

  1. 事务回滚:当事务需要回滚时,InnoDB可以通过undo log将数据恢复到事务开始前的状态。
  2. MVCC(多版本并发控制)支持:undo log记录了行记录的多个版本,使不同事务能看到该行记录的不同历史版本,实现了非锁定读。

工作原理

  • 当事务对数据进行修改前,InnoDB会先将修改前的数据备份到undo log中。
  • 事务提交后,相关的undo log不会立即删除,而是由系统根据需要进行回收(purge线程)。
  • undo log会产生redo log,保证undo log的可靠性。

我们举个栗子:假如更新ID=1记录的name字段,name原始数据为小富,现改name为程序员内点事

事务执行update X set name = 程序员内点事 where id =1语句时,先会在undo log中记录一条相反逻辑的update X set name = 小富 where id =1记录,这样当某些原因导致服务异常事务失败,就可以借助undo log将数据回滚到事务执行前的状态,保证事务的完整性。

image.png

Redo Log(重做日志)

基本概念

  • 定义:redo log是InnoDB特有的物理日志,记录了对页(Page)的物理修改,用于确保事务的持久性。
  • 存储位置:默认位于数据目录下,通常有两个文件ib_logfile0ib_logfile1

主要功能

  1. 保证事务持久性:即使系统崩溃,也能通过redo log恢复已提交事务的修改。
  2. 提高性能:通过WAL(Write-Ahead Logging)机制,先写日志再修改磁盘,将随机IO转为顺序IO。

工作原理

  • WAL机制:事务提交时,先将修改写入redo log buffer,再调用fsync写入磁盘。
  • 循环写入:redo log采用循环写入方式,有固定大小,写满后会覆盖最早的记录。
  • 检查点(Checkpoint) :定期将脏页刷新到磁盘,然后标记redo log中对应的部分可重用。

配置参数

  • innodb_log_file_size:单个redo log文件的大小
  • innodb_log_files_in_group:redo log文件组中的文件数量
  • innodb_flush_log_at_trx_commit:控制redo log刷盘策略

image.png

Binlog(二进制日志)

基本概念

  • 定义:binlog是MySQL服务器层的日志(不是存储引擎层),记录了所有对MySQL数据库的修改操作。
  • 存储位置:默认在数据目录,文件名格式为[hostname]-bin.nnnnnn

主要功能

  1. 复制(Replication) :主从复制的基础,从服务器通过读取主服务器的binlog来复制数据。
  2. 数据恢复:可基于时间点恢复(Point-in-Time Recovery)。
  3. 审计:记录所有数据变更,可用于安全审计。

image.png

  • 用户在主库master执行DDLDML操作,修改记录顺序写入bin log;
  • 从库slave的I/O线程连接上Master,并请求读取指定位置position的日志内容;
  • Master收到从库slave请求后,将指定位置position之后的日志内容,和主库bin log文件的名称以及在日志中的位置推送给从库;
  • slave的I/O线程接收到数据后,将接收到的日志内容依次写入到relay log文件最末端,并将读取到的主库bin log文件名和位置position记录到master-info文件中,以便在下一次读取用;
  • slave的SQL线程检测到relay log中内容更新后,读取日志并解析成可执行的SQL语句,这样就实现了主从库的数据一致;

记录格式

  1. STATEMENT格式:记录SQL语句。
  2. ROW格式:记录行数据的变更。
  3. MIXED格式:混合使用前两种,根据SQL语句的特点选择。

工作原理

  • 事务执行过程中,先将修改操作记录到binlog cache。
  • 事务提交时,将binlog cache写入binlog文件。
  • MySQL通过两阶段提交确保binlog和存储引擎的事务日志(如redo log)一致。

配置参数

  • log_bin:启用binlog
  • binlog_format:设置binlog格式
  • sync_binlog:控制binlog刷盘策略
  • expire_logs_days:binlog保留天数

三种日志的对比

特性Undo LogRedo LogBinlog
层次存储引擎层(InnoDB)存储引擎层(InnoDB)服务器层
记录内容数据修改前的状态对页的物理修改逻辑SQL或行变更
主要作用事务回滚、MVCC崩溃恢复、性能优化复制、数据恢复、审计
记录格式逻辑日志物理日志逻辑日志
写入时机数据修改前数据修改时(内存)、提交时(磁盘)事务提交时

两阶段提交(Two-Phase Commit)

为了保证数据一致性,特别是redo log和binlog的一致性,MySQL采用两阶段提交机制:

  1. 准备阶段:InnoDB将事务的redo log标记为prepare状态,并写入磁盘。

  2. 提交阶段

    • 写入binlog并刷盘
    • 将redo log状态修改为commit
    • 完成事务提交

这种机制确保了即使系统在任何阶段崩溃,数据库也能通过崩溃恢复保持一致性。

总结

MySQL的这三种日志协同工作,共同保障了数据库的ACID特性:

  • 原子性(Atomicity) :主要通过undo log实现
  • 一致性(Consistency) :通过redo log和undo log共同保障
  • 隔离性(Isolation) :通过undo log支持的MVCC机制实现
  • 持久性(Durability) :主要通过redo log和binlog实现