Java 杂谈JavaMySQL

一文带你看懂binlog和redo log

2019-05-27  本文已影响4人  shysheng

在介绍binlog和redolog之前,有必要先简单介绍一下MySQL的逻辑架构。总体上来说,MySQL可以分为server层和engine层两部分,如下图所示:

image

其中server层包括连接池、查询缓存、分析器、优化器等部分,MySQL的大多数核心服务都在这一层,而engine层就是其插件式的存储引擎,主要负责数据的存储和读取。

1.binlog

1.1binlog作用

我们今天要讲的binlog就是server层产生的日志,因此你知道,不管你使用的是哪一种存储引擎,都会产生binlog。那问题来了,binlog有什么用呢?

要知道它能「做什么」,需要先知道它「是什么」。简单来说,binlog其实就是记录了MySQL对数据库执行更改的所有操作,因此很显然,它可以用来做数据归档和数据恢复。

1.2binlog格式

在MySQL5.1之前,所有的binlog都是基于SQL语句级别的。但是应用这种格式的binlog进行数据恢复时,如果SQL语句带有rand或uuid等函数,可能导致恢复出来的数据与原始数据不一致。因此从5.1版本开始,MySQL引入了binlog_format参数,该参数有三种可选值:statement、row和mixed:

我们可以通过这条语句来查看MySQL当前的binlog格式:

image

1.3binlog内容 —— statement格式

为了查看binlog的具体内容,我们先创建一张表并对它进行初始化:

CREATE TABLE `t` (
  `id` int(10) NOT NULL auto_increment,
  `a` int(10) DEFAULT NULL,
  `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

insert into t values(null, 1,'2019-05-01');
insert into t values(null, 2,'2019-05-02');
insert into t values(null, 3,'2019-05-03');

查看当前binlog文件列表:

show master logs;
image

查看当前正在写入的binlog文件:

show master status;
image

查看binlog文件内容:

show binlog events in 'mysql-bin.000006';
image

可以看到,我们执行的insert语句被包裹在一个事务当中,同时binlog原原本本记录了我们的SQL语句。除此之外,我们还发现了另外一些东西:

1.4binlog内容 —— row格式

执行以下语句将binlog格式切换为row,看看row格式下的binlog有何不同:

set session binlog_format = 'row';

插入一条新数据:

insert into t values (null, 4, '2019-05-04');

查看binlog如下:

image

可以发现,变化在于第3行和第4行,Intvar和Query两个事件变成了Tablemap和Writerows。但是从这些信息中我们只能知道该事务对表test.t做了插入操作,确并不知道插入的具体数据是什么。

还好我们有mysqlbinlog工具,借助它我们可以一窥究竟。

这里有一点需要说明的是,mysqlbinlog不是MySQL数据库的语法,而只是客户端提供的一个工具,因此不需要登录数据库!!!不需要!!!说来惭愧,这个问题困扰了我好久,怎么就一直提示我语法错误呢?o(╯□╰)o

image

另外执行mysqlbinlog命令必须指定binlog文件的具体路径,笔者使用的是5.7版本,在该版本中,binlog存储路径的默认配置为log-bin=mysql-bin。可是mysql-bin具体哪个路径呢?这个也困扰了我一段时间,其实很简单,find一下就知道了。

image

好,现在切到该目录下执行命令,重点关注红框中的内容。不难发现,与statement模式记录完整SQL语句不通,在row模式下,binlog记录的表中每个字段的值。

image

1.5binlog内容 —— mixed格式

前面提到,在mixed模式下,MySQL默认仍然采用statement格式进行记录,但是一旦它判断可能会有数据不一致的情况发生,则会采用row格式来记录,大家可以自行进行试验查看。

2.redo log

在binlog日志文件目录下,我们还发现了这两个文件:

image

事实上这就是我们接下来要讲的redo log,也就是重做日志,它是InnoDB引擎特有的,记录了InnoDB引擎下的事务日志。

2.1redo log作用

同样,我们首先要搞明白的是,已经有binlog了,为什么还需要redo log。

因为两者分工不同。binlog主要用来做数据归档,但是它并不具备崩溃恢复的能力,也就是说如果你的系统突然崩溃,重启后可能会有部分数据丢失,而redo log的存在则可以完美解决这个问题。

2.2redo log构成

默认情况下,每个InnoDB引擎至少有一个重做日志组,每个组下至少有两个重做日志文件,例如上文提到的iblogfile0和iblogfile1。重做日志组中的每个日志文件大小一致且循环写入,也就是说先写iblogfile0,写满了之后写iblogfile1,一旦iblogfile1也写满了,则继续写iblogfile0。显然,如果没有任何保护措施,这种机制会导致之前写入ib_logfile0的内容被覆盖。因此一旦redo log写满,MySQL将不得不停下所有更新操作来刷脏页,这也是我们在为什么你的SQL执行很慢中提到的一点。

2.3redo log内容

binlog有三种格式,并且每种格式我们都可以具体查看其内容,那么redo log的内容怎么查看呢?

目前好像并没有什么办法可以以人类可以理解的方式查看redo log,原因在于与binlog记录的是逻辑日志不同,redo log记录的是对数据页更改的物理日志,比如类似「将第8页、第1行、第6个位置改成666」这种,下图是我用hexdump查看ib_logfile0的结果,其中红框标出来的部分是插入一条数据后新增的日志文件。

image

3.总结

本文从几个方面简单介绍了一下binlog和redo log,现在简单总结一下两者的不同点:

更多技术文章,咱们公众号见,我在公众号里等你~

image.png
上一篇 下一篇

猜你喜欢

热点阅读