在前面的文章中,我不止一次地和你提到了binlog,大家知道binlog可以用来归档,也可以用来做主备同步,但它的内容是什么样的呢?为什么备库执行了binlog就可以跟主库保持一致了呢?今天我就正式地和你介绍一下它。
毫不夸张地说,MySQL能够成为现下最流行的开源数据库,binlog功不可没。
在最开始,MySQL是以容易学习和方便的高可用架构,被开发人员青睐的。而它的几乎所有的高可用架构,都直接依赖于binlog。虽然这些高可用架构已经呈现出越来越复杂的趋势,但都是从最基本的一主一备演化过来的。
MySQL主备的基本原理
如图1所示就是基本的主备切换流程
在状态1中,客户端的读写都直接访问节点A,而节点B是A的备库,只是将A的更新都同步过来,到本地执行。这样可以保持节点B和A的数据是相同的。
当需要切换的时候,就切成状态2。这时候客户端读写访问的都是节点B,而节点A是B的备库。
在状态1中,虽然节点B没有被直接访问,但是我依然建议你把节点B(也就是备库)设置成只读(readonly)模式。这样做,有以下几个考虑:
-
有时候一些运营类的查询语句会被放到备库上去查,设置为只读可以防止误操作;
-
防止切换逻辑有bug,比如切换过程中出现双写,造成主备不一致;
-
可以用readonly状态,来判断节点的角色。
你可能会问,我把备库设置成只读了,还怎么跟主库保持同步更新呢?
这个问题,你不用担心。因为readonly设置对超级(super)权限用户是无效的,而用于同步更新的线程,就拥有超级权限。
接下来,我们再看看节点A到B这条线的内部流程是什么样的。图2中画出的就是一个update语句在节点A执行,然后同步到节点B的完整流程图。
图2中,包含了我在上一篇文章中讲到的binlog和redo log的写入机制相关的内容,可以看到:主库接收到客户端的更新请求后,执行内部事务的更新逻辑,同时写binlog。
备库B跟主库A之间维持了一个长连接。主库A内部有一个线程,专门用于服务备库B的这个长连接。一个事务日志同步的完整过程是这样的:
- 在备库B上通过change master命令,设置主库A的IP、端口、用户名、密码,以及要从哪个位置开始请求binlog,这个位置包含文件名和日志偏移量。在备库B上执行start slave命令,这时候备库会启动两个线程,就是图中的io_thread和sql_thread。其中io_thread负责与主库建立连接。
- 在备库B上执行start slave命令,这时候备库会启动两个线程,就是图中的io_thread和sql_thread。其中io_thread负责与主库建立连接。
- 主库A校验完用户名、密码后,开始按照备库B传过来的位置,从本地读取binlog,发给B。
- 备库B拿到binlog后,写到本地文件,称为中转日志(relay log)。
- sql_thread读取中转日志,解析出日志里的命令,并执行。
binlog的三种格式对比
binlog有两种格式,一种是statement,一种是row。可能你在其他资料上还会看到有第三种格式,叫作mixed,其实它就是前两种格式的混合。
mysql> CREATE TABLE `t` ( `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, `t_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `a` (`a`), KEY `t_modified`(`t_modified`) ) ENGINE=InnoDB; insert into t values(1,1,‘2018-11-13‘); insert into t values(2,2,‘2018-11-12‘); insert into t values(3,3,‘2018-11-11‘); insert into t values(4,4,‘2018-11-10‘); insert into t values(5,5,‘2018-11-09‘);
如果要在表中删除一行数据的话,我们来看看这个delete语句的binlog是怎么记录的。
注意,下面这个语句包含注释,如果你用MySQL客户端来做这个实验的话,要记得加-c参数,否则客户端会自动去掉注释。
mysql> delete from t /*comment*/ where a>=4 and t_modified<=‘2018-11-10‘ limit 1;
当binlog_format=statement时,binlog里面记录的就是SQL语句的原文。你可以用
mysql> show binlog events in ‘master.000001‘;
命令看binlog中的内容。