并行复制的原理
在普通的主从复制架构中,slave服务器上有两个线程:IO线程和SQL线程。IO线程负责接收master的二进制日志(准确的说是二进制日志的event),SQL线程负责应用二进制日志(准确的说是relay-log)。
在MySQL5.6版本中的并行复制中(需开启并行复制功能),SQL线程变为coordinator线程,判断是否可以并发执行:
- 如可以并行执行,选择worker线程执行二进制日志
- 如不可并行执行,是DDL或是跨schema的操作,则等待所有的worker线程执行完成之后再执行当前日志
coordinator线程不仅仅可以将日志发送给worker线程,也可以回放日志,但是并行的操作都会交给worker线程来完成。
server6(slave)上:
[root@server6 ~]# mysql -p
mysql> show processlist;
修改配置文件:
[root@server6 ~]# vim /etc/my.cnf
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON
[root@server6 ~]# /etc/init.d/mysqld restart
mysql> show processlist;
Mysql半同步
- 正常的复制为:事务一(t1) 写入binlog buffer;dumper 线程通知slave有新的事务t1;binlog buffer 进行checkpoint;slave的io线程接收到t1并写入到自己的的relay log;slave的sql线程写入到本地数据库。 这时,master和slave都能看到这条新的事务,即使master挂了,slave可以提升为新的master。
- 异 常的复制为:事务一(t1)写入binlog buffer;dumper 线程通知slave有新的事务t1;binlog buffer 进行checkpoint;slave因为网络不稳定,一直没有收到t1;master 挂掉,slave提升为新的master,t1丢失。
- 很大的问题是:主机和从机事务更新的不同步,就算是没有网络或者其他系统的异常,当业务并发上来时,slave因为要顺序执行master批量事务,导致很大的延迟。
为了弥补以上几种场景的不足,mysql从5.5开始推出了半同步。即在master的dumper线程通知slave后,增加了一个ack,即是否成功 收到t1的标志码。也就是dumper线程除了发送t1到slave,还承担了接收slave的ack工作。如果出现异常,没有收到ack,那么将自动降 级为普通的复制,直到异常修复。
主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所 以,半同步复制最好在低延时的网络中使用。
1.主库端加载mater模块(server5)
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so'; 在master上安装这个插件
(--删除插件的方法 mysql > uninstall plugin rpl_semi_sync_master;)
mysql> set global rpl_semi_sync_master_enabled=ON; #激活半同步复制
--安装OK后,主上会多几个参数
mysql> show variables like '%semi%'; ##环境变量
rpl_semi_sync_master_enabled ON #表示半同步开启
rpl_semi_sync_master_timeout | 10000 | #默认主等待从返回信息的超时间时间,10秒
rpl_semi_sync_master_trace_level | 32 | #监控
rpl_semi_sync_master_wait_no_slave | ON | # 是否允许每个事物的提交都要等待slave的信号.on为每一 个事物都等待
2.server6上安装插件(slave)
mysql> stop slave;
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so'; #安装slave插件
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so'; #安装master插件
mysql> set global rpl_semi_sync_master_enabled=ON; #激活半同步
mysql> set global rpl_semi_sync_slave_enabled=ON;
mysql> show variables like '%semi%'; #查看状态
mysql> start slave;
mysql> stop slave io_thread; #关闭IO线程
mysql> start slave io_thread; #开启IO线程
mysql> show status like '%rpl_semi_sync%';
3.在master查看状态
mysql> show status like '%rpl_semi_sync%';
| Rpl_semi_sync_master_clients | 1 | --有一个从服务器启用半同步复制
| Rpl_semi_sync_master_net_avg_wait_time | 0 | --master等待slave回复的平均等待时间。单位毫秒
| Rpl_semi_sync_master_net_wait_time | 0 | --master总的等待时间。单位毫秒
| Rpl_semi_sync_master_net_waits | 0 | --master等待slave回复的总的等待次数
| Rpl_semi_sync_master_no_times | 0 | --master关闭半同步复制的次数
| Rpl_semi_sync_master_no_tx | 0 | --master 等待超时的次数
| Rpl_semi_sync_master_status | ON | --标记master现在是否是半同步复制状态
| Rpl_semi_sync_master_timefunc_failures | 0 | --master调用时间(如gettimeofday())失败的次数
| Rpl_semi_sync_master_tx_avg_wait_time | 0 | --master花在每个事务上的平均等待时间
| Rpl_semi_sync_master_tx_wait_time | 0 | --master花在事物上总的等待时间
| Rpl_semi_sync_master_tx_waits | 0 | --master事物等待次数
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 | --后来的先到了,而先来的还没有到的次数
| Rpl_semi_sync_master_wait_sessions | 0 | --当前有多少个session因为slave回复而造成等待
| Rpl_semi_sync_master_yes_tx | 0 | --标记slave是否在半同步状态
4.测试
1)master上:
mysql> show databases;
mysql> use westos;
mysql> insert into usertable values('user3','222');
mysql> show global status like 'rpl_semi_sync%_yes_tx';
Rpl_semi_sync_master_yes_tx | 1 | --表示这次 事物成功从slave返回一次确认信号
2)模拟错误,把slave上的IO线程停掉!
mysql> stop slave io_thread; (slave上)
再回到master上测试
mysql> insert into usertable values('user4','777');
--这次插入一个值需要等待10秒(默认的等待时间)!
再把slave上的IO线程开启,查看数据发现刚才slave关闭期间的那几条数据还是会自动复制过来,数据又回到一致
mysql> start slave io_thread;
mysql> select * from westos.usertable;
如果是把slave上的mysql停掉,再次把slave启动,看到半同步复制没启来,是异步模式,需要重新把同步模式再启起来就可以了.