MySQL 半同步复制
MySQL通过复制(Replication)实现存储系统的高可用。目前,MySQL支持的复制方式有:
- 异步复制(Asynchronous Replication):原理最简单,性能最好。但是主备之间数据不一致的概率很大。
- 半同步复制(Semi-synchronous Replication):相比异步复制,半同步复制牺牲了一定的性能,提升了主备之间数据的一致性(有一些情况还是会出现主备数据不一致)。
- 组复制(Group Replication):基于Paxos算法实现分布式数据复制的强一致性。只要大多数机器存活就能保证系统可用。相比半同步复制,Group Replication的数据一致性和系统可用性更高。
半同步复制介绍
默认情况下MySQL是异步复制,异步复制可以提供最佳的性能。主库把binlog日志发送给从库,从库IO线程接收存入中继日志,SQL线程执行二进制日志以同步主库数据。这一过程并不会验证从库是否接收完毕,也就意味着有可能出现当主服务器或从服务器端发生故障的时候,有可能从服务器没有接收到主服务器发送过来的binlog日志,这就会造成主服务器和从服务器的数据不一致,甚至在恢复时造成数据的丢失。
MySQL5.5之后支持半自动同步模式,该模式可以确保从服务器接收完主服务器发送的binlog日志文件并写入到自己的中继日志relay log里,然后会给主服务器一个反馈,告诉主服务器已经接收完毕,这时主服务线程才返回给当前session告知操作完成。
当出现超时情况是,主服务器会暂时切换到异步复制模式,直到至少有一个从服务器从及时收到信息为止。
从MySQL5.5开始,增加了relay_log_recovery参数,这个参数的作用是:当slave从库宕机后,假如relay.log损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的relay-log,并且重新从master上获取日志,这样就保证了relay-log的完整性。默认情况下该功能是关闭的,将relay_log_recovery的值设置为1时,可在slave从库上开启该功能,建议开启。
半同步复制与异步复制的切换:
半同步复制的工作原理就是当slave从库IO_Thread线程将binlog日志接收完毕之后,要给master主库一个确认,如果rpl_semi_sync_master_timeout=10000 (10秒)超过10秒未收到slave从库的接受确认信号,那么就会自动切换为传统的异步复制模式。
MySQL支持两种略有不同的半同步复制:AFTER_SYNC和AFTER_COMMIT(受rpl_semi_sync_master_wait_wait_point控制),MySQL5.7.3开始支持配置半同步复制等待Slave应答的个数:rpl_semi_sync_master_wait_slave_count 。
- AFTER_SYNC: 日志复制到Slave之后,Master再commit。
- 所有在master上commit的事务都已经复制到slave。
- 所有已经复制到slave的事务在master不一定commit了(比如,master将日志复制到slave之后,在commit之前宕机了)
- AFTER_COMMIT:Master commit之后再将日志复制到Slave。
- 所有master上commit的事务不一定复制到slave。(比如,master commit之后,还没来得及将日志复制到slave就宕机了)
- 所有已经复制到slave的事务在master上一定commit了。
注意:
半同步复制模式必须在主服务器和从服务器端同时开启,否则主服务器默认使用异步复制模式。
MySQL半同步复制配置
首先安装两台MySQL,我这里提供了两台安装了MySQL服务的虚机
- master:192.168.204.128
- slave:192.168.204.129
这是在异步复制的基础上配置的MySQL 主从复制
master配置
在Master数据库安装半同步复制插件:
mysql>INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so
;
设置Master上开启半同步复制和超时时间:
mysql>SET GLOBAL rpl_semi_sync_master_enabled = 1;
mysql>SET GLOBAL rpl_semi_sync_master_timeout=1000
重启生效需要修改 /etc/my.cnf 配置文件
[mysqld]
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000查看配置是否成功:
mysql>SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';
- 参数说明:
- rpl_semi_sync_master_enabled = 1,表示在master上已经开启了半同步复制模式;
- rpl_semi_sync_master_timeout = 10000,表示如果主库在某次事务中的等待时间超过10000毫秒,则降级为异步复制模式,不在等待slave从库。如果主库再次探测到slave从恢复了,则会自动切换回半同步复制模式;
- rpl_semi_sync_master_wait_no_slave ,表示是否允许master每个事务提交后都要等待slave的接收确认信号。默认为ON,即每一个事务都会等待。如果为OFF,则slave追赶上之后,也不会开启半同步复制模式,需要手工开启;
- rpl_semi_sync_master_trace_level = 32,指用于开启半同步复制模式时的调试级别,默认为32,可以看出,在配置Master的时候,只设置了1,其他的都采取的默认设置。
Slave配置
- 在Slave数据库安装半同步复制插件:
mysql>INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
设置Slave上开启半同步复制:
mysql>SET GLOBAL rpl_semi_sync_slave_enabled = 1;
修改 /etc/my.cnf 配置文件:
[mysqld]
rpl_semi_sync_slave_enabled = 1查看配置是否成功:
mysql>SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';
- 参数说明:
- rpl_semi_sync_slave_enabled = 1,表示在slave上已经开启了半同步复制模式;
- rpl_semi_sync_slave_trace_level = 32,指用于开启半同步复制模式时的调试级别,默认为32。
- 在Slave数据库安装半同步复制插件:
为Slave指定Master
重启master和slave mysql服务
service mysql restart
- 查看master状态
mysql> show master status\G;
*************************** 1. row ***************************
File: mysql-bin.000006
Position: 120
Binlog_Do_DB:
Binlog_Ignore_DB: mysql,information_schema
Executed_Gtid_Set:
1 row in set (0.00 sec)
ERROR:
No query specified
- 为Slave指定Master:
- 首先关闭Slave的半同步复制
stop slave
- 为Slave指定Master
mysql>change master to master_host='192.168.204.128',master_user='root',master_password='123456',master_log_file='mysql-bin.000006', master_log_pos=120;
- 开启Slave的半同步复制
start slave
- 首先关闭Slave的半同步复制
场景模拟
半同步复制与异步复制切换
查看master 半同步复制状态
show status like '%Rpl_semi_sync_master_status%';
关闭slave同步,停止IO接收binlog日志
stop slave
在master 插入一条数据,可以明显看到停顿了一会,这是在等待slave响应,slave一直没有响应,超时后自动切为异步复制
show status like '%Rpl_semi_sync_master_status%';
开启slave,有能切换为半同步复制
同步报错演示
在master新建一张表 test
create table test(id int);在slave 把这张表删了
drop table test;在master 插入一条数据
- slave 同步报错
- 查看 master 状态
是开启的,因此没有将半同步复制模式转化为异步复制模式,可以看出半同步复制模式跟IO_Thread是有直接关系的,但跟SQL_THREAD没有关系。
总结:
1. slave从库接收完二进制日志后给master主库一个确认,但是他不会管relay-log中继日志是否执行完毕。
2. 在通常情况下,由于异步复制模式不需要等待从服务器的响应,其速度较半同步复制模式要快,吞吐率要高,在数据进行更新、插入、删除的时候其速度要高于半同步复制模式。但是,半同步复制模式有利于数据的一致性,对于一些数据一致性要求较高的,网络波动较小的可以采用半同步复制模式。