MySQL——redo log 与 binlog


读这篇文章前,可以先看看前文 MySQL——update 语句执行流程,以便对整体有个大概的了解。

一、重做日志(redo log)

InnoDB 存储引擎会使用重做日志文件恢复到掉电前的时刻,以此来保证数据的完整性。
redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;

  • 采用 WAL(Write Ahead Log)策略,事务提交时,先写重做日志再修改页;
  • 每个 InnoDB 存储引擎至少有 1 个重做日志文件组(group),每个文件组下至少有 2 个重做日志文件(如默认的 ib_logfile0 和 ib_logfile1);
  • 可以设置多个镜像日志组,将不同的文件组放在不同磁盘上,以提高重做日志的高可用性;
  • 在日志组中每个重做日志文件大小一致,并以循环写入的方式运行;
表1 重做日志文件参数
重做日志文件参数作用大小
innodb_log_file_size指定每个重做日志文件的大小最大 512GB
innodb_log_files_in_group指定日志文件组中重做日志文件的数量默认为 2
innodb_mirrored_log_groups指定日志镜像文件组的数量默认为 1,表示只有一个日志文件组,没有镜像
innodb_log_group_home_dir指定日志文件组所在路径默认 ./ 表示在 MySQL数据库的数据目录下

下图 1 以一个重做日志文件组中有四个重做日志文件为例,每个日志文件大小最大只能 512GB。

图1 redo log 文件结构图

重做日志文件设置过大 —— 恢复时间长。
重做日志文件设置过小 —— 可能导致一个事务的日志需要多次切换重做日志文件。且会导致频繁地发生 async checkpoint,导致性能的抖动。

重做日志文件组

在每个组的第一个redo log file中,前四个块记录特定部分(2KB),之后才开始记录 log block。除了第一个 redo log file 中会记录,log group 中的其他 log file 不会记录这2KB,但是却会腾出这 2KB 的空间。

图2 redo log 写入过程
图2 redo log 写入过程

重做日志缓冲(内存中)写入磁盘的重做日志文件时,按 512 字节(一个扇区大小),因为扇区是写入的最小单位,因此可以保证写入必定是成功的。因此在重做日志的写入过程中不需要有 doublewrite

重做日志格式

在 InnoDB 存储引擎中,对于各种不同的操作有着不同的重做日志格式。到 InooDB 1.2.x 版本为止,总共定义了 51 种重做日志类型(例如下图3 insert 语句和 delete 语句写入 redo_log_body 内容是不一样的)。虽然各种重做日志类型不同,但是它们有着基本的格式,下表 2 显示了重做日志条目的结构。

表2 重做日志条目结构
redo_log_typespacepage_noredo_log_body
图3 不同重做日志格式

可以从上表 2 中看到,重做日志由 4 部分组成。

表3 重做日志条目结构解释
组成部分作用大小
redo_log_type表示重做日志类型1 字节
space表示表空间的 ID采用压缩方式,占用空间可能小于 4 字节
page_no表示页的偏移量采用压缩方式
redo_log_body表示每个重做日志的数据部分恢复时需要调用相应的函数进行解析

表空间ID + 页号 即可唯一定位需要进行修改的页。

重做日志块

redo log 是基于页的格式来记录的,innodb 的页大小默认是16KB(由 innodb_page_size变量控制),一个页中可以存放多个 redo log block 重做日志块(512B),

图4 重做日志块

redo log恢复

假如数据在 LSN:10 000 的时候宕机了,则恢复 LSN:10 000 到 LSN:13 000 范围的日志,因为此时 CP 的 LSN 为 10 000。

图5 重做日志数据恢复

刷盘时机

重做日志写入重做日志文件触发条件:

  1. 主线程中每秒会将重做日志缓冲写入磁盘的重做日文件中,不论事务是否提交。
  2. 参数 innodb_flush_log_at_trx_commit 控制,表示在提交(commit)操作时,处理重做日志的方式。
  3. 当重做日志缓冲池剩余空间小于1/2时,重做日志刷新到重做日志文件。

引发数据库刷脏页(flush)过程的情况:

  1. InnoDB 的 redo log 写满时,系统会停止所有的更新操作,把 checkpoint 往前推进(如图1),redo log 留出空间继续写。
  2. 系统内存不足时,淘汰一些数据页,如果是脏页则先刷到磁盘。
  3. MySQL 认为系统 ”空闲“ 时,只要有机会就刷一点 ”脏页“。
  4. MySQL 正常关闭时,MySQL 会把内存的脏页都 flush 到磁盘上。

二、二进制日志(binlog)

binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1 ”。其有以下三大模式。
参数设置: binlog_format

  • Statement,基于 SQL 语句复制(statement-based replication, SBR)(默认)
    二进制文件记录的是日志的逻辑 SQL 语句。
    优点:不需要记录每一条 SQL 语句与每行的数据变化,这样子 binlog 的日志也会比较少,减少了磁盘IO,提高性能。
    缺点:在某些情况下会导致 master-slave 中的数据不一致。
  • ROW,基于行复制(row-based replication, RBR)
    不只是记录简单的 SQL 语句,而是记录表的更改情况。
    优点:只需要记录被修改的
  • Mixed,混合模式复制(mixed-based replication, MBR)

三、redo log 与 binlog 的区别

表4 redo log 与 binlog 的区别
区别redo logbinlog
所处位置不同InnoDB 引擎特有MySQL 的 server 层实现的,所有的引擎都可以使用
记录内容不同记录关于每个页的更改物理情况,即该日志是物理日志记录一个事务的具体操作内容,即该日志是逻辑日志
写入方式不同空间固定会用完,循环写入不会覆盖以前的日志,追加写入
写入时间不同在事务进行过程中,不断有重做日志条目(redo entry)被写入重做日志文件中仅在事务提交前进行提交,即只写磁盘一次,不论这时该事务多大

redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;
binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1 ”。

参考资料

[1]【图文详解】MySQL系列之redo log、undo log和binlog详解 https://cloud.tencent.com/developer/article/1801920
[2] MySQL技术内幕 InnoDB存储引擎 第2版
[2] MySQL之InnoDB存储引擎:浅谈Redo Log重做日志 https://jishuin.proginn.com/p/763bfbd65c1c

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值