MGR(MySQL Group Replication)部署测试

1. 环境说明

192.168.11.131 mgr1  主节点
192.168.11.132 mgr2  从节点
192.168.11.133 mgr3  从节点

2. 在mgr1、mgr2、mgr3上安装mysql##

(1)安装过程(略),mysql版本-5.7.32
	根据官方文档,mysql配置文件的最低要求:

		#---------- basic setting: 组复制的MySQL Server实例所需的配置设置 -----------#
		server_id=1			# 注意:各节点不同
		gtid_mode=ON
		enforce_gtid_consistency=ON
		master_info_repository=TABLE
		relay_log_info_repository=TABLE
		binlog_checksum=NONE
		log_slave_updates=ON
		log_bin=binlog
		binlog_format=ROW

		#---------- Storage Engines: 禁用非InnoDB存储引擎 -----------#
		disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"

		#---------- Group Replication Settings: 组复制配置 -----------#
		# 将组复制插件添加到服务器在启动时加载的插件列表中。
		plugin_load_add='group_replication.so'
		# 这个神奇的参数5.7.6版本引入,用于定义一个记录事务的算法,这个算法使用hash标识来记录事务。
		# 如果使用MGR,那么这个hash值需要用于分布式冲突检测何处理,在64位的系统,官网建议设置该参数使用 XXHASH64 算法。
		transaction_write_set_extraction=XXHASH64
		# 此GROUP的名字,必须是一个有效的UUID,以此来区分整个内网里边的各个不的GROUP,可以使用SELECT UUID()生成。
		group_replication_group_name="a60fce0f-294c-11eb-8779-005056895fb9"
		# 是否随服务器启动而自动启动组复制
		group_replication_start_on_boot=off
		# 本地的IP地址字符串,host:port
		group_replication_local_address="192.168.11.131:33061"			# 注意:各节点不同
		# 设置组成员的主机名和端口。
		# 注意:该端口用于组内成员之间内部通信,不可用于与app连接。
		group_replication_group_seeds="192.168.11.131:33061,192.168.11.132:33061,192.168.11.133:33061"
		# 指定使用哪个Server来引导组(这里指的是将此系统变量设置为ON的Server)
		# 在组所有可能涉及的Server的配置文件中建议统一将此系统变量设置为OFF
		group_replication_bootstrap_group=off

    	        注意:
	         (a)三个节点的server_id不同;group_replication_local_address也不同(对应各节点IP和端口);
	         (b)如需必要,请将root用户的ip地址修改为%(启动组复制后不可再修改)。

3. mgr1上创建复制用户

mysql> SET SQL_LOG_BIN=0;
mysql> CREATE USER repluser@'%' IDENTIFIED BY 'replpass';
mysql> GRANT REPLICATION SLAVE ON *.* TO repluser@'%';
mysql> FLUSH PRIVILEGES;
mysql> SET SQL_LOG_BIN=1;

4. mgr1上配置mgr

mysql> CHANGE MASTER TO MASTER_USER='rpluser', MASTER_PASSWORD='replpasss' FOR CHANNEL 'group_replication_recovery';

5. mgr1上安装组复制插件

(1)有两种方式:
	(a)在配置文件中指定加载插件; 
	(b)手动安装插件。

(2)配置文件方式:(本文采用的方式)	
    plugin_load_add='group_replication.so'

(3)手动安装插件方式:
    mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';

(4)检查是否安装成功
    mysql> SHOW PLUGINS;
    | group_replication          | ACTIVE   | GROUP REPLICATION  | group_replication.so | GPL     |

6. mgr1上引导组(首次启动组)

注意:默认情况下是单主模式,执行引导的节点为主节点,可以读写;后面加入的节点(未执行引导)为从节点,只读(自动调整参数super_read_only=on/read_only=on)。
        所谓引导其实就是SET GLOBAL group_replication_bootstrap_group=ON;(可以理解为指定主节点)

mysql> SET GLOBAL group_replication_bootstrap_group=ON;
mysql> START GROUP_REPLICATION;
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;

检查是否已创建组:发现组已经存在,并且有一个组成员,状态为ONLINE

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 8b4f47fe-2d32-11eb-a8cf-0050568907ba | mgr1        |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+

7. mgr1上创建测试库、表,并添加数据,以测试在新节点接入到组中后,会同步这些数据

mysql> CREATE DATABASE test;
mysql> USE test;
mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL);
mysql> INSERT INTO t1 VALUES (1, 'Luis');

mysql> select * from test.t1;
+----+------+
| c1 | c2   |
+----+------+
|  1 | Luis |
+----+------+

8. 添加mgr2到组

(1)创建复制用户
    mysql> SET SQL_LOG_BIN=0;
    mysql> CREATE USER repluser@'%' IDENTIFIED BY 'replpass';
    mysql> GRANT REPLICATION SLAVE ON *.* TO repluser@'%';
    mysql> FLUSH PRIVILEGES;
    mysql> SET SQL_LOG_BIN=1;   
(2)配置mgr
	mysql> CHANGE MASTER TO MASTER_USER='repluser', MASTER_PASSWORD='replpass' FOR CHANNEL 'group_replication_recovery';
(3)启动组复制: 注意由于在配置mgr1时,已经引导并创建过组,因此只需要启动组复制将mgr2加入到组中即可。
	mysql> START GROUP_REPLICATION;
(4)检查表performance_schema.replication_group_members,查看组成员及状态
    mysql> SELECT * FROM performance_schema.replication_group_members;
    +---------------------------+--------------------------------------+-------------+-------------+--------------+
    | CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
    +---------------------------+--------------------------------------+-------------+-------------+--------------+
    | group_replication_applier | 10a9692d-2d4c-11eb-b5f8-005056891ca6 | mgr2        |        3306 | ONLINE       |
    | group_replication_applier | 8b4f47fe-2d32-11eb-a8cf-0050568907ba | mgr1        |        3306 | ONLINE       |
    +---------------------------+--------------------------------------+-------------+-------------+--------------+
(5)由于mgr2的状态时ONLINE,因此,mgr2已经追上了mgr1的事务,因此查看表test.t1。
    mysql> select * from test.t1;
    +----+------+
    | c1 | c2   |
    +----+------+
    |  1 | Luis |
    +----+------+
	事务已经自动同步完成。

(6)注意:在启动组复制时出现的2个报错及解决方法
    报错1: [ERROR] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. 
            Local transactions: 10a9692d-2d4c-11eb-b5f8-005056891ca6:1-2 > Group transactions: 8b4f47fe-2d32-11eb-a8cf-0050568907ba:1-2, a60fce0f-294c-11eb-8779-005056895fb9:1-4'
    原因:虽然该mysql是新装的,但是在修改初始密码时,开启了binlog,因此将修改密码的过程写入到了binlog中,因此需要清空。
    解决:reset master将二进制日志清空,重新START GROUP_REPLICATION
        mysql> RESET MASTER;
            mysql> START GROUP_REPLICATION
    
    报错2:2020-11-23T14:42:31.109221+08:00 46 [ERROR] Plugin group_replication reported: 'There was an error when connecting to the donor server. Please check that group_replication_recovery channel credentials and all MEMBER_HOST column values of performance_schema.replication_group_members table are correct and DNS resolvable.'
          2020-11-23T14:42:31.109267+08:00 46 [ERROR] Plugin group_replication reported: 'For details please check performance_schema.replication_connection_status table and error log messages of Slave I/O for channel group_replication_recovery.'

    原因:由于在配置mgr时,change master时,写错了用户名或者密码,因此报错。
    解决:
        mysql> STOP GROUP_REPLICATION;
        mysql> CHANGE MASTER TO MASTER_USER='repluser', MASTER_PASSWORD='replpass' FOR CHANNEL 'group_replication_recovery';
        mysql> START GROUP_REPLICATION;

9. 添加mgr3到组:与mgr2加入组的步骤相同

(1)创建复制用户
    mysql> RESET MASTER;
    mysql> SET SQL_LOG_BIN=0;
    mysql> CREATE USER repluser@'%' IDENTIFIED BY 'replpass';
    mysql> GRANT REPLICATION SLAVE ON *.* TO repluser@'%';
    mysql> FLUSH PRIVILEGES;
    mysql> SET SQL_LOG_BIN=1;   
(2)配置mgr
	mysql> CHANGE MASTER TO MASTER_USER='repluser', MASTER_PASSWORD='replpass' FOR CHANNEL 'group_replication_recovery';
(3)启动组复制: 注意由于在配置mgr1时,已经引导并创建过组,因此只需要启动组复制将mgr3加入到组中即可。
	mysql> START GROUP_REPLICATION;
(4)检查表performance_schema.replication_group_members,查看组成员及状态
	mysql> SELECT * FROM performance_schema.replication_group_members;
    +---------------------------+--------------------------------------+-------------+-------------+--------------+
    | CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
    +---------------------------+--------------------------------------+-------------+-------------+--------------+
    | group_replication_applier | 10a9692d-2d4c-11eb-b5f8-005056891ca6 | mgr2        |        3306 | ONLINE       |
    | group_replication_applier | 8b4f47fe-2d32-11eb-a8cf-0050568907ba | mgr1        |        3306 | ONLINE       |
    | group_replication_applier | a67ba921-2d4e-11eb-8c11-005056892789 | mgr3        |        3306 | ONLINE       |
    +---------------------------+--------------------------------------+-------------+-------------+--------------+
(5)由于mgr3的状态时ONLINE,因此,mgr2已经追上了mgr1的事务,因此查看表test.t1。
    mysql> select * from test.t1;
    +----+------+
    | c1 | c2   |
    +----+------+
    |  1 | Luis |
    +----+------+
    事务已经自动同步完成。

10. 单主模式下,如何查看哪个服务器是主服务器?

mysql> SHOW STATUS LIKE 'group_replication_primary_member';
+----------------------------------+--------------------------------------+
| Variable_name                    | Value                                |
+----------------------------------+--------------------------------------+
| group_replication_primary_member | 8b4f47fe-2d32-11eb-a8cf-0050568907ba |
+----------------------------------+--------------------------------------+

结合命令:SELECT * FROM performance_schema.replication_group_members;可确定主服务器的host为mgr1。

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 10a9692d-2d4c-11eb-b5f8-005056891ca6 | mgr2        |        3306 | ONLINE       |
| group_replication_applier | 8b4f47fe-2d32-11eb-a8cf-0050568907ba | mgr1        |        3306 | ONLINE       |
| group_replication_applier | a67ba921-2d4e-11eb-8c11-005056892789 | mgr3        |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+

11. 当服务器加入组时,尝试次数与间隔的设置

mysql> show global variables like 'group_replication_recovery_retry_count';
+----------------------------------------+-------+
| Variable_name                          | Value |
+----------------------------------------+-------+
| group_replication_recovery_retry_count | 10    |
+----------------------------------------+-------+
1 row in set (0.10 sec)

重试次数默认次数为10,可通过设置参数group_replication_recovery_retry_count调整。
如:mysql> SET GLOBAL group_replication_recovery_retry_count=15;

mysql> show global variables like 'group_replication_recovery_reconnect_interval';
+-----------------------------------------------+-------+
| Variable_name                                 | Value |
+-----------------------------------------------+-------+
| group_replication_recovery_reconnect_interval | 60    |
+-----------------------------------------------+-------+
1 row in set (0.14 sec)

间隔默认为60。

12. 将单主模式切换为多主模式

(1)停止组复制(所有节点执行):
    mysql> stop group_replication;

(2)单主模式设置为ON,多主模式设置为OFF
    mysql> set global group_replication_single_primary_mode=OFF;

(3)在所有节点启用多主数据更新的严格一致性检查
    mysql> set global group_replication_enforce_update_everywhere_checks=ON;

(4)引导,随便选择某个节点执行(本文选择mgr2)
    mysql> SET GLOBAL group_replication_bootstrap_group=ON;
    mysql> START GROUP_REPLICATION;
    mysql> SET GLOBAL group_replication_bootstrap_group=OFF;

(5)其他节点执行
    mysql> START GROUP_REPLICATION;

(6)查看组成员及状态
    mysql> select * from performance_schema.replication_group_members;
    +---------------------------+--------------------------------------+-------------+-------------+--------------+
    | CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
    +---------------------------+--------------------------------------+-------------+-------------+--------------+
    | group_replication_applier | 10a9692d-2d4c-11eb-b5f8-005056891ca6 | mgr2        |        3306 | ONLINE       |
    | group_replication_applier | 8b4f47fe-2d32-11eb-a8cf-0050568907ba | mgr1        |        3306 | ONLINE       |
    | group_replication_applier | a67ba921-2d4e-11eb-8c11-005056892789 | mgr3        |        3306 | ONLINE       |
    +---------------------------+--------------------------------------+-------------+-------------+--------------+
    3 rows in set (0.00 sec)

(7)查看所有节点的read_only及supper_read_only变量,都是OFF(所有节点都可读写)
    mysql> show global variables like '%read_only%';
    +-----------------------+-------+
    | Variable_name         | Value |
    +-----------------------+-------+
    | innodb_read_only      | OFF   |
    | read_only             | OFF   |
    | super_read_only       | OFF   |
    | transaction_read_only | OFF   |
    | tx_read_only          | OFF   |
    +-----------------------+-------+
    5 rows in set (0.04 sec)

    实际测试也证实组内所有节点均可读写。

(8)多主模式下,group_replication_primary_member变量值为空。
    mysql> SHOW STATUS LIKE 'group_replication_primary_member';
    +----------------------------------+-------+
    | Variable_name                    | Value |
    +----------------------------------+-------+
    | group_replication_primary_member |       |
    +----------------------------------+-------+
    1 row in set (0.04 sec)

13. 多主模式切换为单主模式

(1)所有节点执行
    mysql> stop group_replication;
    mysql> set global group_replication_enforce_update_everywhere_checks=OFF;
    mysql> set global group_replication_single_primary_mode=ON;

(2)主节点(mgr1)执行
    mysql> SET GLOBAL group_replication_bootstrap_group=ON;
    mysql> START GROUP_REPLICATION;
    mysql> SET GLOBAL group_replication_bootstrap_group=OFF;

(3)从节点(mgr2、mgr3)执行
    mysql> START GROUP_REPLICATION;

14. 多主模式下,新节点加入(mgr4)

(1)新节点配置文件:
    server_id=4
    group_replication_local_address="192.168.11.134:33061"
    group_replication_group_seeds="192.168.11.131:33061,192.168.11.132:33061,192.168.11.133:33061,192.168.11.134:33061"

(2)在其他三个节点(mgr1、mgr2、mgr3)执行(重启失效!若想持久生效,需要同时配置文件中修改。)
    mysql> set global group_replication_group_seeds='192.168.11.131:33061,192.168.11.132:33061,192.168.11.133:33061,192.168.11.134:33061';

(2)创建复制用户
    mysql> reset master;
    mysql> SET SQL_LOG_BIN=0;
    mysql> CREATE USER repluser@'%' IDENTIFIED BY 'replpass';
    mysql> GRANT REPLICATION SLAVE ON *.* TO repluser@'%';
    mysql> FLUSH PRIVILEGES;
    mysql> SET SQL_LOG_BIN=1;  

(3)配置mgr
    mysql> set global group_replication_single_primary_mode=OFF;
    mysql> set global group_replication_enforce_update_everywhere_checks=ON;

    mysql> CHANGE MASTER TO MASTER_USER='repluser', MASTER_PASSWORD='replpass' FOR CHANNEL 'group_replication_recovery';

(4)启动组复制: 注意由于在配置mgr1时,已经引导并创建过组,因此只需要启动组复制将mgr3加入到组中即可。
    mysql> START GROUP_REPLICATION;

(5)检查表performance_schema.replication_group_members,查看组成员及状态
    mysql> SELECT * FROM performance_schema.replication_group_members;
    +---------------------------+--------------------------------------+-------------+-------------+--------------+
    | CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
    +---------------------------+--------------------------------------+-------------+-------------+--------------+
    | group_replication_applier | 10a9692d-2d4c-11eb-b5f8-005056891ca6 | mgr2        |        3306 | ONLINE       |
    | group_replication_applier | 8b4f47fe-2d32-11eb-a8cf-0050568907ba | mgr1        |        3306 | ONLINE       |
    | group_replication_applier | 8e5d0881-2e2e-11eb-a6ac-005056895fb9 | mgr4        |        3306 | ONLINE       |
    | group_replication_applier | a67ba921-2d4e-11eb-8c11-005056892789 | mgr3        |        3306 | ONLINE       |
    +---------------------------+--------------------------------------+-------------+-------------+--------------+
    4 rows in set (0.01 sec)

(6)注意:
    (a)其实相对于单节点模式,其区别在于多设置了两个参数:group_replication_single_primary_mode=OFF 和  group_replication_enforce_update_everywhere_checks=ON;
    (b)若想持久保存这台新加入组的机器的信息,需要在配置文件中修改group_replication_group_seeds。

15. 多主模式下,故障转移

(1)多主模式下,一个节点fail了,写线程可以连接到其他的节点上,因为所有节点都是读写的。

(2)手动kill掉mgr1的mysqld和mysqld_safe线程,发现该节点被踢出。
    (a)错误日志:      
        2020-11-24T17:12:10.632391+08:00 0 [Warning] Plugin group_replication reported: 'Member with address mgr1:3306 has become unreachable.'
        2020-11-24T17:12:11.620997+08:00 0 [Warning] Plugin group_replication reported: 'Members removed from the group: mgr1:3306'
        2020-11-24T17:12:11.621301+08:00 0 [Note] Plugin group_replication reported: 'Group membership changed to mgr2:3306, mgr4:3306, mgr3:3306 on view 16062011996623015:13.'
    (b)检查表performance_schema.replication_group_members,查看组成员已经没有mgr1
        mysql>  select * from performance_schema.replication_group_members;
        +---------------------------+--------------------------------------+-------------+-------------+--------------+
        | CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
        +---------------------------+--------------------------------------+-------------+-------------+--------------+
        | group_replication_applier | 10a9692d-2d4c-11eb-b5f8-005056891ca6 | mgr2        |        3306 | ONLINE       |
        | group_replication_applier | 8e5d0881-2e2e-11eb-a6ac-005056895fb9 | mgr4        |        3306 | ONLINE       |
        | group_replication_applier | a67ba921-2d4e-11eb-8c11-005056892789 | mgr3        |        3306 | ONLINE       |
        +---------------------------+--------------------------------------+-------------+-------------+--------------+
        3 rows in set (0.01 sec)

(3)手动添加一部分数据,再重新启动mgr1,并将其加入组中:
    mysql> set global group_replication_single_primary_mode=OFF;
    mysql> set global group_replication_enforce_update_everywhere_checks=ON;
    mysql> START GROUP_REPLICATION;

    发现mgr1已经添加进组:
        mysql>  select * from performance_schema.replication_group_members;
        +---------------------------+--------------------------------------+-------------+-------------+--------------+
        | CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
        +---------------------------+--------------------------------------+-------------+-------------+--------------+
        | group_replication_applier | 10a9692d-2d4c-11eb-b5f8-005056891ca6 | mgr2        |        3306 | ONLINE       |
        | group_replication_applier | 8b4f47fe-2d32-11eb-a8cf-0050568907ba | mgr1        |        3306 | ONLINE       |
        | group_replication_applier | 8e5d0881-2e2e-11eb-a6ac-005056895fb9 | mgr4        |        3306 | ONLINE       |
        | group_replication_applier | a67ba921-2d4e-11eb-8c11-005056892789 | mgr3        |        3306 | ONLINE       |
        +---------------------------+--------------------------------------+-------------+-------------+--------------+
        4 rows in set (0.00 sec)
        
        错误日志:
        2020-11-24T17:16:53.584056+08:00 0 [Note] Plugin group_replication reported: 'Members joined the group: mgr1:3306'
        2020-11-24T17:16:53.587879+08:00 0 [Note] Plugin group_replication reported: 'Group membership changed to mgr2:3306, mgr1:3306, mgr4:3306, mgr3:3306 on view 16062011996623015:14.'
        2020-11-24T17:16:55.266815+08:00 0 [Note] Plugin group_replication reported: 'The member with address mgr1:3306 was declared online within the replication group'

    并且发现新添加的数据已经在mgr1上存在。

16. 单主模式下,故障转移

(1)当主节点(primary member)挂掉或者因为其他原因而导致unreachable,会根据自动选举机制选择一个新的主节点。

(2)自动选举机制的规则是什么?
    首先会比较剩余各节点的group_replication_member_weight变量的值,若都是相同版本的mysql,group_replication_member_weight的值高的当选为新主;
    如果各节点的group_replication_member_weight的值相同(默认情况下都是50),则会根据各节点的server_uuid的值进行字典排序,选择第一个为新主。

(3)手动kill掉主节点(mgr1)的mysqld和mysqld_safe进程,查看错误日志(error log),发现节点被踢出,并且已经选择出一个新的主(mgr2)。
    2020-11-25T09:20:36.787529+08:00 0 [Warning] Plugin group_replication reported: 'Member with address mgr1:3306 has become unreachable.'
    2020-11-25T09:20:37.795746+08:00 0 [Warning] Plugin group_replication reported: 'Members removed from the group: mgr1:3306'
    2020-11-25T09:20:37.796055+08:00 0 [Note] Plugin group_replication reported: 'Primary server with address mgr1:3306 left the group. Electing new Primary.'
    2020-11-25T09:20:37.796412+08:00 0 [Note] Plugin group_replication reported: 'A new primary with address mgr2:3306 was elected, enabling conflict detection until the new primary applies all relay logs.'
    2020-11-25T09:20:37.796604+08:00 102 [Note] Plugin group_replication reported: 'This server is working as secondary member with primary member address mgr2:3306.'
    2020-11-25T09:20:37.796696+08:00 0 [Note] Plugin group_replication reported: 'Group membership changed to mgr2:3306, mgr4:3306, mgr3:3306 on view 16062105035172940:5.'

(4)检查表performance_schema.replication_group_members,查看当前组成员及状态
    mysql> select * from performance_schema.replication_group_members;
    +---------------------------+--------------------------------------+-------------+-------------+--------------+
    | CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
    +---------------------------+--------------------------------------+-------------+-------------+--------------+
    | group_replication_applier | 10a9692d-2d4c-11eb-b5f8-005056891ca6 | mgr2        |        3306 | ONLINE       |
    | group_replication_applier | 8e5d0881-2e2e-11eb-a6ac-005056895fb9 | mgr4        |        3306 | ONLINE       |
    | group_replication_applier | a67ba921-2d4e-11eb-8c11-005056892789 | mgr3        |        3306 | ONLINE       |
    +---------------------------+--------------------------------------+-------------+-------------+--------------+
    3 rows in set (0.01 sec)

(5)查看group_replication_primary_member的值,再次确认主节点是mgr2。
    mysql> show global status like '%primary%';
    +----------------------------------+--------------------------------------+
    | Variable_name                    | Value                                |
    +----------------------------------+--------------------------------------+
    | group_replication_primary_member | 10a9692d-2d4c-11eb-b5f8-005056891ca6 |
    +----------------------------------+--------------------------------------+
    1 row in set (0.01 sec)

(6)手动添加部分数据后,再次将mgr1启动,并启动组复制
    (a)启动mysql(略)

    (b)启动组复制
        mysql> START GROUP_REPLICATION;

    (c)查看组成员及状态(mgr1又加入组中,是一个只读节点)
        mysql> select * from performance_schema.replication_group_members;
        +---------------------------+--------------------------------------+-------------+-------------+--------------+
        | CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
        +---------------------------+--------------------------------------+-------------+-------------+--------------+
        | group_replication_applier | 10a9692d-2d4c-11eb-b5f8-005056891ca6 | mgr2        |        3306 | ONLINE       |
        | group_replication_applier | 8b4f47fe-2d32-11eb-a8cf-0050568907ba | mgr1        |        3306 | ONLINE       |
        | group_replication_applier | 8e5d0881-2e2e-11eb-a6ac-005056895fb9 | mgr4        |        3306 | ONLINE       |
        | group_replication_applier | a67ba921-2d4e-11eb-8c11-005056892789 | mgr3        |        3306 | ONLINE       |
        +---------------------------+--------------------------------------+-------------+-------------+--------------+
        4 rows in set (0.01 sec)

        mysql> show global status like '%primary%';
        +----------------------------------+--------------------------------------+
        | Variable_name                    | Value                                |
        +----------------------------------+--------------------------------------+
        | group_replication_primary_member | 10a9692d-2d4c-11eb-b5f8-005056891ca6 |
        +----------------------------------+--------------------------------------+
        1 row in set (0.01 sec)

        mysql> show global variables like '%read_only';
        +-----------------------+-------+
        | Variable_name         | Value |
        +-----------------------+-------+
        | innodb_read_only      | OFF   |
        | read_only             | ON    |
        | super_read_only       | ON    |
        | transaction_read_only | OFF   |
        | tx_read_only          | OFF   |
        +-----------------------+-------+
        5 rows in set (0.01 sec)

17. 组复制–指定ip白名单

(1)如果没有显示指定ip白名单,那么自动允许的ip列表包含下列ip地址:(所有内网地址,范围比较大)
    10/8 prefix       (10.0.0.0 - 10.255.255.255) - Class A
    172.16/12 prefix  (172.16.0.0 - 172.31.255.255) - Class B
    192.168/16 prefix (192.168.0.0 - 192.168.255.255) - Class C
    127.0.0.1 - localhost for IPv4

(2)如果要显示指定ip白名单,而非使用默认允许列表,指定方式为:
    mysql> STOP GROUP_REPLICATION;
    mysql> SET GLOBAL group_replication_ip_whitelist="192.0.2.21/24,198.51.100.44,203.0.113.0/24,example.org,www.example.com/24";
    mysql> START GROUP_REPLICATION;

    注意: 
        (1)该列表必须包含所有mgr节点的地址(group_replication_local_address)。
        (2)为避免组成员离开后,导致有服务器无法连接至组,最好所有组成员设置相同的ip白名单(非必须)。
        (3)ip白名单尽量使用ip地址,如需使用域名,优先使用hosts文件解析。

18. 组复制的要求:

(1)基础设施要求:
    (a)InnoDB存储引擎
        数据必须存储在InnoDB存储引擎中,否则会报错。可指定disabled_storage_engines参数阻止使用其他存储引擎。
        disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
    (b)主键
        组复制的每个表都必须有主键,或者与主键等效的非空唯一键(not null unique)。
    (c)ipv4
        组复制仅支持ipv4网络。
    (d)网络性能
        组复制的实例要求部署在彼此通信非常好的网络环境中,网络延迟和带宽会影响组复制的性能和稳定性。

(2)服务器实例配置要求:
    (a)唯一的server_id;
        server_id=1
    (b)开启二进制日志;
        log_bin=/data/mysql/log/binlog/mysql-bin
        log_bin_index=/data/mysql/log/binlog/binlog.index
    (c)将副本更新写入日志;
        log_slave_updates=1   
    (d)二进制日志格式为row;
        binlog_format=row
    (e)关闭二进制日志校验和
        binlog_checksum=NONE
    (f)开启全局事务标识符(GTID)
        gtid_mode=on  
        enforce_gtid_consistency=1
    (g)复制信息存储方式为TABLE
        master_info_repository=TABLE  
        relay_log_info_repository=TABLE
    (h)记录事务算法
        transaction_write_set_extraction=XXHASH64
    (i)表名都转换小写在所有节点设置相同
        lower_case_table_names=1
    (j*)可启用并行复制
        slave-parallel-type=LOGICAL_CLOCK
        slave-parallel-workers=N
        slave_preserve_commit_order=1
        slave_pending_jobs_size_max=134217728   #多线程复制中,work线程最大内存,可参考max_allowed_packet进行设置(本文中max_allowed_packet=128M)。

19. 组复制的限制

(1)间隙锁(Gap Lock)
    组复制的并发事务认证过程未考虑间隙锁。
    多主模式的事务隔离级别建议为:READ_COMMITTED
(2)表锁和命名锁(Table Locks and Named Locks)
    认证过程未考虑表锁和命名锁。
(3)二进制日志校验和(binlog_checksum=NONE)
    由于校验和设计限制,组复制无法使用,只能设置为NONE。
(4)SERIALIZABLE事务隔离级别
    多主模式下,不支持SERIALIZABLE事务隔离级别。
(5)并行DDL与DML操作
    多主模式下,对同一对象在不同服务器上并发执行DDL与DML语句是不支持的。
(6)级联外键约束
    多主模式组(成员均配置有group_replication_single_primary_mode=OFF)不支持具有多级外键依赖关系的表,特别是定义了CASCADING外键约束的表。
    因为可能会导致无法检测到的冲突,并导致该组成员之间的数据不一致。
    因此,在多主模式中建议设置group_replication_enforce_update_everywhere_checks=ON,以避免未检测到的冲突。
(7)MySQL企业审核和MySQL企业防火墙(MySQL Enterprise Edition)
    在5.7.21版之前,MySQL企业审核和MySQL企业防火墙使用mysql库中的MyISAM表,而组复制不支持MyISAM表。
(8)多主模式死锁
    多主模式时,SELECT .. FOR UPDATE语句可能导致死锁。
(9)复制过滤
    组复制不支持复制过滤,因为事务过滤可能无法让组在一致性状态上达成协议。
(10)组成员数量限制
    组成员个数最多为9。
(11)事务大小限制
    若单个事务太大,无法在5秒的时间内通过网络在组成员之间复制消息(message),则可能会怀疑成员失败了,然后将其驱逐出局。
    此外,大型事务可能还会由于内存分配问题导致系统变慢。为避免这些问题,请使用以下缓解措施:
    (a)限制事务大小;
    (b)可使用group_replication_transaction_size_limit变量指定事务大小限制,
        在5.7版本中该值为0,没有限制;8.0版本中默认值为150000000字节(约143 MB),
        超过此限制的事务将回滚,并且不会发送到组复制的组通信系统(GCS)进行分发。
    (c)使用系统变量group_replication_compression_threshold来指定消息大小,系统默认值为1000000字节,如果消息大小大于该值会进行压缩。
        当组复制的组通信系统(GCS)收到group_replication_transaction_size_limit设置允许,但超出group_replication_compression_threshold设置的消息时,将执行压缩。
        如果group_replication_transaction_size_limit设置为零,则将禁用压缩。(当网络带宽成为瓶颈时,消息压缩可以在组通信级别上将吞吐量提高多达30-40%)

        如未使用消息压缩并且未指定最大事务大小,则复制组成员上的应用程序线程可以处理的消息的大小上限为该成员的值slave_max_allowed_packet系统变量,
        其默认值为最大值1073741824字节(1 GB),当接收成员尝试处理超过此限制的消息时,该消息将失败。
        
        (但是max_allowed_packet会指定事务的大小,如果执行的事务超出max_allowed_packet但是未超出slave_max_allowed_packet会不会执行成功呢?(猜测不可以,未测试))