前言
从MySQL5.5开始,MySQL以插件的形式支持半同步复制。如何理解半同步呢?首先我们来看看异步,全同步的概念.
异步复制(Asynchronous replication)
MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。
全同步复制(Fully synchronous replication)
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
半同步复制(Semisynchronous replication)
介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。
一、环境说明
半同步复制是以异步复制搭建完成为前提的,之前我们已经完成了异步复制的搭建。异步复制
要想使用半同步复制,必须满足以下几个条件:
1)MySQL 5.5及以上版本
2)变量have_dynamic_loading为YES (查看命令:show variables like “have_dynamic_loading”;)
3)主从复制已经存在 (即提前部署mysql主从复制环境,主从同步要配置基于整个数据库的,不要配置基于某个库的同步,即同步时不要过滤库)
二、搭建步骤
1.验证异步复制是否成功
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 192.168.101.122
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: binlog.000054
Read_Master_Log_Pos: 453
Relay_Log_File: hisdg-relay-bin.000003
Relay_Log_Pos: 321
Relay_Master_Log_File: binlog.000054
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
也可以在主库插入数据验证。
2.安装半同步复制插件
插件位置:
[root@hisdg plugin]# ls
adt_null.so component_keyring_file.so component_validate_password.so innodb_engine.so mysql_clone.so semisync_source.so
authentication_fido_client.so component_log_filter_dragnet.so connection_control.so keyring_file.so mysql_no_login.so validate_password.so
authentication_kerberos_client.so component_log_sink_json.so ddl_rewriter.so keyring_udf.so rewrite_example.so version_token.so
authentication_ldap_sasl_client.so component_log_sink_syseventlog.so debug libmemcached.so rewriter.so
authentication_oci_client.so component_mysqlbackup.so group_replication.so libpluginmecab.so semisync_master.so
auth_socket.so component_query_attributes.so ha_example.so locking_service.so semisync_replica.so
component_audit_api_message_emit.so component_reference_cache.so ha_mock.so mypluglib.so semisync_slave.so
[root@hisdg plugin]# pwd
/usr/local/mysql-8.0.27/lib/plugin
插件安装
主库安装插件
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
Query OK, 0 rows affected, 1 warning (0.09 sec)
mysql> show variables like '%rpl_semi_sync_master%';
+-------------------------------------------+------------+
| 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)
主库配置文件配置
在主库参数文件中添加
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000
查看插件安装状态
mysql> show plugins;
+---------------------------------+----------+--------------------+--------------------+---------+
| Name | Status | Type | Library | License |
+---------------------------------+----------+--------------------+--------------------+---------+
| binlog | ACTIVE | STORAGE ENGINE | NULL | GPL |
。
。
。
|
| rpl_semi_sync_master | ACTIVE | REPLICATION | semisync_master.so | GPL |
+---------------------------------+----------+--------------------+--------------------+---------+
46 rows in set (0.00 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.00 sec)
从库插件安装
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected, 1 warning (0.10 sec)
mysql> set global rpl_semi_sync_slave_enabled=on;
Query OK, 0 rows affected (0.00 sec)
从库配置文件配置
rpl_semi_sync_slave_enabled=1
3.启动半同步复制
由于之前是异步复制,需要重启从库IO线程,激活半同步复制。
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;
4.查看半同步复制状态
mysql> show variables like '%rpl_semi_sync_master%';
+-------------------------------------------+------------+
| 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)
rpl_semi_sync_master_enabled=ON:表示在master上已经开启了半同步复制模式。
rpl_semi_sync_master_timeout=10000:当半同步复制发生超时时(由rpl_semi_sync_master_timeout参数控制,单位是毫秒,默认为10000,即10s),会暂时关闭半同步复制,转而使用异步复制。当master dump线程发送完一个事务的所有事件之后,如果在rpl_semi_sync_master_timeout内,收到了从库的响应,则主从又重新恢复为半同步复制。
rpl_semi_sync_master_wait_no_slave:表示是否允许master每个事务提交后都要等待slave的接收确认信号。默认是on,即每一个事务都会等待,如果为off,则slave追赶上后,也不会开启半同步复制模式,需要手动开启。
rpl_semi_sync_master_trace_level=32:表示用于开启半同步复制模式时的调试级别,默认是32。
5.半同步复制到异步复制切换
修改超时时间
rpl_semi_sync_master_timeout 时间为10s。生产上建议设置的尽可能大。只要超过10s就会自动转为异步复制。
set global rpl_semi_sync_master_timeout=xxx;
手动切换
主库
set global rpl_semi_sync_master_enabled=off;
从库:
set global rpl_semi_sync_slave_enabled=off
关闭从库I/O thread
stop slave io_thread;
start slave io_thread;
6.切换测试
当slave从库的io_thread线程将binlog日志接收完毕时,要给master主库一个确认信号,如果rpl_semi_sync_master_timeout=10000(10秒)超过10秒未收到slave从库的接收信号,那么就会自动转换为传统的异步复制模式:
从库关闭io_thead线程:
mysql>stop slave io_thread;
Query OK, 0 rows affected (0.00 sec)
mysql> show status like '%semi%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | OFF |
+----------------------------+-------+
1 row in set (0.01 sec)
从库同步已停止
在主库新建一张表
mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> create table t2(id int);
Query OK, 0 rows affected (10.61 sec) --这里主库新建表的时间为10s,因为从库的slave进程停止,从库一直无法将同步结果返回给从库,等到超时时间10s到了之后,主库主动切换为异步同步。
查看同步模式
mysql> show status like '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 0 |
| 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 | 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 | 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.00 sec)
可以看到这个语句执行了10秒钟才成功,执行完成之后变成了传统主从复制。再次启动io_thread线程之后半同步复制正常。
以上值得关注的参数:
rpl_semi_sync_master_status:用于指示主服务器是使用异步复制模式,还是半同步复制模式。
rpl_semi_sync_master_clients:用于显示有多少个从服务器配置成了半同步复制模式。
rpl_semi_sync_master_yes_tx:用于显示从服务器确认的成功提交数量。
rpl_semi_sync_master_no_tx:用于显示从服务器确认的不成功提交数量。
注:此时因为从库IO_THREAD停止的缘故,主库自动切换成了异步同步,此时如果重启从库IO_THREAD,主库依然会恢复为半同步复制。