MySQL 的日志系统是其可靠性和持久性的关键组成部分,主要包括三种重要的日志:undo log(撤销日志)、redo log(重做日志)和binlog(二进制日志)。这三种日志在功能和实现上各有不同,下面将详细介绍它们。
Undo Log(撤销日志)
基本概念
- 定义:undo log是InnoDB存储引擎的一种日志,用于记录事务执行过程中对数据的修改记录,以便在事务回滚或数据库崩溃恢复时撤销未提交的事务。
- 存储位置:存储在系统表空间的回滚段(rollback segment)中。
主要功能
- 事务回滚:当事务需要回滚时,InnoDB可以通过undo log将数据恢复到事务开始前的状态。
- 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
将数据回滚到事务执行前的状态,保证事务的完整性。
Redo Log(重做日志)
基本概念
- 定义:redo log是InnoDB特有的物理日志,记录了对页(Page)的物理修改,用于确保事务的持久性。
- 存储位置:默认位于数据目录下,通常有两个文件
ib_logfile0
和ib_logfile1
。
主要功能
- 保证事务持久性:即使系统崩溃,也能通过redo log恢复已提交事务的修改。
- 提高性能:通过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刷盘策略
Binlog(二进制日志)
基本概念
- 定义:binlog是MySQL服务器层的日志(不是存储引擎层),记录了所有对MySQL数据库的修改操作。
- 存储位置:默认在数据目录,文件名格式为
[hostname]-bin.nnnnnn
。
主要功能
- 复制(Replication) :主从复制的基础,从服务器通过读取主服务器的binlog来复制数据。
- 数据恢复:可基于时间点恢复(Point-in-Time Recovery)。
- 审计:记录所有数据变更,可用于安全审计。
- 用户在主库
master
执行DDL
和DML
操作,修改记录顺序写入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语句,这样就实现了主从库的数据一致;
记录格式
- STATEMENT格式:记录SQL语句。
- ROW格式:记录行数据的变更。
- MIXED格式:混合使用前两种,根据SQL语句的特点选择。
工作原理
- 事务执行过程中,先将修改操作记录到binlog cache。
- 事务提交时,将binlog cache写入binlog文件。
- MySQL通过两阶段提交确保binlog和存储引擎的事务日志(如redo log)一致。
配置参数
log_bin
:启用binlogbinlog_format
:设置binlog格式sync_binlog
:控制binlog刷盘策略expire_logs_days
:binlog保留天数
三种日志的对比
特性 | Undo Log | Redo Log | Binlog |
---|---|---|---|
层次 | 存储引擎层(InnoDB) | 存储引擎层(InnoDB) | 服务器层 |
记录内容 | 数据修改前的状态 | 对页的物理修改 | 逻辑SQL或行变更 |
主要作用 | 事务回滚、MVCC | 崩溃恢复、性能优化 | 复制、数据恢复、审计 |
记录格式 | 逻辑日志 | 物理日志 | 逻辑日志 |
写入时机 | 数据修改前 | 数据修改时(内存)、提交时(磁盘) | 事务提交时 |
两阶段提交(Two-Phase Commit)
为了保证数据一致性,特别是redo log和binlog的一致性,MySQL采用两阶段提交机制:
-
准备阶段:InnoDB将事务的redo log标记为prepare状态,并写入磁盘。
-
提交阶段:
- 写入binlog并刷盘
- 将redo log状态修改为commit
- 完成事务提交
这种机制确保了即使系统在任何阶段崩溃,数据库也能通过崩溃恢复保持一致性。
总结
MySQL的这三种日志协同工作,共同保障了数据库的ACID特性:
- 原子性(Atomicity) :主要通过undo log实现
- 一致性(Consistency) :通过redo log和undo log共同保障
- 隔离性(Isolation) :通过undo log支持的MVCC机制实现
- 持久性(Durability) :主要通过redo log和binlog实现