MySQL基于二进制日志的主从复制
一、什么是MySQL的主从复制?
MySQL可以将一个数据库设置为主库,另一个数据库设置为该主库的从库,当主库发生了变更,会同步到从库中。MySQL的主从架构,可以是星型的,也可以是线型的。
星型架构:
线型架构:
由于主从复制的延迟问题,星型架构比线型架构更常用。下文中的应用主要是以星型架构为例。
二、MySQL主从复制的方式
MySQL的复制可以分为基于二进制日志的复制和基于事务(GTID)的复制,基于二进制日志的复制方式,又可以分为基于行(ROW)的二进制日志复制方式,和基于语句(STATEMENT)的二进制日志复制方式。那么这些复制方式有什么区别呢?
基于语句的二进制日志复制,主库将变更SQL语句以及上下文记录到二进制日志中,这样的话,如果SQL语句中有不确定值的函数,例如uuid(),在从库中执行执行相同的SQL语句可能会导致不同的变更结果。现在来看一下基于语句的二进制日志,临时设置二进制日志格式为statement:set session binlog_format=statement,在库中插入一条数据:insert into novel values(4, '杯雪')。查看产生的二进制日志:mysqlbinlog --no-defaults mysql-bin.000002,日志如下所示:
基于行的二进制日志复制,主库是将每行的变更数据记录到二进制日志中,在从库中直接是对每行数据进行修改,而不用在从库中执行SQL语句,这样会更高效,并且不会导致主从数据不一致的问题。不过,这样会导致二进制日志比较大。下面是基于ROW的二进制日志:
上面的两种二进制日志复制方式,需要指定是哪个二进制日志以及相应的偏移量,来进行增量同步,如果指定错误会造成遗漏或者重复。
GTID方式,本文暂不讨论,后续会补上。
三、MySQL复制的原理
- 主库发生变更,将变更事件记录到二进制日志中
- 从库启动一个I/O线程,该线程和主库建立一个连接,并在主库上启动一个二进制转储线程,用于读取主库中的二进制日志事件,从库的I/O线程将接收到的二进制日志事件写到中继日志中。
- 从库的SQL线程从中继日志中读取事件,并更新从库。
四、基于行的二进制日志的主从复制方式实例
- 准备MySQL环境:
- 在win10,以管理员的身份启动docker,启动一个centos6.7容器:
docker run --name cnt-centos-mysql-w -itd 87de1d39ef43 /bin/bash
2. 在容器中安装并配置mysql,参考https://www.cnblogs.com/lzj0218/p/5724446.html
3. docker commit cfb8dfa6ddd8 centos-mysql,将安装mysql后的容器保存为一个镜像。
4. 用上述centos-mysql镜像,启动三个容器实例,作为一主二从:
Master:docker run --name cnt-centos-mysql-master -itd -p 7000:22 centos-mysql /bin/bash
Slave1:ocker run --name cnt-centos-mysql-slave1 -itd -p 7001:22 centos-mysql /bin/bash
Slave2:docker run --name cnt-centos-mysql-slave2 –itd –p 7002:22 centos-mysql /bin/bash
5. 在主库创建一个数据库,创建表,插入数据
在启动mysql服务的时候,如果报“”,可以尝试使用rm -fr /var/lib/mysql/*这个命令来解决,重新初始化数据库。
- 配置主库,vi /etc/my.cnf
- 配置从库
- 将主库的初始数据,初始化到从库中
备份主数据库:
将备份脚本拷贝到从库中:
初始化从库:
- 在主库上建立复制用户并授权:
建立对应网段的复制用户:
给repl用户授予复制权限:
- 在从库上配置复制链路:
其中,master_log_file的取值,来自备份的脚本,如下:
启动复制链路,并查看复制链路转态信息:
- 测试
在主库中插入数据:
查询从库,可以看到刚插入的数据已经从主库同步到从库中了: