一、概述
binlog/redolog/undolog 都是 msql 中的日志模块,binlog 一般被称为二进制日志 (也成为归档日志),redolog 成为重做日志,undolog 称为回滚日志。其中二进制日志是 mysql 服务层实现的,redolog 和 undolog 是引擎层实现的。
binlog 记录的数据库记录的改动日志,如:记录 ID = 2 这条记录的字段 A 加 1,它主要用户数据的同步和复制。 redolog 记录的是物理层面的改动日志,如:记录某个扇区的某个字节修改成了 1,它主要用于数据重做。 undolog 和 binlog 差不多,也是记录的逻辑日志,它主要用于 MVCC 中记录回滚。
redolog 和 undolog 只存在于 innodb 中,myisam 引擎并没有实现,这两个日志在 innodb 中统称为事务日志。但要注意的是,虽然 undolog 和 redolog 都能恢复数据,但 undolog 并不是 redolog 的逆向操作。 undolog 用于回滚,redolog 用于前滚。
关于前滚和回滚:
前滚:事务提交之后,部分数据写入了磁盘,但是还有部分数据存在脏页上,并没有写入磁盘。此时设备宕机,没有写入磁盘的数据丢失。就要依赖 redolog 来恢复这部分数据。
回滚:事务还未提交,改动并没有完全生效,但是记录已经被修改。此时设备宕机,数据是有问题的,就要依赖 undolog 回滚改动。
大致的工作模型为:

二、二进制日志 (bin log)
二进制日志是 server 层 (即 mysql) 实现的,不用引擎单独再实现。它记录了所有对数据修改的过程,属于逻辑日志。例如当我们把某个字段增加了 1,那么 binlog 就会记录一条日志,它是直接写入到文件系统的。 binlog 的主要用途是复制和同步数据,在多台设备间保持数据一致。
binlog 只会保存对数据存在更改的记录,像
select/show
这类查询类的语句是不记录的。
开启二进制日志的方法:
1 2 |
[mysqld] log-bin=[on|filename] |
在 my.cnf
文件中添加上对应的配置段即可,可以手动指定文件名。重启服务后生效。
当开启二进制日志后,mysql 数据目录就会生成对应的数据文件:
也可以在 mysql 中通过指令得到文件相关信息,如:
1 2 3 |
SHOW {BINARY | MASTER} LOGS # 查看使用了哪些日志文件 SHOW BINLOG EVENTS [IN 'log_name'] [FROM pos] # 查看日志中进行了哪些操作 SHOW MASTER STATUS # 显示主服务器中的二进制日志信息 |
三、重做日志 (redolog)
redolog 是工作在物理层,它的作用主要是为了减少磁盘开销。因为磁盘操作是极为耗时的,因此,不可能每次对数据的更改都直接写入磁盘。 redolog 的作用就是缓存起来这些数据改动 (缓存到磁盘),等缓存到达一定的数量后再统一写磁盘。
redolog 是引擎层实现的,MyISAM 没有实现这个功能,而 InooDB 实现了。
一个很生动形象的例子是 《孔乙己》,在这篇文章中,有记录到老板赊账的过程:酒店掌柜有一个粉板,专门用来记录客人的赊账记录。如果赊账的人不多,那么他可以把顾客名和账目写在板上。但如果赊账的人多了,粉板记不下了,这个时候掌柜一定还有一个专门记录赊账的账本。如果有人要赊账或者还账的话,掌柜一般有两种做法:
- 直接把账本翻出来,把这次赊的账加上去或者扣除掉;
- 另一种做法是先在粉板上记下这次的账,等打烊以后再把账本翻出来核算。
在生意红火柜台很忙时,掌柜一定会选择后者,因为前者操作实在是太麻烦了。首先,你得找到这个人的赊账总额那条记录。你想想,密密麻麻几十页,掌柜要找到那个名字,可能还得带上老花镜慢慢找,找到之后再拿出算盘计算,最后再将结果写回到账本上。
redolog 的作用实际上也就是老板赊账一样,为了提高效率,先提前把修改记录到一块地方,等到修改达到一定数量后再写入磁盘,减少磁盘写入次数。
为什么会减少磁盘写入次数呢?
假设 redolog 记录了一条日志,是说把某个扇区的值更新为 3,然后后面又来了一条日志,要修改这个扇区的值为 5,那么在这种情况下,只要把 5 写入到磁盘就行了。
redolog 和 binlog 的对比
- redolog 写入的是对磁盘的更改,binlog 写入的是对记录行的修改。
- redolog 是一个环形缓冲区,有大小限制,缓冲区满后把数据写入磁盘。而 binlog 是直接记录文件,没有文件大小限制, 大小超出后重新生成一个文件继续记录。
- redolog 是引擎层实现,binlog 是 server 层实现。
四、回滚日志 (undo log)
回滚日志主要的用途是多版本并发控制中的回滚,多个事务同时更新数据时会生成回滚日志:
图片来源:极客时间《 MySQL 实战 45 讲》。
其中 U1/U2/U3 表示的就是回滚日志,当记录要从 V4 回滚到 V1 时,要先依次通过 U3 和 U2 回滚到 V2,再通过 U1 回滚到 V1 。
四、关于二阶段提交
二阶段提交的意思是:redolog 和 binlog 都写入了之后再提交数据,确保日志数据都正常了才写入磁盘。
以下是 binlog 和 redolog 的工作流程:
写入 redolog 后,事务处于 prepare 状态,然后写入 binlog,再 commit 。
这样做的目的就是避免两个日志中的某一个没有被正确写入出现异常,一旦两个日志行为不一致,后续的同步和恢复数据就不准确。
使用 binlog 和 redolog 恢复数据
如何使用 binlog 和 redolog 来恢复数据呢,一般是以下几个过程:
- 找到最近一次的全量备份
- 从备份的时间点开始执行 binlog,重放到需要的时间点。
1F
redolog 和 binlog 都写入了之后再提交数据,确保日志数据都正常了才写入磁盘。是写入到 log buffer 还是写入到磁盘中?