1. 了解mysql半同步复制
1)半同步复制:一主多从模式下,有一个从节点返回成功,即成功,不必等待多个节点全部返回
MySQL半同步,MySQL5.5由Google贡献的补丁才开始支持半同步复制(semi Replication)模式,
该模式可以确保从服务器接收完主服务器发送的binlog日志文件并写入自己的中继日志(relay log)里,
然后会给主服务器一个反馈,告诉对方已经接收到完毕,
这时主库线程才返回当前session告知操作完成,当出现超时情况时,源主服务器会暂时切换到异步复制模式,
直到至少有一台设置为半同步复制模式的从服务器及时收到信息为止。
2)半同步复制的原理:
- master做完一步等一步,需要等待至少一个slave节点完成复制之后才开始进行下一个操作
- master做大事件的时候,需要进行半同步,master节点等待一个节点即可
- 当半同步出现问题的时候会自动切换为异步同步
- 数据库要避免慢查询问题,会造成延迟,占用数据库的IO
- 优点:提高了数据完整性,数据至少会存在两个节点(master节点和一个slave节点)
- 加了消息确认ACK,不会造成数据丢失
- 出现问题会自动降低为异步复制
注意:
- 半同步复制模式在主服务器和从服务器同时启用,否则主服务器默认使用异步复制模式
- 异步复制可能会造成数据丢失,半同步复制就是为了解决数据丢失的问题。
2. 配置半同步复制
实验准备:需要之前的gtid异步复制作为底
1)在主节点上安装半同步复制的插件:
[root@master ~]# mysql -uroot -pServer+147
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.7.24-log MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
Query OK, 0 rows affected (0.01 sec)
2)在从节点安装半同步复制的插件:
[root@slave ~]# mysql -uroot -pServer+147
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 5.7.24 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected (0.01 sec)
3)主服务器上查看插件:
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
-> FROM INFORMATION_SCHEMA.PLUGINS
-> WHERE PLUGIN_NAME LIKE '%semi%';
+----------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE |
+----------------------+---------------+
1 row in set (0.01 sec)mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
-> FROM INFORMATION_SCHEMA.PLUGINS
-> WHERE PLUGIN_NAME LIKE '%semi%';
+----------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE |
+----------------------+---------------+
1 row in set (0.01 sec)
(4)在从服务器查看插件:
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
-> FROM INFORMATION_SCHEMA.PLUGINS
-> WHERE PLUGIN_NAME LIKE '%semi%';
+---------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+---------------------+---------------+
| rpl_semi_sync_slave | ACTIVE |
+---------------------+---------------+
1 row in set (0.00 sec)
5)主服务器上激活插件:
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
Query OK, 0 rows affected (0.00 sec)
6)从服务器上激活插件:
从库重启io进程,激活插件之后必须要重启io进程,否则不会生效,如果重启不了的话就说明两端的数据不同步
mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;
Query OK, 0 rows affected (0.00 sec)
mysql> STOP SLAVE IO_THREAD;
Query OK, 0 rows affected (0.01 sec)
mysql> START SLAVE IO_THREAD;
Query OK, 0 rows affected (0.00 sec)
7)查看主库的变量的值,可以查看到延迟时间(10000指10000毫秒,也就是10秒):
- 查看变量的值:
mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%';
+-------------------------------------------+------------+
| 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.00 sec)
- 查看变量的状态:
mysql> show status like '%rpl%';
+--------------------------------------------+-------+
| 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.01 sec)
8)查看从库变量的值:
mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
2 rows in set (0.01 sec)
3.测试
1)关闭从库io线程:
mysql> STOP SLAVE IO_THREAD;
Query OK, 0 rows affected (0.00 sec)
2)主库建立数据库testfile:
mysql> CREATE DATABASE testfile;
- 有10秒的延迟,这是因为从库的io进程关闭了,不能及时的写入数据;主库等待10秒之后从库还没有起来,主库不再等待直接写入
3)再次插入数据,主库直接写入,没有延迟:
mysql> CREATE DATABASE testfiles;
Query OK, 1 row affected (0.00 sec)
- 这是因为:半同步复制再一次失败后会自动切换成异步复制,从库进程起来之后会将没有做的事情再做一遍
4)从库重新开启:发现所有的数据都过来了(基于gtid),接着上一次的事情做
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| testfile |
| testfiles |
+--------------------+
6 rows in set (0.01 sec)
总结:
- 也就是说只要从库的io进程恢复工作就会立即同步没有同步的数据;
- 半同步复制失败后会自动切换成异步复制,从库进程起来之后会检测主从库数据是否同步;
- 若不同步,将会采用异步复制的方式同步数据;
- 将插件安装在数据库中是临时的,退出重新登陆会失效,永久的可以将配置写在配置文件中。