| 角色 | IP | 主机名 |server_id |mysql版本 | 备注 |
| :------- | :------- | :------- |:------- |:------- |
| master | 192.168.187.177 | mysql01 | 1 | 8.0.22 | 主服务器,提供读写操作 |
| slave | 192.168.187.178 | mysql02 | 2 | 8.0.22 | 从服务器,提供读操作 |
| slave | 192.168.187.179 | mysql03 | 3 | 8.0.22 | 从服务器,提供读操作|
各个机器都要操作
cat >> /etc/hosts <
sudo hostnamectl set-hostname mysql01
sudo hostnamectl set-hostname mysql02
sudo hostnamectl set-hostname mysql03
各个机器都要操作
sudo sed -i 's/SELINUX=permissive/SELINUX=disabled/g' /etc/sysconfig/selinux
cat /etc/sysconfig/selinux | grep SELINUX=
各个机器都要操作
参考
https://blog.csdn.net/zhou920786312/article/details/124230776
# 登陆mysql
mysql -u root -p123456 -S /data/mysql/tmp/mysql.sock
# 创建复制用户
CREATE USER 'repl'@'192.168.187.%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.187.%';
# 刷新权限
flush privileges;
# 登陆mysql
mysql -u root -p123456 -S /data/mysql/tmp/mysql.sock
# 安装
install PLUGIN group_replication SONAME "group_replication.so";
# 查看
show plugins;
# 修改命令
sudo vi /data/mysql/conf/my.cnf
# 重启命令
sudo service mysqld restart
新增内容,注意:这里不能直接拿去用,因为有有重复的配置,这里这样写的原因是为了体现MGR需要哪些配置。
可以直接使用 MYSQL–架构–MGR–部署–03–配置 的单机配置。
# Mysql服务ID
server-id=1
# 开启全局事务
gtid_mode=on
# 强制GTID的一致性
enforce_gtid_consistency=on
# 禁用二进制日志事件校验
binlog_checksum=none
# 以行的格式记录
binlog_format=ROW
# 二进制文件日志
log-bin = /data/mysql/binlog/mysql-bin
# 将master的连接信息写入表:mysql.salve_master_info
master_info_repository=TABLE
## 将中继日志的信息写入表:mysql.slave_realy_log_info
relay_log_info_repository=TABLE
# 从服务器 从 主服务器 收到的更新 记入到 从服务器 自己的二进制日志文件中。
log_slave_updates=ON
# 使用哈希算法将其编码为散列
transaction_write_set_extraction=XXHASH64
# 加入的组名,可以修改,只要格式对
loose-group_replication_group_name="ce9be252-2b71-11e6-b8f4-00212844f856"
# 不自动启用组复制集群
loose-group_replication_start_on_boot=off
# 以本机端口33061接受来自组中成员的传入连接
loose-group_replication_local_address="mysql01:33061"
# 组中成员访问表
loose-group_replication_group_seeds="mysql01:33061,mysql02:33061,mysql02:33061"
# 不启用引导组
loose-group_replication_bootstrap_group=off
因为组复制基于GTID,所以必须开启gtid_mode和enforce_gtid_consistency。
# 开启全局事务
gtid_mode=on
# 强制GTID的一致性
enforce_gtid_consistency=on
组复制必须开启二进制日志,且必须设置为行格式的二进制日志,这样才能从日志记录中收集信息且保证数据一致性。所以设置log_bin和binlog_format。
# 以行的格式记录
binlog_format=ROW
# 二进制文件日志
log-bin = /data/mysql/binlog/mysql-bin
由于MySQL对复制事件校验的设计缺陷,组复制不能对他们校验,所以设置binlog_checksum=none
# 禁用二进制日志事件校验
binlog_checksum=none
组复制要将master和relay log的元数据写入到mysql.slave_master_info和mysql.slave_relay_log_info中。
# 将master的连接信息写入表:mysql.salve_master_info
master_info_repository=TABLE
## 将中继日志的信息写入表:mysql.slave_realy_log_info
relay_log_info_repository=TABLE
组中的每个节点都保留了完整的数据副本,它是share-nothing的模式。所以所有节点上都必须开启log_slave_updates,这样新节点随便选哪个作为donor都可以进行异步复制。
# 从服务器 从 主服务器 收到的更新 记入到 从服务器 自己的二进制日志文件中。
log_slave_updates=ON
# [mysqld]
# 修改位置
server-id=2
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 = /data/mysql/binlog/mysql-bin
binlog_format=ROW
transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name="ce9be252-2b71-11e6-b8f4-00212844f856"
loose-group_replication_start_on_boot=off
# 修改位置
loose-group_replication_local_address="mysql02:33061"
loose-group_replication_group_seeds="mysql01:33061,mysql02:33061,mysql03:33061"
loose-group_replication_bootstrap_group=off
新增内容
# [mysqld]
# 修改位置
server-id=3
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 = /data/mysql/binlog/mysql-bin
binlog_format=ROW
transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name="ce9be252-2b71-11e6-b8f4-00212844f856"
loose-group_replication_start_on_boot=off
# 修改位置
loose-group_replication_local_address="mysql03:33061"
loose-group_replication_group_seeds="mysql01:33061,mysql02:33061,mysql03:33061"
loose-group_replication_bootstrap_group=off
# 登陆mysql
mysql -u root -p123456 -S /data/mysql/tmp/mysql.sock
# 配置节点加组时的通道
change master to
master_user="repl",
master_password="123456"
for channel "group_replication_recovery";
在新节点加入组时,首先要选择donor。新节点和donor之间的异步复制就是通过一个名为group_replication_recovery的通道(通道名固定)进行数据恢复的,经过数据恢复后,新节点填充了它缺失的那部分数据,这样就和组内其他节点的数据保持了同步。
当执行完上面的语句后,就生成了一个该通道的relay log文件,当新节点联系上donor后,会从donor处以异步复制的方式将其binlog复制到这个通道的relay log中,新节点将从这个recovery通道的relay log中恢复数据。
前面配置文件中已经指定了master和relay log的元数据信息要记录到表中,可以通过以下sql查看
mysql> select * from mysql.slave_relay_log_info\G
*************************** 1. row ***************************
Number_of_lines: 12
Relay_log_name: /data/mysql/relaylog/mysql-relay-bin-group_replication_recovery.000001
Relay_log_pos: 4
Master_log_name:
Master_log_pos: 0
Sql_delay: 0
Number_of_workers: 0
Id: 1
Channel_name: group_replication_recovery
Privilege_checks_username: NULL
Privilege_checks_hostname: NULL
Require_row_format: 1
Require_table_primary_key_check: STREAM
mysql> select * from mysql.slave_master_info\G
*************************** 1. row ***************************
Number_of_lines: 32
Master_log_name:
Master_log_pos: 4
Host:
User_name:
User_password:
Port: 0
Connect_retry: 60
Enabled_ssl: 0
Ssl_ca:
Ssl_capath:
Ssl_cert:
Ssl_cipher:
Ssl_key:
Ssl_verify_server_cert: 0
Heartbeat: 30
Bind:
Ignored_server_ids: 0
Uuid:
Retry_count: 86400
Ssl_crl:
Ssl_crlpath:
Enabled_auto_position: 1
Channel_name: group_replication_applier
Tls_version:
Public_key_path:
Get_public_key: 0
Network_namespace:
Master_compression_algorithm: uncompressed
Master_zstd_compression_level: 3
Tls_ciphersuites: NULL
Source_connection_auto_failover: 0
*************************** 2. row ***************************
Number_of_lines: 32
Master_log_name:
Master_log_pos: 4
Host:
User_name: repl
User_password: 123456
Port: 0
Connect_retry: 60
Enabled_ssl: 0
Ssl_ca:
Ssl_capath:
Ssl_cert:
Ssl_cipher:
Ssl_key:
Ssl_verify_server_cert: 0
Heartbeat: 30
Bind:
Ignored_server_ids: 0
Uuid:
Retry_count: 1
Ssl_crl:
Ssl_crlpath:
Enabled_auto_position: 1
Channel_name: group_replication_recovery
Tls_version: TLSv1,TLSv1.1,TLSv1.2,TLSv1.3
Public_key_path:
Get_public_key: 0
Network_namespace:
Master_compression_algorithm: uncompressed
Master_zstd_compression_level: 3
Tls_ciphersuites: NULL
Source_connection_auto_failover: 0
2 rows in set (0.00 sec)
# 开启组复制引导
set global group_replication_bootstrap_group=on;
# 开启组复制
start group_replication;
# 关闭组复制引导
set global group_replication_bootstrap_group=off;
在开启组复制之前,设置全局变量group_replication_bootstrap_group为on,这表示稍后启动的组复制功能将引导组,也就是创建组并配置组,这些都是自动的。
配置引导变量为ON后,再开启组复制插件功能,也就是启动组复制。
最后将引导变量设回OFF,之所以要设置回OFF,是为了避免下次重启组复制插件功能时再次引导创建一个组,这样会存在两个名称相同实际却不相同的组。
这几个过程不适合放进配置文件中,强烈建议手动执行它们的。否则下次重启mysql实例时,会自动重新引导创建一个组。同理,除了第一个节点,其他节点启动组复制功能时,不应该引导组,所以只需执行其中的start语句,千万不能开启group_replication_bootstrap_group变量引导组。
当启动组复制功能后,将生成另一个通道group_replication_applier的相关文件。
在receiver接收到消息后,验证是否有并发事务存在冲突问题。冲突检测通过后,这条消息就会写入到组复制的relay log中,等待applier去应用。
select * from performance_schema.replication_group_members;
当组中已有第一个节点后,需要做的是向组中添加新的节点。这里以添加mysql02和mysql03为例。
前面多次提到,新节点在加入组的时候,会先选择一个donor,并通过异步复制的方式从这个donor处获取缺失的数据,以便在成功加入组的时候它的数据和组中已有的节点是完全同步的,这样才能向外界客户端提供查询。
这里的重点在于异步复制,既然是复制,它就需要复制binlog,并通过应用binlog中的记录来写数据。如果在加入组之前,组中的数据量已经非常大,那么这个异步复制的过程会很慢,而且还会影响donor的性能,毕竟它要传输大量数据出去。
本来加入新节点的目的就是对组复制进行扩展,提高它的均衡能力,现在因为异步复制慢,反而导致性能稍有下降,新节点短期内还无法上线向外提供服务。这有点背离原本的目标。
再者,如果组中的节点purge过日志,那么新节点将无法从donor上获取完整的数据。这时新节点上的恢复过程会让它重新选择下一个donor。但很可能还是会失败,因为实际环境中,既然purge了某节点上的一段日志,很可能同时会去所有节点上也Purge。(注意,purge不是事件,不会写入到binlog中,所以不会复制到其它节点上,换句话说,某节点Purge后,那么它的binlog和其它节点的binlog是不一致的)。
所以,在新节点加入组之前,应该先通过备份恢复的方式,从组中某节点上备份目前的数据到新节点上,然后再让新节点去加组,这样加组的过程将非常快,且能保证不会因为purge的原因而加组失败。至于如何备份恢复,这里不多说
我这里做实验的环境,所有节点都是刚安装好的全新实例,数据量小,也没purge过日志,所以直接加入到组中就可以。
# 登陆mysql
mysql -u root -p123456 -S /data/mysql/tmp/mysql.sock
# 构建组复制通道
change master to master_user="repl",master_password="123456" for channel "group_replication_recovery";
# 开启组复制
start group_replication;
# 查看到添加到组复制集群的服务器信息
select * from performance_schema.replication_group_members;
mysql> show variables like "group_replication%";
+-----------------------------------------------------+-------------------------------------------+
| Variable_name | Value |
+-----------------------------------------------------+-------------------------------------------+
| group_replication_advertise_recovery_endpoints | DEFAULT |
| group_replication_allow_local_lower_version_join | OFF |
| group_replication_auto_increment_increment | 7 |
| group_replication_autorejoin_tries | 3 |
| group_replication_bootstrap_group | OFF |
| group_replication_clone_threshold | 9223372036854775807 |
| group_replication_communication_debug_options | GCS_DEBUG_NONE |
| group_replication_communication_max_message_size | 10485760 |
| group_replication_components_stop_timeout | 31536000 |
| group_replication_compression_threshold | 1000000 |
| group_replication_consistency | EVENTUAL |
| group_replication_enforce_update_everywhere_checks | OFF |
| group_replication_exit_state_action | READ_ONLY |
| group_replication_flow_control_applier_threshold | 25000 |
| group_replication_flow_control_certifier_threshold | 25000 |
| group_replication_flow_control_hold_percent | 10 |
| group_replication_flow_control_max_quota | 0 |
| group_replication_flow_control_member_quota_percent | 0 |
| group_replication_flow_control_min_quota | 0 |
| group_replication_flow_control_min_recovery_quota | 0 |
| group_replication_flow_control_mode | QUOTA |
| group_replication_flow_control_period | 1 |
| group_replication_flow_control_release_percent | 50 |
| group_replication_force_members | |
| group_replication_group_name | ce9be252-2b71-11e6-b8f4-00212844f856 |
| group_replication_group_seeds | mysql01:33061,mysql02:33061,mysql02:33061 |
| group_replication_gtid_assignment_block_size | 1000000 |
| group_replication_ip_allowlist | AUTOMATIC |
| group_replication_ip_whitelist | AUTOMATIC |
| group_replication_local_address | mysql01:33061 |
| group_replication_member_expel_timeout | 5 |
| group_replication_member_weight | 50 |
| group_replication_message_cache_size | 1073741824 |
| group_replication_poll_spin_loops | 0 |
| group_replication_recovery_complete_at | TRANSACTIONS_APPLIED |
| group_replication_recovery_compression_algorithms | uncompressed |
| group_replication_recovery_get_public_key | OFF |
| group_replication_recovery_public_key_path | |
| group_replication_recovery_reconnect_interval | 60 |
| group_replication_recovery_retry_count | 10 |
| group_replication_recovery_ssl_ca | |
| group_replication_recovery_ssl_capath | |
| group_replication_recovery_ssl_cert | |
| group_replication_recovery_ssl_cipher | |
| group_replication_recovery_ssl_crl | |
| group_replication_recovery_ssl_crlpath | |
| group_replication_recovery_ssl_key | |
| group_replication_recovery_ssl_verify_server_cert | OFF |
| group_replication_recovery_tls_ciphersuites | |
| group_replication_recovery_tls_version | TLSv1,TLSv1.1,TLSv1.2,TLSv1.3 |
| group_replication_recovery_use_ssl | OFF |
| group_replication_recovery_zstd_compression_level | 3 |
| group_replication_single_primary_mode | ON |
| group_replication_ssl_mode | DISABLED |
| group_replication_start_on_boot | OFF |
| group_replication_tls_source | MYSQL_MAIN |
| group_replication_transaction_size_limit | 150000000 |
| group_replication_unreachable_majority_timeout | 0 |
+-----------------------------------------------------+-------------------------------------------+
58 rows in set (0.01 sec)
# 登陆mysql
mysql -u root -p123456 -S /data/mysql/tmp/mysql.sock
# 查看配置
show variables like "%read_only%";
在mysql01(主服务器)上创建数据
# 登陆mysql
mysql -u root -p123456 -S /data/mysql/tmp/mysql.sock
# 创建数据库
create database test;
# 切换数据库
use test;
# 创建表
create table user(id int key,name varchar(20));
# 插入数据
insert into user values(1,"zhangsan");
我们可以看到,2个从节点都有数据了。
# mysql03 机器
[root@mysql03 ~]# ifconfig ens32 down
2022-04-27T07:09:24.769741Z 0 [Warning] [MY-011493] [Repl] Plugin group_replication reported: 'Member with address mysql03:3306 has become unreachable.'
2022-04-27T07:09:41.309689Z 0 [Warning] [MY-011499] [Repl] Plugin group_replication reported: 'Members removed from the group: mysql03:3306'
2022-04-27T07:09:41.309792Z 0 [System] [MY-011500] [Repl] Plugin group_replication reported: 'Primary server with address mysql03:3306 left the group. Electing new Primary.'
2022-04-27T07:09:42.318138Z 0 [System] [MY-011507] [Repl] Plugin group_replication reported: 'A new primary with address mysql02:3306 was elected. The new primary will execute all previous group transactions before allowing writes.'
2022-04-27T07:09:42.319861Z 0 [System] [MY-011503] [Repl] Plugin group_replication reported: 'Group membership changed to mysql02:3306, mysql01:3306 on view 16507706540186162:6.'
2022-04-27T07:09:42.323422Z 31 [System] [MY-011566] [Repl] Plugin group_replication reported: 'Setting super_read_only=OFF.'
2022-04-27T07:09:42.325000Z 31 [System] [MY-011510] [Repl] Plugin group_replication reported: 'This server is working as primary member.'
这里将mysql02选为新的主节点,且告知成员视图中目前组中成员变为mysql02和mysql03。
# 登陆mysql
mysql -u root -p123456 -S /data/mysql/tmp/mysql.sock
# 切换数据库
use test;
# 插入数据
insert into user values(3,"zhangsan3");
# 查询
select * from user;
可以向新的主节点mysql02中插入数据。
# mysql01 机器
[root@mysql01 ~]# ifconfig ens32 down
mysql> insert into user values(4,"zhangsan4");
发现无法插入,一直阻塞。
2022-04-27T07:41:14.764884Z 0 [Warning] [MY-011493] [Repl] Plugin group_replication reported: 'Member with address mysql01:3306 has become unreachable.'
2022-04-27T07:41:14.764953Z 0 [ERROR] [MY-011495] [Repl] Plugin group_replication reported: 'This server is not able to reach a majority of members in the group. This server will now block all updates. The server will remain blocked until contact with the majority is restored. It is possible to use group_replication_force_members to force a new group membership.'
[root@mysql02 logs]#
已经说明了,mysql01移除后,组中的成员无法达到大多数的要求,所以将复制组给阻塞了。如果想要修复组,可以强制生成一个新的组成员视图。
ifconfig ens32 up
将mysql01和mysql03的网卡启动,mysql01和mysql03会加入到组中,且没有脑裂现象