新实例配置半同步复制

部署 MySQL

  • 可使用脚本部署:https://github.com/XiangYyy/install_mysql_tools.git
    • 需注意更改 DEPLOY_TYPE 为 semisync,且 SEMI_ROLE 设置为对应角色
  • 或手动增加配置(需注意主从节点增加配置不同):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 主/从节点均增加
loose-plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"

# 主节点增加
## 部署时或主动主从切换时,设为 OFF,其他时间推荐为 ON
loose-rpl_semi_sync_master_wait_no_slave=OFF
loose-rpl_semi_sync_master_timeout = 99999999
loose-rpl_semi_sync_master_enabled = 1
## 主节点收到多少个从节点的 ack 后认为执行成功
loose-rpl_semi_sync_master_wait_for_slave_count = 1
loose-rpl_semi_sync_master_wait_point = AFTER_SYNC

# 从节点增加(8.0.26前为 rpl_semi_sync_slave_enabled)
loose-rpl_semi_sync_replica_enabled = 1

建立主从关系

  • 主库创建从库同步用户(ip地址需要改为从库地址,根据实际情况选择允许访问的 ip 范围)
1
2
create user 'backup_user'@'%' identified by 'slaveBkPass';
GRANT SELECT, RELOAD, PROCESS, SHOW DATABASES, LOCK TABLES, REPLICATION CLIENT,REPLICATION SLAVE, EVENT ON *.* TO 'backup_user'@'%' ;
  • 从库清空 GTID 信息
1
reset master;
  • 从库指定主库的 GTID
1
2
-- ID 通过主库 show master status ; 命令查询
SET GLOBAL GTID_PURGED='8de332e5-2080-11ee-97ea-000c29c15bdf:1-4';
  • 从库配置主库信息
1
2
3
4
5
6
change master to MASTER_HOST='172.16.2.181',  -- 设置主库 IP
MASTER_PORT=3306,                              -- 设置主库 端口
MASTER_USER='backup_user',                     -- 主库配置的同步用户
MASTER_PASSWORD='slaveBkPass',                 -- 主库配置的同步用户的密码
master_auto_position=1 ,                       -- 开启自动 GTID 同步
get_master_public_key=1;                       -- 自动获取 pem,加密为 caching_sha2_password 时可保证正常连接。
  • 从库开启同步
1
start slave;

查看状态

  • 主节点查看半同步信息
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
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             | 1736    |
| Rpl_semi_sync_master_no_times              | 0       |
| Rpl_semi_sync_master_no_tx                 | 2879    |
| Rpl_semi_sync_master_status                | ON      |
| Rpl_semi_sync_master_timefunc_failures     | 0       |
| Rpl_semi_sync_master_tx_avg_wait_time      | 1436    |
| Rpl_semi_sync_master_tx_wait_time          | 2476282 |
| Rpl_semi_sync_master_tx_waits              | 1724    |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0       |
| Rpl_semi_sync_master_wait_sessions         | 0       |
| Rpl_semi_sync_master_yes_tx                | 1726    |
| Rpl_semi_sync_replica_status               | OFF     |
+--------------------------------------------+---------+
  • 从节点查看从信息
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 172.16.2.181
                  Master_User: backup_user
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000002
          Read_Master_Log_Pos: 3838583
               Relay_Log_File: relay-bin.000002
                Relay_Log_Pos: 3837714
        Relay_Master_Log_File: mysql-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 3838583
              Relay_Log_Space: 3837918
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1689144700
                  Master_UUID: 8de332e5-2080-11ee-97ea-000c29c15bdf
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set: 8de332e5-2080-11ee-97ea-000c29c15bdf:5-10195
            Executed_Gtid_Set: 8de332e5-2080-11ee-97ea-000c29c15bdf:1-10195
                Auto_Position: 1
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 1
            Network_Namespace:
  • 从节点查看半同步信息
1
2
3
4
5
6
mysql>  show status like "Rpl_semi_sync_replica_status";
+------------------------------+-------+
| Variable_name                | Value |
+------------------------------+-------+
| Rpl_semi_sync_replica_status | ON    |
+------------------------------+-------+

完善其他配置

主节点开启 rpl_semi_sync_master_wait_no_slave

  • 更改配置文件
1
rpl_semi_sync_master_wait_no_slave = ON
  • MySQL 热更改参数
1
mysql> set @@global.rpl_semi_sync_master_wait_no_slave=ON;

从节点开启 readonly

  • 更改配置文件
1
2
read_only = 1
super_read_only = 1
  • MySQL 热更改参数
1
2
set @@global.read_only = 1;
set @@global.super_read_only = 1;

正在运行的实例不停机配置半同步从库

  • 操作和建立从库类似,先基于 xtrabackup,建立异步从库,同步主库数据
  • 待主从延迟较低时,主从关系切换为半同步复制模式

创建异步从库

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 172.16.2.181
                  Master_User: backup_user
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 11472906
               Relay_Log_File: relay-bin.000002
                Relay_Log_Pos: 3311696
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 3311520
              Relay_Log_Space: 11473286
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 304
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1689148379
                  Master_UUID: 1f259e5d-2089-11ee-a7d1-000c29c15bdf
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Waiting for replica workers to process their queues
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set: 1f259e5d-2089-11ee-a7d1-000c29c15bdf:56574-86844
            Executed_Gtid_Set: 1f259e5d-2089-11ee-a7d1-000c29c15bdf:1-65311
                Auto_Position: 1
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 1
            Network_Namespace:
1 row in set, 1 warning (0.00 sec)

所有节点安装 plugin

1
2
3
4
5
install plugin rpl_semi_sync_master soname 'semisync_master.so';
-- mysql8.0
install plugin rpl_semi_sync_replica soname 'semisync_replica.so';
-- mysql5.7
install plugin rpl_semi_sync_slave soname 'semisync_slave.so';

从节点开启半同步复制配置

1
2
3
4
5
-- 开启从节点半同步(mysql5.7 rpl_semi_sync_slave_enabled)
set @@global.rpl_semi_sync_replica_enabled=1;
-- 重启 slave 同步进程
stop slave;
start slave;

主节点配置半同步复制配置

1
2
3
4
set @@global.rpl_semi_sync_master_wait_no_slave=ON;
set @@global.rpl_semi_sync_master_timeout = 99999999;
set @@global.rpl_semi_sync_master_wait_for_slave_count = 1;
set @@global.rpl_semi_sync_master_wait_point = AFTER_SYNC;
  • 关注主从延迟,在主从延迟较低时,开启主节点半同步复制
1
2
-- 开启主节点半同步复制
set @@global.rpl_semi_sync_master_enabled = 1;

查看状态

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
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             | 5059    |
| 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      | 1486    |
| Rpl_semi_sync_master_tx_wait_time          | 7500110 |
| Rpl_semi_sync_master_tx_waits              | 5045    |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0       |
| Rpl_semi_sync_master_wait_sessions         | 0       |
| Rpl_semi_sync_master_yes_tx                | 5059    |
| Rpl_semi_sync_replica_status               | OFF     |
+--------------------------------------------+---------+

从节点配置只读

1
2
set @@global.read_only=1;
set @@global.super_read_only=1;

主从节点更改配置文件(完全配置好后添加)

  • 主从节点更改配置文件,根据实际配置调整
  • 主节点增加配置
1
2
3
4
5
6
loose-plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_replica=semisync_replica.so"
loose-rpl_semi_sync_master_wait_no_slave=ON
loose-rpl_semi_sync_master_timeout = 99999999
loose-rpl_semi_sync_master_enabled = 1
loose-rpl_semi_sync_master_wait_for_slave_count = 1
loose-rpl_semi_sync_master_wait_point = AFTER_SYNC
  • 从节点增加配置
1
2
3
4
5
6
loose-plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_replica=semisync_replica.so"
# 8.0.26 前为 rpl_semi_sync_slave_enabled
loose-rpl_semi_sync_replica_enabled = 1
# 配置只读
read_only = 1
super_read_only = 1

涉及参数

plugin

  • 半同步复制需要引入的 plugin
1
loose-plugin_load="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"

leader

loose-rpl_semi_sync_master_wait_no_slave

  • 默认为 ON
  • 设为 OFF 后,当连接 master 的 slave 的数量少于 rpl_semi_sync_master_wait_for_slave_count 设置的值,master 不会等待超时,立刻自动降为异步复制模式

rpl_semi_sync_master_timeout

  • 等待从库回复 ACK 的时间,超过这个时间会降级为异步
  • 设置为较大值时,如果 slave 节点异常,会影响主库状态,但可以保证所有提交的数据在从节点也有一份,适用于对数据完整性要求较高的场景
  • 设置为较小值时,如果 slave 节点异常,仅影响主库较短时间,但存在 leader flower 不分时间数据不一致的场景,适用于对数据可用性要求高,并能容忍一定数据丢失风险的场景
  • 默认为 10000,即 10s
1
2
3
rpl_semi_sync_master_timeout = 99999999
# or
rpl_semi_sync_master_timeout = 3000

rpl_semi_sync_master_enabled

  • 主库是否开启半同步复制

rpl_semi_sync_master_wait_for_slave_count

  • 主库收到多少个 ACK 才认为提交成功,默认值为 1

rpl_semi_sync_master_wait_point

  • 提交流程
    • AFTER_SYNC:client–>execute sql–>wrtie redolog–>write binlog–>wait ACK–>innodb storage commit–>client receive OK
    • AFTER_COMMIT:client–>execute sql–>wrtie redolog–>write binlog–>innodb storage commit–>wait ACK–>client receive OK
  • 差别:
    • 实际差别是 leader 服务器提交变更的时机不同,AFTER_SYNC 会在 flower 返回 ACK 后,提交变更,AFTER_SYNC 会先提交然后等待 flower 的 ACK
  • 影响:
    • AFTER_SYNC 所有客户端查到的数据是一致的,AFTER_COMMIT 其他客户端可能看到当前客户端提交更改的(commit)在等待 ACK 的数据
    • AFTER_COMMIT 模式当发生主从切换时,有的终端可能会看到类似于数据丢失的情况,因为非触发更改的线程能看到还未返回 ACK 的数据,节点切换后,如果节点并未同步到该部分数据,则查询的结果会发生变化,即可能产生幻读

flower

rpl_semi_sync_replica_enabled

  • 从库是否开启半同步复制

状态参数说明

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
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             | 6538     |
| 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      | 5192     |
| Rpl_semi_sync_master_tx_wait_time          | 33877094 |
| Rpl_semi_sync_master_tx_waits              | 6524     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0        |
| Rpl_semi_sync_master_wait_sessions         | 0        |
| Rpl_semi_sync_master_yes_tx                | 6538     |
| Rpl_semi_sync_replica_status               | OFF      |
+--------------------------------------------+----------+
  • Rpl_semi_sync_master_clients:当前连接了多少个半同步从库
  • Rpl_semi_sync_master_net_avg_wait_time(已弃用):主库等待从库回复的平均时间,以微秒为单位。此变量始终为0,不推荐使用,并且将在以后的版本中删除
  • Rpl_semi_sync_master_net_wait_time(已弃用):主库等待从库回复的总时间,以微秒为单位。此变量始终为0,不推荐使用,并且将在以后的版本中删除
  • Rpl_semi_sync_master_net_waits:主库等待从库回复的总次数
  • Rpl_semi_sync_master_no_times:主库关闭半同步复制(降级)的次数
  • Rpl_semi_sync_master_no_tx:从库未成功确认的事务数
  • Rpl_semi_sync_master_status:为 ON 时表示主库使用半同步复制,为 OFF 时表示主库使用异步复制
  • Rpl_semi_sync_master_timefunc_failures:调用 gettimeofday 等时间函数时主库失败的次数
  • Rpl_semi_sync_master_tx_avg_wait_time:主库等待一个事务的平均时间,以微秒为单位
  • Rpl_semi_sync_master_tx_waits:主库等待事务的总时间,以微秒为单位
  • Rpl_semi_sync_master_wait_pos_backtraverse:主库等待事件的二进制日志次数低于之前等待事件的总次数。当事务等待回复的顺序与其二进制日志事件的写入顺序不同时,会发生这种情况
  • Rpl_semi_sync_master_wait_sessions:当前等待从库回复的会话数
  • Rpl_semi_sync_master_yes_tx:从库成功确认的事务数