mysql5.5之后引入的半同步机制。
默认的异步同步是 主服务器把binlog扔到从服务器后就不管了 不管从服务器是否接受到。
半同步是 至少有一台从服务器接受到主服务器binlog日志并且应用到自己的relaylog中,然后给主服务器反馈 告诉已接受完毕 ,这时主服务器才返回给当前session操作完成。
当超时(rpl-semi-sync-master-timeout 参数默认 10000毫秒 =10秒)情况时,主服务器会切换到异步复制模式,直到有一台从服务器追上进度。
--1、安装半同步插件
#主服务器#
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected (0.37 sec)
mysql> set global rpl_semi_sync_master_enabled=1;
Query OK, 0 rows affected (0.03 sec)
#从服务器#
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.37 sec)
mysql> set global rpl_semi_sync_slave_enabled=1;
Query OK, 0 rows affected (0.07 sec)
--2、配置参数
#主服务器参数配置 my.cnf#
#开启半同步#
rpl_semi_sync_master_enabled=1
#超时(rpl-semi-sync-master-timeout 参数默认 10000毫秒 =10秒)情况时,主服务器会切换到异步复制模式,直到有一台从服务器追上进度#
rpl_semi_sync_master_timeout=10000
#是否每个事务提交都都要等待slave的返回型号,如果slave掉队 追赶上master日志时 可自动的开启半同步方式。参数默认开启#
rpl_semi_sync_master_wait_no_slave=1
#5.7新增 设置传输binlog时的 事务提交方式 默认after_sync,参考 最后的“附1:两阶段提交 2pc 内部xa”#
#AFTER_SYNC(the default):即在主服务器的执行一次sync 提交binlog后 等待从服务器的relay log写入并应用后反馈,之后再commit存储引擎事务(innodb的redo log),最后返回会话操作完成#
#AFTER_COMMIT:即在主服务器的commit存储引擎事务(innodb的redo log)后,等待从服务器的relay log写入并应用后反馈,最后返回会话操作完成#
rpl_semi_sync_master_wait_point= AFTER_SYNC
#调试级别 默认32#
rpl_semi_sync_master_trace_level=32
#从服务器参数配置 my.cnf#
#开启半同步#
rpl_semi_sync_slave_enabled=1
#调试级别 默认32#
rpl_semi_sync_slave_trace_level=32
--3、从服务器重启复制的io线程
mysql> stop slave io_thread;
Query OK, 0 rows affected (0.00 sec)
mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)
--4、重启主从服务器查看半同步插件是否加载成功和设置的参数
#主服务器#
mysql> show plugins;
| rpl_semi_sync_master | ACTIVE | REPLICATION | semisync_master.so | GPL |
mysql> show variables like '%semi%';
+-------------------------------------------+------------+
| Variable_name | Value |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled | ON |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_for_slave_count | 1 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_SYNC |
+-------------------------------------------+------------+
6 rows in set (0.06 sec)
#从服务器#
mysql> show plugins;
| rpl_semi_sync_slave | ACTIVE | REPLICATION | semisync_slave.so | GPL |
mysql> show variables like '%semi%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
2 rows in set (0.06 sec)
--5、查看半同步运行状态
#主服务器#
mysql> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 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 | //从服务器确认的成功提交数量
+--------------------------------------------+-------+
14 rows in set (0.03 sec)
#从服务器#
mysql> show global status like '%semi%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON | //是否开启半同步复制的状态
+----------------------------+-------+
1 row in set (0.00 sec)
--6、测试:模拟从半同步到异步复制的转换
--从服务器停止io_thread线程模拟从半同步到异步复制的转换
#从服务器停止io_thread线程#
mysql> stop slave io_thread;
Query OK, 0 rows affected (0.02 sec)
#从服务器查看无半同步,现在为异步复制#
mysql> show global status like '%semi%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | OFF |
+----------------------------+-------+
1 row in set (0.00 sec)
--主服务器
#主服务器删除一条数据#
mysql> delete from tttt;
Query OK, 4 rows affected (0.08 sec)
#提交需要10秒 因为rpl_semi_sync_master_timeout参数为10秒(10000毫秒)#
mysql> commit;
Query OK, 0 rows affected (10.00 sec)
#从服务器查看无半同步#
mysql> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 0 | //查看连接主服务器的半同步从服务器数量为0
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 3 |
| Rpl_semi_sync_master_no_times | 1 |
| Rpl_semi_sync_master_no_tx | 1 | //从服务器确认的不成功提交数量为1
| Rpl_semi_sync_master_status | OFF | //主服务器为异步复制
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 5188 |
| Rpl_semi_sync_master_tx_wait_time | 15566 |
| Rpl_semi_sync_master_tx_waits | 3 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 3 |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)
--从服务器开启io_thread线程模拟从异步复制恢复到半同步的过程
#开启io_thread线程#
mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)
#从服务器查看半同步生效#
mysql> show global status like '%semi%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+----------------------------+-------+
1 row in set (0.01 sec)
mysql> select * from tttt;
Empty set (0.00 sec)
--主服务器
#主服务器查看半同步生效#
mysql> show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 4 |
| Rpl_semi_sync_master_no_times | 1 |
| Rpl_semi_sync_master_no_tx | 1 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 5188 |
| Rpl_semi_sync_master_tx_wait_time | 15566 |
| Rpl_semi_sync_master_tx_waits | 3 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 3 |
+--------------------------------------------+-------+
14 rows in set (0.01 sec)
附1:两阶段提交 2pc 内部xa
--两阶段提交
1、prepare阶段:存储引擎(innodb redo)事务 redo写完 但未提交 返回OK状态
写入二进制日志的顺序和存储引擎(innodb redo)事务准备顺序一致
2、提交阶段:以下三个步骤 并且每个步骤都有一个队列(会话进入空队列就是leader 负责登记进入该队列的所有会话,进入非空队列就是follower 需要等待其他会话进入)
1)flush:每个会话的事务 按照他们进入队列的顺序被 flush到binlog中
2)sync:执行一次fsync ,组提交binlog
3)commit:按照事物写入binlog的顺序 来commit存储引擎(innodb redo)事务(换句话说 存储引擎(innodb)事务的提交顺序和他们在队列登记的顺序一致)
after_sync 就是在sync阶段后 等待从服务器的反馈
after_commit 就是在commit阶段后 等待从服务器的反馈
参考:https://dev.mysql.com/doc/refman/5.7/en/replication-semisync.html
《MySQL管理之道,性能调优,高可用与监控(第2版)》
《MySQL技术内幕 InnoDB存储引擎 第2版》