一、前言
在本月初( 2024年7月1日),官方发布了MySQL 9.0.0 创新版。
其发版说明详见:https://dev.mysql.com/doc/relnotes/mysql/9.0/en/
在其中对“创新版”和 “LTS(长期支持版)”做了介绍。并给出了MySQL 发布时间表,截图如下:

同时,也给出了MySQL 9.0 的新功能说明,详见:https://dev.mysql.com/doc/refman/9.0/en/mysql-nutshell.html
由于我负责运维管理的MySQL,多为MGR集群,因此想赶紧尝尝鲜。于是抽工作之余,在本地虚机环境上,搭建了一套基于MySQL 9.0 的MGR集群。并整理了这篇文字记录。
二、MGR简介
MGR是“MySQL Group Replication”的简称,它是MySQL官方推出的基于组复制的高可用集群架构。MGR基于分布式Paxos协议,实现组复制,保证数据一致性。内置故障检测和自动选主功能,只要半数以上节点正常,就可继续正常工作。 它具有以下特点和要求:
- MGR由奇数个节点共同组成一个数据库集群(至少3个节点,最多9个节点)
- 各节点配置尽量保持一致,因为和 PXC一样,也会有“木桶短板效应”。
- 事务的提交必须经过半数以上节点确认方可提交。
- 支持单主模式和多主模式。官方推荐使用单主模式。
- 仅支持InnoDB引擎
- 需要开启GTID
- 表要有显式主键
- 不建议使用外键
以下是3节点MGR的拓扑结构示意图:

对于正常部署3节点的MGR集群,需要三台主机。但由于我本机资源有限,而且只是用于测试,因此准备在一台虚拟机上搭建3节点的MGR集群。
以下搭建过程,参照了官方文档(https://dev.mysql.com/doc/refman/9.0/en/group-replication.html)的指导说明。
三、准备一台虚拟机
1、创建一台VMware虚机
(1)运行 VMware Workstation 新建虚拟机:

(2)选择在虚拟机中要安装的操作系统:

(3)分配虚拟机资源:
虚拟机分配2G内存即可。

2、在虚机中安装Rocky Linux
(1)下载最新的Rocky Linux 9.4 ISO文件
下载地址:https://rockylinux.org/download

(2)挂载Rocky-9.4-x86_64-dvd.iso到虚机并安装
(3)启动安装了 Rocky Linux 的虚机

四、在虚机上安装3节点MGR集群
1、关闭防火和SELinux
systemctl stop firewalld
systemctl disable firewalld
sed -i 's/^SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
setenforce 02、设置主机名解析
编辑/etc/hosts文件,加入以下内容:
192.168.20.94 rocky94
3、安装依赖包
yum install -y libaio4、创建mysql用户
groupadd mysql
useradd -r -g mysql -s /bin/false mysql
5、下载mysql 9.0 安装包
下载地址:https://dev.mysql.com/downloads/mysql/

可以看到 mysql 9.0 的“Mini版”安装包非常小巧,只有58.5M,还不到60MB。
6、上传安装包到虚拟机,并解压
tar -xvf mysql-9.0.0-linux-glibc2.17-x86_64-minimal.tar.xz -C /opt/
cd /opt
mv mysql-9.0.0-linux-glibc2.17-x86_64-minimal mgr
cd mgr
mkdir mysql-files
chown mysql:mysql mysql-files
chmod 750 mysql-files7、设置系统环境变量
export PATH=/opt/mgr/bin:$PATH8、创建数据目录
mkdir -p /data/mgr/db{1,2,3}
chown -R mysql:mysql /data/mgr9、配置MGR各节点参数
(1)/etc/my.3321.cnf
[mysqld]
server_id=3321
port=3321
report_port=3321
report_host=rocky94
socket=/tmp/mysql.3321.sock
mysqlx_socket=/tmp/mysqlx.33210.sock
mysqlx_port=33210
datadir=/data/mgr/db1
basedir=/opt/mgr
user=mysql
log_error=error.log
pid-file=mysqld.pid
#log-error=/var/log/mysqld.log
#pid-file=/var/run/mysqld/mysqld.pid
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
default_storage_engine=InnoDB
gtid_mode=ON
enforce_gtid_consistency=ON
plugin_load_add='group_replication.so'
loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
loose-group_replication_start_on_boot=off
loose-group_replication_local_address= "rocky94:33061"
loose-group_replication_group_seeds= "rocky94:33061,rocky94:33062,rocky94:33063"
loose-group_replication_bootstrap_group=off
(2)/etc/my.3322.cnf
[mysqld]
server_id=3322
port=3322
report_port=3322
report_host=rocky94
socket=/tmp/mysql.3322.sock
mysqlx_socket=/tmp/mysqlx.33220.sock
mysqlx_port=33220
datadir=/data/mgr/db2
basedir=/opt/mgr
user=mysql
log_error=error.log
pid-file=mysqld.pid
#log-error=/var/log/mysqld.log
#pid-file=/var/run/mysqld/mysqld.pid
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
default_storage_engine=InnoDB
gtid_mode=ON
enforce_gtid_consistency=ON
plugin_load_add='group_replication.so'
loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
loose-group_replication_start_on_boot=off
loose-group_replication_local_address= "rocky94:33062"
loose-group_replication_group_seeds= "rocky94:33061,rocky94:33062,rocky94:33063"
loose-group_replication_bootstrap_group=off
(3)/etc/my.3323.cnf
[mysqld]
server_id=3323
port=3323
report_port=3323
report_host=rocky94
socket=/tmp/mysql.3323.sock
mysqlx_socket=/tmp/mysqlx.33230.sock
mysqlx_port=33230
datadir=/data/mgr/db3
basedir=/opt/mgr
user=mysql
log_error=error.log
pid-file=mysqld.pid
#log-error=/var/log/mysqld.log
#pid-file=/var/run/mysqld/mysqld.pid
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
default_storage_engine=InnoDB
gtid_mode=ON
enforce_gtid_consistency=ON
plugin_load_add='group_replication.so'
loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
loose-group_replication_start_on_boot=off
loose-group_replication_local_address= "rocky94:33063"
loose-group_replication_group_seeds= "rocky94:33061,rocky94:33062,rocky94:33063"
loose-group_replication_bootstrap_group=off
10、初始化MGR各节点实例
mysqld --defaults-file=/etc/my.3321.cnf --initialize
mysqld --defaults-file=/etc/my.3322.cnf --initialize
mysqld --defaults-file=/etc/my.3323.cnf --initialize11、启动MGR各节点实例
mysqld_safe --defaults-file=/etc/my.3321.cnf &
mysqld_safe --defaults-file=/etc/my.3322.cnf &
mysqld_safe --defaults-file=/etc/my.3323.cnf &12、修改mysql的root密码(以节点1为例)
(1)查看初始密码
grep "A temporary password" /data/mgr/db1/error.log(2)登录mysql
mysql -uroot -p -S/tmp/mysql.3321.sock此时报错,截图如下:

解决方法:
ln -s /usr/lib64/libncurses.so.6.2 /usr/lib64/libncurses.so.5
ln -s /usr/lib64/libtinfo.so.6.2 /usr/lib64/libtinfo.so.5(3)修改密码
mysql> alter user root@'localhost' identified by 'root_password';
mysql> flush privileges;13、创建复制用户
mysql> SET SQL_LOG_BIN=0;
mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'rel_password';
mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
mysql> GRANT CONNECTION_ADMIN ON *.* TO rpl_user@'%';
mysql> GRANT BACKUP_ADMIN ON *.* TO rpl_user@'%';
mysql> GRANT GROUP_REPLICATION_STREAM ON *.* TO rpl_user@'%';
mysql> FLUSH PRIVILEGES;
mysql> SET SQL_LOG_BIN=1;14、检查确认MGR各节点均已经安装了组复制插件

这个复制插件,已经安装了。如果尚未安装,则执行如下命令进行安装:
mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';15、启动第一个节点的服务实例
mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user', SOURCE_PASSWORD='rel_password' \
FOR CHANNEL 'group_replication_recovery';
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
mysql> START GROUP_REPLICATION;
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
mysql> SELECT * FROM performance_schema.replication_group_members;启动第一个节点后,查询结果截图如下:

16、启动第二个节点的服务实例
mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user', SOURCE_PASSWORD='rel_password' \
FOR CHANNEL 'group_replication_recovery';
mysql> START GROUP_REPLICATION;
mysql> SELECT * FROM performance_schema.replication_group_members;
启动第二个节点后,查询结果截图如下:

17、启动第三个节点的服务实例
mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user', SOURCE_PASSWORD='rel_password' \
FOR CHANNEL 'group_replication_recovery';
mysql> START GROUP_REPLICATION;
mysql> SELECT * FROM performance_schema.replication_group_members;
启动第三个节点后,查询结果截图如下:

至此,可以看到由三个节点组成的MGR集群,已经正常运行了。其中有一主库(PRIMARY)和两从库(SECONDARY)。
18、MGR主库和从库的只读属性
MGR集群,会根据各节点的角色(主库还是从库),自动设置其只读属性,通过以下查询可得以验证:
(由于是在同一台虚拟机上,MGR的各个节点的服务端口不同,因此通过端口来加以区分)

(1)查看主库的只读属性

可以看到,主库的只读属性是关闭的,即主库是可以读写的。
(2)查看两个从库的只读属性


可以看到,从库都是只读的,即只能执行读操作,不允许写操作。因此确保从库不会被误写入数据,避免因从库误写而导致主从不一致的情况发生。
五、MGR集群的简单测试
1、MGR集群的主从同步的测试
(1)、在主库上建库、建表、添加表数据

(2)、在从库上验证


可以看到,在主库上创建的库、创建的表,以及添加的表数据,都已经同步到各个从库上。
2、MGR集群的高可用测试
(1)先查看集群状态

(2)终止主节点服务
shutdown或直接kill掉主库服务(3321端口的服务),用以模拟主库宕机。
(3)再次查看集群状态

可以看到,MGR在原主库终止后,重新选出了新的主库。
(4)重新拉起被终止服务的节点
重新启动刚刚被终止服务的节点,用以模拟主库宕机后的恢复,并将其加入MGR集群:
mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user', SOURCE_PASSWORD='rel_password' \
FOR CHANNEL 'group_replication_recovery';
mysql> START GROUP_REPLICATION;
(5)查看加入恢复节点后的集群状态

可以看到,将恢复后的节点重新加入集群,其角色为从库,MGR集群又恢复为3节点的运行状态。
六、MGR更改主库
1、命令格式
对于刚搭建的MGR集群,第一个节点是主库,但也可以将指定的节点设置为新的主库(原来的主库,则成为从库),以下是更改主库的命令格式如下:
SELECT group_replication_set_as_primary(member_uuid);2、命令演示
以下是MGR集群各节点的初始情况:

可以看到,端口为3321的节点为主库。现在要将端口为3323的节点设置为新的主库,则执行如下命令:

再次查看MGR集群各节点的情况如下:

可以看到,端口为3323的节点已经成为主库。
七、切换单主和多主模式
1、单主模式切换为多主模式的命令
默认情况下,MGR是一主多从的单主模式,但也可以切换为多主模式,命令如下:
SELECT group_replication_switch_to_multi_primary_mode();以下是命令执行结果截图:

2、多主模式切换为单主模式的命令
SELECT group_replication_switch_to_single_primary_mode([member_uuid]);以上命令中的member_uuid参数是可选的,如果不加此参数,则由系统自动选一个节点为主库;如果加上此参数,则将对应的节点设置为主库。
以下是命令执行结果的截图:

可以看到MGR集群已经由多主模式,又切换回单主模式。由于切换命令中,并未指定主库的member_uuid,所以主库就由系统自动选定。
八、结语
以上,完成了在一台虚拟机上搭建3节点的MGR 9.0 集群,并进行了简单的测试。
另外补充说明一下:与MGR相类似的,还有一个“InnoDB集群”,这也是由MySQL官方推出的高可用集群架构,它可以由“MySQL Shell”来管理,更加方便。并结合“MySQL Router”来使用,实现读写分离。
其架构示意图如下:

“InnoDB集群”的具体介绍,可详见官方文档:https://dev.mysql.com/doc/refman/9.0/en/mysql-innodb-cluster-introduction.html
我将以上学习和实践的过程记录下来,再结合近期墨天轮推出的“MySQL知识图谱”,分享给感兴趣的小伙伴,希望一起学习、共同进步。




