环境介绍:
10.10.10.62 testdb62
10.10.10.136 testdb136
10.10.10.76 testdb76
添加/etc/hosts 对IP的映射
10.10.10.62 testdb62
10.10.10.136 testdb136
10.10.10.76 testdb76
一、多主/单主模式搭建
随机生成一串 uuid 用来做 loose-group_replication_group_name
cat /proc/sys/kernel/random/uuid
# 修改配置文件,修改或者新增到[mysqld]模块下。3个节点除了server_id、loose-group_replication_local_address 参数不一样外,其他保持一致,然后重启mysql
server-id=1
log_bin=binlog
binlog_format=ROW
transaction_isolation = READ-COMMITTED
gtid_mode=ON
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
binlog_checksum=NONE
log_slave_updates=ON
transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name="ac99b07f-acd1-45c1-adc8-7005f9205b87"
loose-group_replication_start_on_boot=off
loose-group_replication_local_address="testdb62:33061"
loose-group_replication_group_seeds="testdb62:33061,testdb136:33061,testdb76:33061"
loose-group_replication_ip_whitelist="testdb62,testdb136,testdb76"
loose-group_replication_bootstrap_group=off
loose-group_replication_single_primary_mode=off
loose-group_replication_enforce_update_everywhere_checks=on
如果是单主模式,需要修改如下两个参数,单主和多主模式就这点区别,其他操作都一样
loose-group_replication_single_primary_mode=ON
loose-group_replication_enforce_update_everywhere_checks=OFF
# 如果防火墙是打开的,要添加mysql的端口号。
firewall-cmd --permanent --zone=public --add-port={3306,33061}/tcp
firewall-cmd --reload
firewall-cmd --zone=public --list-ports
# 关闭SELinux
临时关闭
setenforce 0
修改配置文件需要重启机器:
sed -i 's/^SELINUX=.*$/SELINUX=disabled/g' /etc/selinux/config
# 创建一个复制用的用户(所有节点执行)
针对5.7创建用户的方式
SET SQL_LOG_BIN=0;
grant replication slave on *.* to 'repl'@'10.10.10.%' identified by 'Jimstars';
flush privileges;
SET SQL_LOG_BIN=1;
针对8.0创建用户的方式
SET SQL_LOG_BIN=0;
CREATE USER 'repl'@'10.10.10.%' IDENTIFIED BY 'Jimstars';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'10.10.10.%';
GRANT BACKUP_ADMIN ON *.* TO 'repl'@'10.10.10.%';
ALTER USER 'repl'@'10.10.10.%' IDENTIFIED BY "Jimstars" PASSWORD EXPIRE NEVER;
SET SQL_LOG_BIN=1;
# 安装group replication插件(所有节点执行)
install PLUGIN group_replication SONAME 'group_replication.so';
# 查看组件是否安装成功
show plugins;
# 修改master信息,构建组复制(group replication)集群信息(所有节点执行)
change master to master_user='repl',master_password='Jimstars' for channel 'group_replication_recovery';
# 随便选择某个节点执行
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
# 其他节点加入MGR(在其他节点上执行)
reset master; # 如果是新搭建的库并且没有任何数据才能执行此语句
start group_replication;
# 查看MGR组信息
SELECT * FROM performance_schema.replication_group_members;
二、单主切换至多主模式
# 如果是5.7
停止组复制(所有节点执行)
stop group_replication;
set global group_replication_single_primary_mode=OFF;
set global group_replication_enforce_update_everywhere_checks=ON;
随便选择某个节点执行
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
其他节点执行
START GROUP_REPLICATION;
# 如果是8.0,只需在任意节点执行下面语句即可
select group_replication_switch_to_multi_primary_mode();
# 查看组信息,所有节点的 MEMBER_ROLE 都为 PRIMARY
SELECT * FROM performance_schema.replication_group_members;
三、多主切换回单主模式(单主模式切主)
# 如果是5.7
停止组复制(所有节点执行)
stop group_replication;
set global group_replication_enforce_update_everywhere_checks=OFF;
set global group_replication_single_primary_mode=ON;
主节点执行
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
从节点执行
START GROUP_REPLICATION;
# 如果是8.0
不指定主节点切换
select group_replication_switch_to_single_primary_mode();
指定主节点切换
select group_replication_switch_to_single_primary_mode("MEMBER_ID");
注意,MEMBER_ID 就是 server_uuid
# 查看MGR组信息
SELECT * FROM performance_schema.replication_group_members;
四、MGR相关运维
# MGR区分主从服务器
show variables like '%read_only%';
如果是主服务器,read_only和super_read_only显示的是 OFF ,从服务器显示的是 ON
# 日常维护步骤
(1)如果从库某一节点关闭
stop group_replication;
(2)如果所有的库都关闭后,第一个库作为主库首先执行
set global group_replication_bootstrap_group=ON;
start group_replication;
剩下的库直接执行即可!
start group_replication;
(3)如果主库故障,会自动从两个从库选出一个主库,主库启动后再次执行如下命令后会变成从库
start group_replication;
# 主库宕机,修复并加入节点
模拟宕机
/etc/init.d/mysqld stop
在testdb136 节点查看已经提升到主节点了。
mysql> show variables like '%read_only%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| read_only | OFF |
+---------------+-------+
1 row in set (0.00 sec)
在testdb136 节点写入测试数据
mysql> insert into textbook select 2,10076,1;
mysql> select * from textbook;
+--------+----------+--------+
| bookid | schoolid | status |
+--------+----------+--------+
| 1 | 10075 | 1 |
| 2 | 10076 | 1 |
+--------+----------+--------+
2 rows in set (0.04 sec)
修复好 test62 节点,启动并查看状态
mysql> select * from performance_schema.replication_group_members;
+---------------------------+-----------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+-----------+-------------+-------------+--------------+
| group_replication_applier | | | NULL | OFFLINE |
+---------------------------+-----------+-------------+-------------+--------------+
1 row in set (0.00 sec)
将修好的test62 节点添加回复制组
change master to master_user='repl',master_password='Jimstars' for channel 'group_replication_recovery';
set global group_replication_allow_local_disjoint_gtids_join=ON;
start group_replication;
如果是单主模式,需要在执行start group_replication 之前执行下面语句
set global group_replication_enforce_update_everywhere_checks=OFF;
set global group_replication_single_primary_mode=ON;
查看是否加入复制组
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 4b53cb18-e2ce-11ea-9cd7-d45d64086d0a | testdb136 | 3306 | ONLINE |
| group_replication_applier | 4db2798b-e2ce-11ea-adfa-000c298e7822 | testdb62 | 3306 | ONLINE |
| group_replication_applier | 501d0288-e2ce-11ea-9575-000c292f0c3c | testdb76 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)
测试数据也已经同步
mysql> select * from textbook;
+--------+----------+--------+
| bookid | schoolid | status |
+--------+----------+--------+
| 1 | 10075 | 1 |
| 2 | 10076 | 1 |
+--------+----------+--------+
2 rows in set (0.01 sec)
# 新节点加入集群环境
修改配置文件,修改或者新增到[mysqld]模块下。3个节点除了server_id、loose-group_replication_local_address 参数不一样外,其他保持一致,然后重启mysql
server-id=1
log_bin=binlog
binlog_format=ROW
transaction_isolation = READ-COMMITTED
gtid_mode=ON
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
binlog_checksum=NONE
log_slave_updates=ON
transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name="ac99b07f-acd1-45c1-adc8-7005f9205b87"
loose-group_replication_start_on_boot=off
loose-group_replication_local_address="testdb62:33061"
loose-group_replication_group_seeds="testdb62:33061,testdb136:33062,testdb76:33063"
loose-group_replication_bootstrap_group=off
loose-group_replication_single_primary_mode=off
loose-group_replication_enforce_update_everywhere_checks=on
针对5.7创建用户的方式
SET SQL_LOG_BIN=0;
grant replication slave on *.* to 'repl'@'10.10.10.%' identified by 'Jimstars';
flush privileges;
SET SQL_LOG_BIN=1;
针对8.0创建用户的方式
SET SQL_LOG_BIN=0;
CREATE USER 'repl'@'10.10.10.%' IDENTIFIED BY 'Jimstars';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'10.10.10.%';
GRANT BACKUP_ADMIN ON *.* TO 'repl'@'10.10.10.%';
ALTER USER 'repl'@'10.10.10.%' IDENTIFIED BY "Jimstars" PASSWORD EXPIRE NEVER;
SET SQL_LOG_BIN=1;
安装group replication插件
install PLUGIN group_replication SONAME 'group_replication.so';
查看组件是否安装成功
show plugins;
从集群环境导出数据并导入新节点
mysqldump -h10.10.10.136 -uroot -pJimstars --single-transaction --triggers --routines --all-databases > /data/backup/`date +%Y%m%d-%H%M`-136-all_bak.sql
mysql -h10.10.10.62 -uroot -pJimstars < /data/backup/20200917-1345-136-all_bak.sql
修改master信息,构建组复制(group replication)集群信息
备份的文件前 有如下的语句:
SET @@GLOBAL.GTID_PURGED=/*!80000 '+'*/ '64269cc6-f88a-11ea-bed1-d45d64086d0a:1-43,ac99b07f-acd1-45c1-adc8-7005f9205b87:1';
执行下面的语句,加入集群
reset master;
SET @@GLOBAL.GTID_PURGED= '64269cc6-f88a-11ea-bed1-d45d64086d0a:1-43,ac99b07f-acd1-45c1-adc8-7005f9205b87:1';
change master to master_user='repl',master_password='Jimstars' for channel 'group_replication_recovery';
START GROUP_REPLICATION;
查看MGR组信息
SELECT * FROM performance_schema.replication_group_members;
# 网络异常恢复
MGR对网络要求很高,有的时候会因网络波动,自动退出集群的情况,此时需要先在出问题的节点停止组复制,然后再重新加入到集群中。
在问题节点上直接执行
stop group_replication;
start group_replication;
# 暂时性数据异常修复
MGR对数据具有一定的容错性和最终一致性,原则上并不会出现数据不一致的情况,并且每次执行事务都会检测冲突,
然后如果当某个节点的数据因为异常导致不一致,切主节点的binlog丢失的情况,势必会导致集群数据不一致,此时可以通过以下的方法暂时让集群起来。
停止异常节点的组复制
stop group_replication;
清空当前的GTIDEXECUTED
reset master;
在异常节点将GTID事务号设置和主节点一致,在主节点输入 show master status; 查看具体的主节点的GTID号
SET @@GLOBAL.GTID_PURGED='主节点的GTID号';
启动异常节点的组复制
Start group_replication;
这里需要注意,这样的方式即使恢复了集群,因为binlog的缺失,实际上数据是不一致的,极有可能发生后续因为数据不一致导致集群出现问题,这里强烈不建议这么做
# 节点重新加入集群环境
reset master;
install PLUGIN group_replication SONAME 'group_replication.so';
change master to master_user='repl',master_password='Jimstars' for channel 'group_replication_recovery';
START GROUP_REPLICATION;
# 克隆恢复加入集群环境
采用节点 testdb62 作为需要接收克隆的节点,新增的节点为 testdb76
在接收克隆的节点 testdb62 添加克隆插件,添加用户
INSTALL PLUGIN clone SONAME 'mysql_clone.so';
CREATE USER clone_user@'10.10.10.%' IDENTIFIED by 'Jimstars';
GRANT BACKUP_ADMIN ON *.* TO 'clone_user'@'10.10.10.%';
在新增节点 testdb76 添加克隆插件,添加用户
INSTALL PLUGIN clone SONAME 'mysql_clone.so';
CREATE USER clone_user@'10.10.10.%' IDENTIFIED by 'Jimstars';
GRANT CLONE_ADMIN ON *.* TO 'clone_user'@'10.10.10.%';
SET GLOBAL clone_valid_donor_list = '10.10.10.62:3306';
在新增节点 testdb76 执行clone操作,执行完MySQL会重启,属于正常现象
mysql -uclone_user -pJimstars -h10.10.10.76 -P3306
mysql> CLONE INSTANCE FROM 'clone_user'@'10.10.10.62':3306 IDENTIFIED BY 'Jimstars';
在新增节点 testdb76 修改配置文件,将之前注释的mgr的配置打开
transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name="ac99b07f-acd1-45c1-adc8-7005f9205b87"
loose-group_replication_start_on_boot=off
loose-group_replication_local_address="10.10.10.76:33061"
loose-group_replication_group_seeds="10.10.10.62:33061,10.10.10.136:33061,10.10.10.76:33061"
loose-group_replication_bootstrap_group=off
loose-group_replication_single_primary_mode=off
loose-group_replication_enforce_update_everywhere_checks=on
新增节点 testdb76 重启
/etc/init.d/mysqld restart
开启复制
START GROUP_REPLICATION;
查看MGR组信息
SELECT * FROM performance_schema.replication_group_members;
# MGR流量控制
MySQL8中通过以下两个参数控制
group_replication_flow_control_certifier_threshold
group_replication_flow_control_applier_threshold
在MySQL8.0.20中这两个参数默认都是25000个事务数,最大值为2147483647个事务数
当场景中触发任意一个参数的值,就会触发MGR的流控功能,限制写节点的写入速度。开启流控后,MGR的写入能力由集群中性能最低的节点决定。
在MGR中通过以下参数进行流控的开关,这个参数默认为开启状态
group_replication_flow_control_mode
如果想关闭,直接设置为disabled
set globalgroup_replication_flow_control_mode='DISABLED';
# 组复制监控常用相关表
显示组复制所有成员信息
SELECT * FROM performance_schema.replication_group_member_stats;
显示监控组内成员复制信息
SELECT * FROM performance_schema.replication_group_members;
显示当前节点连接信息态
SELECT * FROM performance_schema.replication_connection_status;
显示当前组复制线程信息
SELECT * FROM performance_schema.replication_applier_status;
五、MGR搭建过程遇到的问题汇总
[ERROR] Plugin group_replication reported: 'This member has more executed transactions than those present in the group.
Local transactions: c4100eab-f25f-11ea-a0c0-000c292f0c3c:1-4 > Group transactions: ac99b07f-acd1-45c1-adc8-7005f9205b87:1-2,
slave执行的事务gtid与master不一致,如果只是因为误操作,或者是一些无关紧要的数据,
可以通过set globalgroup_replication_allow_local_disjoint_gtids_join=on;来忽略这些事务,
或者通过 reset master 清空 gtidexecuted 表然后重新设置 gtid purged 参数跟 master 的gtid executed一致来跳过这些事务。
如果这些数据不一致会导致问题那么可以通过pt-table-sync来检查误差数据并同步,然后再通过reset master等操作重设gtid相关参数,
需要注意的是这个工具需要binlog格式为statment以使slave也能执行同样检查语句。