MySQL 的BinLog日志

43 阅读7分钟

1 基本概念

BinLog是一种记录所有MySQL数据库表结构变更以及表数据变更的二进制日志。BinLog中不会记录诸如select和show这类查询操作的日志。BinLog有如下两个重要的使用场景

  • 主从复制:在主数据库上开启BinLog,主数据库把BinLog发送至从数据库,从数据库获取BinLog后通过IO线程将日志吸入到中继日志,也就是Relay Log中。然后通过SQL线程将Relay Log中的数据同步至从数据库,从而达到主从数据库的一致性。
  • 数据恢复:当MySQL数据库发生故障或者崩溃时,可以通过BinLog进行数据恢复。

2 记录模式

2.1 Row模式

  • 记录内容:记录数据行的实际变更(如某行的字段从A变为B)。
  • 特点
    • 优点:复制更精确,不会出现因语句执行环境不同导致的主从数据不一致。
    • 缺点:日志量大(尤其是批量操作时),性能略低。大批量操作时候,会产生大量的二进制日志。比如使用alter table操作修改用友大量数据的数据表结构时,会使二进制日志的内容暴涨,产生大量的二进制日志,从而大大影响主从数据库的同步性能。
  • 适用场景:对数据一致性要求高的场景(如金融系统),或使用了不确定函数的环境。

2.2 Statement模式

  • 记录内容:记录 SQL 语句本身(如INSERTUPDATE)。
  • 特点
    • 优点:日志量小,节省存储空间,性能较高。由于不记录数据的修改细节,只是记录数据表结构和数据变更的SQL语句,因此产生的二进制日志数据量比较小,这样能够减少磁盘的IO操作,提升数据存储和恢复的效率。
    • 缺点:某些语句在复制时可能导致主从数据不一致(如NOW()RAND()等函数,或使用触发器、存储过程时)。
  • 适用场景:语句确定性高、无特殊函数或触发器的环境。

2.3 Mixed模式

  • 记录内容自动选择使用 STATEMENT 或 ROW 模式:
    • 默认使用 STATEMENT 模式。
    • 遇到不确定语句(如RAND())或可能导致数据不一致的操作时,自动切换为 ROW 模式。
  • 特点
    • 优点:平衡了性能和数据一致性。
    • 缺点:仍可能存在少量特殊场景下的不一致风险。
  • 适用场景:大多数生产环境的默认选择。

3 文件结构

3.1 单个Binlog文件内部结构

每个Binlog文件由以下几部分组成:

3.1.1 文件头(4字节)

  • 魔术数字0xfe 0x62 0x69 0x6e(即"bin"前面加0xfe)

3.1.2 事件序列

  • 由多个事件(Event)按时间顺序排列组成
  • 每个事件代表一个数据库操作或元数据变更

3.1.3 文件尾

  • 当文件正常关闭时,会写入一个Rotate Event指向下一个文件
  • 非正常关闭时可能没有文件尾

3.2 事件(Event)结构

每个事件包含以下部分:

部分大小说明
事件头19字节包含事件元数据
事件体可变事件的具体内容
校验和4字节(可选)事件的CRC32校验值

3.2.1 事件头详细结构(19字节):

偏移量长度字段说明
04timestamp事件发生的时间戳
41type_code事件类型代码
54server_id产生事件的服务器ID
94event_length整个事件长度(头+体)
134next_position下一个事件的位置
172flags事件标志位

3.3 常见事件类型

类型代码事件类型说明
0x01START_EVENT_V3旧版本开始事件
0x02QUERY_EVENT执行SQL语句(STATEMENT 模式)
0x04ROTATE_EVENTbinlog文件切换
0x0fFORMAT_DESCRIPTION_EVENT文件格式描述
0x10XID_EVENT事务提交事件
0x11TABLE_MAP_EVENT表映射事件(ROW模式)
0x12WRITE_ROWS_EVENT插入行事件(ROW模式)
0x13UPDATE_ROWS_EVENT更新行事件(ROW模式)
0x14DELETE_ROWS_EVENT删除行事件(ROW模式)
0x15INCIDENT_EVENT服务器异常事件

3.4 不同模式下的事件差异

3.4.1 STATEMENT 模式

  • QUERY_EVENT:直接记录 SQL 语句。
    +--------+----------------+-------------------+
    | 头信息 | 数据库名长度   | SQL语句           |
    +--------+----------------+-------------------+
    

3.4.2 ROW 模式

  • TABLE_MAP_EVENT:定义表结构(表 ID、列类型等)。
  • WRITE_ROWS_EVENT:记录插入的行数据。
    +--------+-------+----------------+----------------+
    | 头信息 | 表ID  | 列掩码         | 行数据         |
    +--------+-------+----------------+----------------+
    

4 BinLog和Redo Log的区别

4.1 所属层次与适用范围

  • redo log:属于InnoDB 存储引擎特有的日志,仅 InnoDB 会使用,其他存储引擎(如 MyISAM)不支持。
  • binlog:属于MySQL 服务器层(Server 层)  的日志,所有存储引擎(包括 InnoDB、MyISAM 等)都可以使用,是 MySQL 全局的日志机制

4.2 日志类型与记录内容

维度redo logbinlog
日志类型物理日志逻辑日志
记录内容记录数据页(Page)的物理修改(如 “将数据页 X 的偏移量 Y 处的值从 A 改为 B”)记录 SQL 操作的逻辑变化(如 “插入一条 id=1 的记录”“更新 id=2 的记录的 name 字段”)
特点与具体数据页绑定,依赖 InnoDB 的页结构,具有幂等性,多次操作的前后状态可能是一致的与存储引擎无关,仅记录逻辑操作,不依赖底层数据结构

4.3 写入方式

  • redo log
    循环写(circular write)  的日志,有固定大小。当日志写满后,会覆盖最早的日志(前提是这些日志对应的修改已同步到磁盘数据文件)。
  • binlog
    追加写(append write)  的日志,不会覆盖旧内容。当一个 binlog 文件写满,会自动创建新文件(文件名按 “binlog.000001、binlog.000002” 递增),旧文件会保留(可通过expire_logs_days设置自动清理时间)

4.4 写入时机与事务关联

  • redo log:在事务执行过程中实时写入(并非等到事务提交)。例如,执行update t set a=1 where id=1时,每修改一个数据页,就会同步记录 redo log(但此时 redo log 处于 “未提交” 状态,事务提交后才会标记为 “可持久化”)。
  • binlog:在事务提交时写入(默认配置下)。当事务执行commit时,MySQL 会将该事务的逻辑操作(如整个update语句的逻辑)写入 binlog,作为事务完成的记录。BinLog日志的记录方式与事务的提交顺序有关,并且一个事务的BinLog中间不会插入其他事务的BinLog。而Redo Log记录的是物理页的修改,最后一个提交的事务记录会覆盖之前的所有未提交的事务记录,并且一个事务的Redo Log中间会插入其他事务的Redo Log

4.5 核心作用与场景

  • redo log:核心作用是保证事务的持久性(ACID 中的 D) ,防止数据库崩溃后的数据丢失。
    • 场景:数据库宕机后重启时,InnoDB 会通过 redo log 恢复 “已提交但未写入磁盘数据文件(.ibd)” 的修改,确保数据不丢失。
  • binlog:核心作用是记录数据的逻辑变更,用于主从复制数据恢复
    • 场景 1:主从复制中,从库通过读取主库的 binlog,重演逻辑操作以同步数据;
    • 场景 2:数据恢复时,可通过 binlog 重演指定时间范围内的操作(如 “恢复到昨天 18 点的数据”)。

4.6 为何需要两种日志?

两者的设计目标互补:

  • redo log 是 InnoDB 为了保证自身存储引擎的 “崩溃恢复能力” 而设计的,解决了 “内存数据页未刷盘时宕机” 的问题(避免数据丢失);
  • binlog 是 MySQL Server 层为了实现 “跨存储引擎的复制和恢复” 而设计的,解决了 “数据同步到从库” 或 “基于时间点的全量恢复” 问题。

实际中,两者通过 “两阶段提交”(prepare + commit)保证一致性:事务提交时,先写 redo log 的 prepare 阶段,再写 binlog,最后写 redo log 的 commit 阶段。这样即使中途宕机,也能通过两个日志的状态判断事务是否需要最终提交。

4.7 总结

对比维度redo logbinlog
所属层次InnoDB 存储引擎层MySQL Server 层
日志类型物理日志(数据页修改)逻辑日志(SQL 逻辑变更)
写入方式循环写(固定大小,覆盖旧日志)追加写(文件递增,不覆盖)
核心作用保证事务持久性(崩溃恢复)主从复制、时间点恢复
适用存储引擎仅 InnoDB所有存储引擎