所谓半同步机制,master节点只要确认有至少一个slave节点接收到了事物,即可向客户端返回操作成功的信息,master节点甚至不需要等待slave节点也成功执行完这个事物,只要至少有一个slave节点接收到这个事物,并且将之成功写入到本地的中继日志文件,就算成功。
一,MySQL的半同步复制是以插件形式提供,查看目前是否安装
-
(root@localhost) [(none)]> show plugins;
-
+----------------------------+----------+--------------------+---------+---------+
-
| Name | Status | Type | Library | License |
-
+----------------------------+----------+--------------------+---------+---------+
-
| binlog | ACTIVE | STORAGE ENGINE | NULL | GPL |
-
| mysql_native_password | ACTIVE | AUTHENTICATION | NULL | GPL |
-
| sha256_password | ACTIVE | AUTHENTICATION | NULL | GPL |
-
| MEMORY | ACTIVE | STORAGE ENGINE | NULL | GPL |
-
| InnoDB | ACTIVE | STORAGE ENGINE | NULL | GPL |
-
| INNODB_TRX | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_LOCKS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_LOCK_WAITS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_CMP | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_CMP_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_CMPMEM | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_CMPMEM_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_CMP_PER_INDEX | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_CMP_PER_INDEX_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_BUFFER_PAGE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_BUFFER_PAGE_LRU | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_BUFFER_POOL_STATS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_TEMP_TABLE_INFO | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_METRICS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_FT_DEFAULT_STOPWORD | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_FT_DELETED | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_FT_BEING_DELETED | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_FT_CONFIG | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_FT_INDEX_CACHE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_FT_INDEX_TABLE | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_SYS_TABLES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_SYS_TABLESTATS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_SYS_INDEXES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_SYS_COLUMNS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_SYS_FIELDS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_SYS_FOREIGN | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_SYS_FOREIGN_COLS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_SYS_TABLESPACES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_SYS_DATAFILES | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| INNODB_SYS_VIRTUAL | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
-
| MRG_MYISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
-
| PERFORMANCE_SCHEMA | ACTIVE | STORAGE ENGINE | NULL | GPL |
-
| CSV | ACTIVE | STORAGE ENGINE | NULL | GPL |
-
| MyISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
-
| ARCHIVE | ACTIVE | STORAGE ENGINE | NULL | GPL |
-
| partition | ACTIVE | STORAGE ENGINE | NULL | GPL |
-
| FEDERATED | DISABLED | STORAGE ENGINE | NULL | GPL |
-
| BLACKHOLE | ACTIVE | STORAGE ENGINE | NULL | GPL |
-
| ngram | ACTIVE | FTPARSER | NULL | GPL |
-
+----------------------------+----------+--------------------+---------+---------+
-
44 rows in set (0.00 sec)
二,本例目前还没有安装,查看plugin目录位置
-
(root@localhost) [(none)]> show variables like 'plugin_dir';
-
+---------------+------------------------------+
-
| Variable_name | Value |
-
+---------------+------------------------------+
-
| plugin_dir | /usr/local/mysql/lib/plugin/ |
-
+---------------+------------------------------+
-
1 row in set (0.00 sec)
三,在plugin目录下有两个与半同步相关的插件
-
[root@oracle11gtest plugin]# ls -al semisync*
-
-rwxr-xr-x 1 root root 688816 Feb 6 19:44 semisync_master.so
-
-rwxr-xr-x 1 root root 150555 Feb 6 19:44 semisync_slave.so
四,在master端安装semisync_master.so,在slave端安装semisync_slave.so
-
(root@localhost) [(none)]> install plugin rpl_semi_sync_master SONAME 'semisync_master.so' ;
-
Query OK, 0 rows affected (0.04 sec)
-
-
(root@localhost) [(none)]> install plugin rpl_semi_sync_slave SONAME 'semisync_slave.so';
-
Query OK, 0 rows affected (0.01 sec)
五,安装好之后分别用show plugins命令check下六,修改主端半同步相关参数
-
(root@localhost) [(none)]> show variables like '%rpl_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_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.00 sec)
-
-
(root@localhost) [(none)]> set global rpl_semi_sync_master_enabled=1; ---用于控制是否在主端启用半同步复制,
-
Query OK, 0 rows affected (0.00 sec)
-
-
(root@localhost) [(none)]> set global rpl_semi_sync_master_timeout=3000; ---用于指导主端等待slave响应的时间,单位是毫秒,我这里设为3秒
-
Query OK, 0 rows affected (0.00 sec)
七,修改slave端半同步相关参数
-
(root@localhost) [(none)]> show variables like '%rpl_semi_sync%';
-
+---------------------------------+-------+
-
| Variable_name | Value |
-
+---------------------------------+-------+
-
| rpl_semi_sync_slave_enabled | OFF |
-
| rpl_semi_sync_slave_trace_level | 32 |
-
+---------------------------------+-------+
-
2 rows in set (0.01 sec)
-
-
(root@localhost) [(none)]> set global rpl_semi_sync_slave_enabled=1; ---用于控制是否在slave端启用半同步复制,
-
Query OK, 0 rows affected (0.00 sec)
八,重启slave节点的io_thread线程,目的是让slave重新连接master,注册成为半同步的slave身份
-
(root@localhost) [(none)]> stop slave io_thread;
-
Query OK, 0 rows affected (0.01 sec)
-
-
(root@localhost) [(none)]> start slave io_thread;
-
Query OK, 0 rows affected (0.00 sec)
九,测试
在master端插入数据
insert into oms3.gl values('zg');
-
insert into oms3.gl values('gl');
查看slave是否应用
-
(root@localhost) [(none)]> select * from oms3.gl;
-
+------+
-
| abcd |
-
+------+
-
| test |
-
| gl |
-
| zg |
-
+------+
查看master相关变量
-
(root@localhost) [mysql]> show status like 'rpl_semi_sync%';
-
+--------------------------------------------+-------+
-
| 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 | 417 |
-
| Rpl_semi_sync_master_tx_wait_time | 834 |
-
| Rpl_semi_sync_master_tx_waits | 2 |
-
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
-
| Rpl_semi_sync_master_wait_sessions | 0 |
-
| Rpl_semi_sync_master_yes_tx | 1 |
-
主要关注四个参数:Rpl_semi_sync_master_status ---表示当前master节点是否启用了半同步模式
Rpl_semi_sync_master_no_tx ---表示当前未成功发送到slave节点的事物数量
Rpl_semi_sync_master_yes_tx ---表示当前已成功发送到slave节点的事物数量
Rpl_semi_sync_master_clients---表示当前处于半同步模式的slave节点数量
5.7的半同步机制变化
一:rpl_semi_sync_master_wait_slave_count参数设置有几个slave接收到了binlog才成功返回客户端请求,缺省是一台,但不可以指定是具体哪台。
二:rpl_semi_sync_master_wait_point 参数,它有两种选择:
AFTER_SYNC(5.7缺省值,5.6中无此选项)
主库把每一个事务写到二进制日志并且发送给从库,主库在等待从库写到自己的relay-log里的确认信息,在接到确认信息后,主数据库把事务写到存储引擎里并把相应结果反馈给客户端。
AFTER_COMMIT(5.6缺省值)
主库把每一个事务写到二进制日志并且发送给从库,然后马上就把事务写到存储引擎里;主库在等待从库写到自己的relay-log里的信息确认后,主库把相应结果反馈给客户端。
他们俩个的区别:
AFTER_COMMIT模式的弊端在于,虽然主库一直没有告诉提交事务的客户端事务已经成功(在从库成功确认前)但是实际已经提交了,其它客户端此时已经可以看到事务的结果了。
也就是对于事务提交者自身,的确保证了只要收到成功就一定成功了,但是其它客户端却可能存在发现事务成功了,但最后却没成功,因为数据已经到了存储引擎层。
比如A客户端执行事务将字段id从0修改为1
1.A提交事务到主库
2.主库写binlog
3.主库发送给从库,同时主库提交事务到存储引擎
此时还未收到从库确认,此时A还在等待结果,但是此时另外客户端B已经可以看到字段id为1了。
假如此时主库宕机,如果从库实际收到刚才的事务仅仅是主库未收到确认,那么此时从库的数据还是正确的也是id=1,客户端切换到从库后,都看到id=1
但是如果从库没有实际收到刚才的事务,那么此时从库上id=0,对于客户端A,这个并没有问题,因为A先前提交的事务没有收到任何反馈,所以A需要通过其它方式来确定先前事务是否成功,也就是A可以接受id=0或id=1。
但是对于客户端B来说,已经id=1的变成id=0则很可能是无法接受的
AFTER_SYNC模式则可以解决这个问题,继续上面的例子:
1.A提交事务到主库
2.主库写binlog
3.主库发送给从库
4.主库等待从库确认,此时id=0,没有任何客户端能看到id=1的结果,因为没有提交
5.主库收到从库确认,主库开始提交到存储引擎
6.主库返回结果给客户端
假如第4步时主库宕机,客户端切换到从库,如果从库实际接收到事务,那么此时id=1,如果从库未接收到事务,那么此时id=0,
无论哪种状态,对于所有客户端数据库都是一致,事务都没有丢失,同样客户端A需要自己检查事务状态,因为他没收到反馈,业务上他本身就允许两种可能(提交or回滚)
分享题目:MySQL5.7半同步机制
网站路径:
http://cdweb.net/article/pcgccj.html