0%

MySQL组复制(二)

配置复制组

更改primary

查看当前主节点

1
root@(none) 02:12:  SELECT * FROM performance_schema.replication_group_members;

指定新的主节点进行切换

1
root@(none) 02:12:  SELECT group_replication_set_as_primary('d1fbe050-5ecf-11eb-a88d-0050569c8f5e');

查看进度

1
root@(none) 02:12:  SELECT event_name, work_completed, work_estimated FROM performance_schema.events_stages_current WHERE event_name LIKE "%stage/group_rpl%";

更改复制模式

更改为单主模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
###停止复制
mysql> stop group_replication;

###关闭一致性检查
mysql> set global group_replication_enforce_update_everywhere_checks=OFF;

###开启单主模式
mysql> set global group_replication_single_primary_mode=ON;

###主节点引导组复制
mysql> set global group_replication_bootstrap_group=ON;
mysql> start group_replication
mysql> set global group_replication_bootstrap_group=OFF;

###其它节点加入组复制
mysql> start group_replication

Tips:也可以采用SELECT group_replication_switch_to_single_primary_mode(member_uuid)直接进行切换

更改为多主模式

1
2
3
4
5
6
7
8
9
10
###停止复制
mysql> stop group_replication;

###关闭单主
mysql> set global group_replication_single_primary_mode=OFF;

###启动复制
mysql> set global group_replication_bootstrap_group=ON;
mysql> start group_replication;
mysql> set global group_replication_bootstrap_group=OFF;

Tips:也可以采用SELECT group_replication_switch_to_multi_primary_mode()直接进行切换

查看进度

1
mysql> SELECT event_name, work_completed, work_estimated FROM performance_schema.events_stages_current WHERE event_name LIKE "%stage/group_rpl%";

配置最大共识实例数

这个最大值被称为组的事件范围,是组可以并行执行的最大共识实例数。

查看复制组写入并发性

1
mysql> SELECT group_replication_get_write_concurrency();

配置写入并发(需要GROUP_REPLICATION_ADMIN权限)

1
mysql> SELECT group_replication_set_write_concurrency(instances);

设置组通信协议版本

从MySQL 8.0.16开始,组复制有了组通信协议的概念。可以显式管理组复制通信协议版本,并将其设置为适应您希望组支持的最老的MySQL Server版本。这使得组可以由不同MySQL Server版本的成员组成,同时确保向后兼容性。

查看当前通信协议版本

1
mysql> SELECT group_replication_get_communication_protocol();

修改通信协议版本

1
SELECT group_replication_set_communication_protocol("5.7.25");

Tips:当升级组复制成员MySQL Version后,通信协议并不会自动更新,我们可以手动升级协议版本

事务一致性保证

就分布式一致性保证而言,无论是在正常或故障修复的情况下,组复制始终是一个最终一致性的系统。与系统一致性相关的事件包含控制操作和数据流操作,对于组复制,可以根据一致性评估的控制操作为:

  • 成员加入或离开
  • 网络故障
  • 单主模式下,主节点故障切换或通过group_replication_set_as_primary()重新选主

在单主模式下,当主节点发生故障进行转移时,新的主节点可以立即应用程序流量,不管有多少事务复制积压。这种情况写一致性得到了保证,但是在新节点应用backlog中的事务前可能检索到过时数据,无法保证读一致性。如果采用8.0.14或更高版本时,可以在主节点故障切换期间使用group_replication_consistency变量配置成员提供的事务一致性保证级别。该参数有下列选择

  • EVENTUAL:RO和RW事务在执行之前都不等待前面的事务被应用(8.0.14前的唯一选择)
  • BEFORE:确保本地强一致性,并不保证其它节点数据实时同步,可能造成当前节点读延迟
  • AFTER:确保全局一致性,可以保证所有节点数据实时同步,可能造成所有节点都延迟
  • BEFORE_AND_AFTER:最高级别,结合BEFORE和AFTER来确保本地和全局强一致性
  • BEFOR_ON_PRIMARY_FAILOVER: 确保新主的本地一致性,在新选出的主节点上保存新事务,直到应用完积压事务为止

一致性级别的影响

围绕一致性级别对事务的影响我们通过下列案例来重点说明EVENTUAL、BEFORE和AFTER选项的影响

节点 角色
节点1
节点2 只读
节点3 只读

现有如下表

1
2
3
4
5
6
7
8
9
10
root@test 04:19:  show create table t1;\
+-------+-------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-------------------------------------------------------------------------------------+
| t1 | CREATE TABLE `t1` (
`id` int NOT NULL,
`r1` int DEFAULT NULL,
`r2` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci |

插入一条数据,其它节点也能正常读取到

1
2
3
4
5
6
7
8
9
root@test 04:21:  insert into t1 values (1,2,@@server_id);
Query OK, 1 row affected (0.00 sec)

root@test 04:21: select * from t1;
+----+------+------+
| id | r1 | r2 |
+----+------+------+
| 1 | 2 | 2109 |
+----+------+------+

查看一致性级别

1
2
3
4
5
6
root@test 04:23:  show variables like 'group_replication_consistency';
+-------------------------------+----------+
| Variable_name | Value |
+-------------------------------+----------+
| group_replication_consistency | EVENTUAL |
+-------------------------------+----------+

在节点2上手动添加read锁

1
2
root@test 04:21:  lock table t1 read;
Query OK, 0 rows affected (0.00 sec)

再次插入新数据

1
2
root@test 04:21:  insert into t1 values (2,3,@@server_id);
Query OK, 1 row affected (0.01 sec)

在节点2上并未读取到新插入的数据

1
2
3
4
5
6
root@test 04:23:  select * from t1;
+----+------+------+
| id | r1 | r2 |
+----+------+------+
| 1 | 2 | 2109 |
+----+------+------+

释放锁之后就能读取最新数据

1
2
3
4
5
6
7
8
9
10
root@test 04:26:  unlock tables;
Query OK, 0 rows affected (0.00 sec)

root@test 04:26: select * from t1;
+----+------+------+
| id | r1 | r2 |
+----+------+------+
| 1 | 2 | 2109 |
| 2 | 3 | 2109 |
+----+------+------+

下面将节点2的级别调整为before进行测试

1
root@test 04:26:  set @@group_replication_consistency='before';

再次加锁

1
root@test 04:29:  lock table t1 read;

节点1插入新数据

1
root@(test) 04:29: insert into t1 values (3,4,@@server_id);

这时发现,再去节点2查询表会hang住,需要等待本地数据完全应用。节点3则正常查询

下面将节点2的级别调整为AFTER

1
2
root@(test) 04:34:  set @@group_replication_consistency='after';
Query OK, 0 rows affected (0.00 sec)

重复加锁的过程

1
root@(test) 04:35:  lock table t1 read;

在节点1插入新数据

1
root@(test) 04:35:  insert into t1 values (3,4,@@server_id);

这时会发现插入处于等待状态,并没有完成,因为节点2上的表被锁了,无法完成日志应用。节点2查询成功,但都为陈旧数据。节点3上的查询也需要等待其它从节点日志应用完成才能返回结果,而不是返回陈旧数据。当节点2释放锁之后,节点1的插入完成,节点3的查询也返回了最新数据。

单主模式发生故障转移后,为避免在EVENTUAL选项下RO事务可能读取到过时数据导致的一致性问题,建议使用适当的流控设置,减小事务积压的可能。并将一致性级别设置为BEFORE_ON_PRIMARY_FAILOVER。尽管在使用BEFORE_ON_PRIMARY_FAILOVER一致性级别时,所有写操作都被挂起,但并不是所有读操作都被阻塞,我们任然可以执行一些运维管理命令。