1 背景说明
MySQL 5.5之前版本的MySQL Replication都是异步(asynchronous)的,即主库执行完事务后,不用关心备库的情况。如果备库没有及时同步,而主库此时又Crash,那么这时备库中的数据就是不完整的。即在主库发生故障的时候,无法使用备库来继续提供数据一致的服务。
而半同步机制,master节点只要确认有至少一个slave节点接收到了事物,即可向客户端返回操作成功的信息,master节点甚至不需要等待slave节点也成功执行完这个事物,只要至少有一个slave节点接收到这个事物,并且将之成功写入到本地的中继日志文件(写到relay log),就算成功。
当然Semi_synchronous中,仅仅保证事务的已经传递到备库上,但是并不确保已经在备库上执行完成了。此外,还有一种情况会导致主备数据不一致。在某个session中,主库上提交一个事务后,会等待事务传递给至少一个备库,如果在这个等待过程中主库Crash,那么也可能备库和主库不一致。在主库恢复后,可以通过参数Rpl_semi_sync_master_no_tx观察。
在半同步情况下,如果主备之间连接出现故障,比如主备网络故障或者备库故障,主库在事务提交后等待10秒(rpl_semi_sync_master_timeout的默认值)后,就会继续。这时主库就会变回原来的异步状态。
在Mysql 5.7 和 MariaDB 10.2中,半同步机制变化也有如下2个变化:
1) rpl_semi_sync_master_wait_slave_count参数设置有几个slave接收到了binlog才成功返回客户端请求,缺省是一台,但不可以指定是具体哪台。
2) rpl_semi_sync_master_wait_point 参数,它有两种选择:
AFTER_SYNC(5.7缺省值,5.6中无此选项)
主库把每一个事务写到二进制日志并且发送给从库,主库在等待从库写到自己的relay-log里的确认信息,在接到确认信息后,主数据库把事务写到存储引擎里并把相应结果反馈给客户端。AFTER_COMMIT(5.6缺省值)
主库把每一个事务写到二进制日志并且发送给从库,然后马上就把事务写到存储引擎里;主库在等待从库写到自己的relay-log里的信息确认后,主库把相应结果反馈给客户端。这两个参数值的区别:
AFTER_COMMIT模式的弊端在于,虽然主库一直没有告诉提交事务的客户端事务已经成功(在从库成功确认前)但是实际已经提交了,其它客户端此时已经可以看到事务的结果了。
也就是对于事务提交者自身,的确保证了只要收到成功就一定成功了,但是其它客户端却可能存在发现事务成功了,但最后却没成功,因为数据已经到了存储引擎层。
2 搭建主从复制环境
半同步复制,是在主从复制的基础上搭建的。关于主从复制的搭建参考:
MariaDB 主从复制 搭建手册
http://www.cndba.cn/dave/article/2659
3 半同步复制配置
这里假设MariaDB的主从复制已经完成,并正常工作。 我们看半同步的配置。
3.1 安装插件
半同步复制依赖2个插件:semisync_master.so 和 semisync_slave.so。
查看现有插件:
MariaDB [cndba]> show plugins;
+-------------------------------+----------+--------------------+---------+---------+
| Name | Status | Type | Library | License |
+-------------------------------+----------+--------------------+---------+---------+
| binlog | ACTIVE | STORAGE ENGINE | NULL | GPL |
| mysql_native_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| mysql_old_password | ACTIVE | AUTHENTICATION | NULL | GPL |
| wsrep | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MRG_MyISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MEMORY | ACTIVE | STORAGE ENGINE | NULL | GPL |
| CSV | ACTIVE | STORAGE ENGINE | NULL | GPL |
| MyISAM | ACTIVE | STORAGE ENGINE | NULL | GPL |
| CLIENT_STATISTICS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| INDEX_STATISTICS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| TABLE_STATISTICS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| USER_STATISTICS | ACTIVE | INFORMATION SCHEMA | NULL | GPL |
| PERFORMANCE_SCHEMA | 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 |
……
MariaDB [cndba]> show variables like 'plugin_dir';
+---------------+------------------------------+
| Variable_name | Value |
+---------------+------------------------------+
| plugin_dir | /usr/local/mysql/lib/plugin/ |
+---------------+------------------------------+
1 row in set (0.00 sec)
MariaDB [cndba]> system ls -l /usr/local/mysql/lib/plugin/semisync*
-rwxr-xr-x 1 1021 1004 587252 Jan 3 22:52 /usr/local/mysql/lib/plugin/semisync_master.so
-rwxr-xr-x 1 1021 1004 471765 Jan 3 22:53 /usr/local/mysql/lib/plugin/semisync_slave.so
MariaDB [cndba]>
在master库安装semisync_master.so,在slave端安装semisync_slave.so:
MariaDB [cndba]> install plugin rpl_semi_sync_master SONAME 'semisync_master.so' ;
Query OK, 0 rows affected (0.01 sec)
MariaDB [cndba]> install plugin rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected (0.02 sec)
安装完后就可以通过show plugins命令查看到该插件,当然也可以两个插件都装上,已防止以后主从库的切换:
MariaDB [cndba]> show plugins;
……
| rpl_semi_sync_master | ACTIVE | REPLICATION | semisync_master.so | GPL |
| rpl_semi_sync_slave | ACTIVE | REPLICATION | semisync_slave.so | GPL |
+-------------------------------+----------+--------------------+--------------------+---------+
54 rows in set (0.00 sec)
3.2 修改Master端半同步相关参数
MariaDB [cndba]> 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_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_COMMIT |
| rpl_semi_sync_slave_enabled | OFF |
| rpl_semi_sync_slave_trace_level | 32 |
+------------------------------------+--------------+
7 rows in set (0.00 sec)
控制是否在主端启用半同步复制:
MariaDB [cndba]> set global rpl_semi_sync_master_enabled=1;
Query OK, 0 rows affected (0.00 sec)
指定主端等待slave响应的时间,单位是毫秒,这里设为10秒
MariaDB [cndba]> set global rpl_semi_sync_master_timeout=10000;
Query OK, 0 rows affected (0.00 sec)
3.3 修改slave端半同步相关参数
MariaDB [cndba]> 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_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_COMMIT |
| rpl_semi_sync_slave_enabled | OFF |
| rpl_semi_sync_slave_trace_level | 32 |
+------------------------------------+--------------+
7 rows in set (0.00 sec)
控制是否在slave端启用半同步复制:
MariaDB [cndba]> set global rpl_semi_sync_slave_enabled=1;
Query OK, 0 rows affected (0.00 sec)
MariaDB [cndba]> 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_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_COMMIT |
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+------------------------------------+--------------+
7 rows in set (0.00 sec)
3.4 重启slave节点的io_thread线程
通过重启让slave重新连接master,注册成为半同步的slave身份。
MariaDB [cndba]> stop slave io_thread;
Query OK, 0 rows affected (0.01 sec)
MariaDB [cndba]> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)
3.5 查看master相关变量
MariaDB [cndba]> show status like 'rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 |
| Rpl_semi_sync_master_net_avg_wait_time | 432 |
| Rpl_semi_sync_master_net_wait_time | 432 |
| Rpl_semi_sync_master_net_waits | 1 |
| 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 | 468 |
| Rpl_semi_sync_master_tx_wait_time | 468 |
| Rpl_semi_sync_master_tx_waits | 1 |
| 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_slave_status | OFF |
+--------------------------------------------+-------+
15 rows in set (0.00 sec)
主要关注四个参数:
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节点数量
3.6 测试
主库:
MariaDB [(www.cndba.cn/dave)]> use cndba
Database changed
MariaDB [cndba]> select * from dave;
+------+-------------------+
| id | name |
+------+-------------------+
| 1 | www.cndba.cn/dave |
| 2 | www.zhixintech.cc |
+------+-------------------+
2 rows in set (0.00 sec)
MariaDB [cndba]> insert into dave values(1,'dave');
Query OK, 1 row affected (0.04 sec)
从库:
MariaDB [(www.cndba.cn/dave)]> use cndba
Database changed
MariaDB [cndba]> select * from dave;
+------+-------------------+
| id | name |
+------+-------------------+
| 1 | www.cndba.cn/dave |
| 2 | www.zhixintech.cc |
| 1 | dave |
+------+-------------------+
3 rows in set (0.00 sec)
同步正常,进一步测试:
停掉从库:
[root@MariaDB ~]# service mysql stop
Shutting down MySQL. [ OK ]
[root@MariaDB ~]#
主库操作:
MariaDB [cndba]> insert into dave values(1,'dave');
Query OK, 1 row affected (10.01 sec)
注意:这里会hang 10秒钟
MariaDB [cndba]> show status like 'rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 0 |
| Rpl_semi_sync_master_net_avg_wait_time | 263 |
| Rpl_semi_sync_master_net_wait_time | 526 |
| Rpl_semi_sync_master_net_waits | 2 |
| Rpl_semi_sync_master_no_times | 1 |
| Rpl_semi_sync_master_no_tx | 1 |
| Rpl_semi_sync_master_status | OFF |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 468 |
| Rpl_semi_sync_master_tx_wait_time | 468 |
| Rpl_semi_sync_master_tx_waits | 1 |
| 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_slave_status | OFF |
+--------------------------------------------+-------+
15 rows in set (0.00 sec)
版权声明:本文为博主原创文章,未经博主允许不得转载。