半同步复制:
插件由Google提供的。
主库在提交事务时,在客户端接收到查询结束反馈前必须保证二进制日志已经传输到至少一台备库上。
从库的IO线程在接受完binlog并写入到自己的relaylog后(不管realylog是否执行完),要给主库一个确认,这样主库线程才返回给当前session告知操作完成。
如果备库一直没有回应已收到事件,主库会自动转化为异步复制模式,后期若发现从库恢复后,主从又会自动切换成半同步。
半同步必须在master和slave上都启用才能生效,否则还是按照异步复制模式进行的。
插件:
semisync_master.so 【在主库上安装】
semisync_slave.so 【在从库上安装】
MySQL5.6 上安装方式:
假设目前主从关系已经配置好,下面开始开启半同步即可。
【主库】
> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
> set global rpl_semi_sync_master_enabled=ON;
> set global rpl_semi_sync_master_timeout = 1000; ### 单位毫秒。这里1000就表示1秒
> set global rpl_semi_sync_master_wait_no_slave = ON;
> show variables like '%semi%';
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled | ON |
| rpl_semi_sync_master_timeout | 1000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_no_slave | ON |
+------------------------------------+-------+
加配置文件:
rpl_semi_sync_master_enabled = ON
rpl_semi_sync_master_timeout = 1000
rpl_semi_sync_master_wait_no_slave = ON
【从库】
> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
> set global rpl_semi_sync_slave_enabled=ON;
> show variables like '%semi%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
加配置文件:
rpl_semi_sync_slave_enabled = ON
在初次加载插件后,mysql会自动将该插件记录到mysql.plugin表中,下次启动自动加载该插件。因此不需要在配置文件里加上加载semisync的插件(但是配置文件里面还是要写上是否启用这个semi插件的)。
然后,在从库执行 stop slave; start slave ; 即可启用半同步的插件。
从库状态:
> show global status like '%rpl%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+----------------------------+-------+
主库状态:
> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 | ### 1说明有1台从库目前是半同步状态
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 0 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 0 |
| Rpl_semi_sync_master_tx_wait_time | 0 |
| Rpl_semi_sync_master_tx_waits | 0 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 0 |
+--------------------------------------------+-------+
半同步涉及的参数:
> show VARIABLES like '%semi%sync%';
+------------------------------------+---------+
| Variable_name | Value |
|------------------------------------+---------|
| rpl_semi_sync_master_enabled | OFF |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_slave_enabled | OFF |
| rpl_semi_sync_slave_trace_level | 32 |
+------------------------------------+---------+
rpl_semi_sync_master_timeout
单位毫秒,默认10000毫秒,即10秒钟。
从节点发现从库在XX秒钟没有回应,则转为异步复制方式,不再等待从库。如果主库再次探测到从库恢复了,则自动再次回到半同步复制方式。
【注意这个参数不要设置太大,太大的话,master会直到超时才转换为异步复制模式,这样假如当前有事务要提交则要等超时结果才能执行提交。】
rpl_semi_sync_master_trace_level
调试级别,保持默认的32即可。
1 = general level (for example, time function failures)
16 = detail level (more verbose information)
32 = net wait level (more information about network waits)
64 = function level (information about function entry and exit)
rpl_semi_sync_master_wait_no_slave
默认是ON。表示master每个事务提交后都要等待slave的接收确认信号。如果为OFF则slave追赶上后,master也不会自动回到半同步模式,需要手工开启。
rpl_semi_sync_slave_enabled
slave上是否开启半同步复制模式。【这是配置在从节点上的,当然如果在主节点开启也不会有啥报错】
rpl_semi_sync_slave_trace_level
调试级别,保持默认的32即可。
1 = general level (for example, time function failures)
16 = detail level (more verbose information)
32 = net wait level (more information about network waits)
64 = function level (information about function entry and exit)
其他:
此外,启动半同步也会在mysql的日子里面留下记录,类似“start semi-sync replication to master .....”
例1:半同步和异步的切换:
在slave上执行stop slave io_thread;然后执行show slave status like '%semi%';可以看到半同步变为了OFF状态。
10秒钟后,到master上执行SHOW GLOBAL STATUS LIKE '%semi%';可以半同步的很多状态已经改变了。
再到slave上执行start io_thread;可以发现半同步有启用状态了。
例2:验证半同步与SQL线程无关
在slave上drop掉一个库test2,然后再master上再执行drop database test2;到slave上查看可以看到同步报错了,但是show status like '%semi%';发现半同步状态还是ON的,并没有切换到异步复制。
也就是说:半同步复制跟io_thread有直接关系,跟sql_thread没有关系。半同步复制中,slave接收到master传来的binlog后给master一个确认,但不管中继日志是否执行完。
例3:半同步超时设置太大的缺点
在master上修改rpl_semi_sync_master_timeout = 200000; 修改降级为异步的超时时长为差不多3分钟。
在slave上执行 stop slave io_thread; 停止半同步复制,模拟网络抖动造成从库暂时不可达。
在maser上执行如下命令:
> use test;
> begin;
> update t set name='ccd' wherer id=3;
> SELECT * FROM t;
> commit;
会发现commit要好久才能返回成功(差不多3分钟)。
这是因为半同步复制环境中,master要等slave的确认消息,而上面我们模拟slave宕机了,半同步切换异步复制要等到超时时间结束才降级,这就导致commit变慢了。