Mysql 8.0.35 MGR集群实施配置
提示
本文为站长原创文章,版权所有,未经允许,禁止转载!
信息
数据库环境信息: 
操作系统:CentOS Server 7.9  64bit
Mysql数据库版本:mysql 8.0.35 Community Server 64bit
IP地址对应关系:
192.168.99.131  mysql01
192.168.99.132  mysql02
192.168.99.133  mysql03
一、MGR介绍
MySQL MGR(MySQL Group Replication)是MySQL官方推出的一种高可用性和可扩展性解决方案。它基于组复制(Group Replication)技术,为MySQL数据库提供了内置的分布式数据库集群解决方案。
MySQL Group Replication允许多个MySQL实例组成一个复制集群,其中每个实例都可以处理读写请求。集群中的所有实例都能够接收客户端的读写操作,并通过复制协议将这些操作同步到其他实例上,以确保数据的一致性。
MySQL Group Replication的特点包括:
1. 自动容错:当集群中的节点出现故障时,集群能够自动进行故障转移,从而确保系统的高可用性。新的节点可以自动加入集群,并且集群能够自动调整以适应变化。
2. 一致性:集群中的所有节点都保持数据的一致性,因此客户端可以向任何节点发送读写请求,而不必担心数据不一致的问题。
3. 扩展性:MySQL Group Replication支持动态扩展,可以根据负载的变化来扩展集群的规模,从而提高系统的处理能力。
二、配置
1、系统配置
cat /etc/security/limits.conf 
* hard nofile 65535
* soft nofile 65535
# 生效配置
ulimit -a
cat /etc/sysctl.d/99-sysctl.conf 
# shared memory
#kernel.shmmax = 34359738368
#kernel.shmall = 8388609
#kernel.shmmni = 4096
# semaphore
kernel.sem = 250 32000 100 128
# network
net.core.somaxconn = 4096
net.unix.max_dgram_qlen = 256 
net.core.netdev_max_backlog=8192
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
# file
fs.file-max = 65535
# 生效配置
sysctl -p
cat /usr/lib/systemd/system/mysql80.service 
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql80
Group=mysql80
LimitNOFILE=65535
LimitNPROC=65535
Type=forking
# Disable service start and stop timeout logic of systemd for mysqld service.
TimeoutSec=0
 
# Execute pre and post scripts as root
PermissionsStartOnly=true
PIDFile=/opt/mysql80/run/mysqld.pid
# Start main service
ExecStart=/opt/mysql80/8.0.35/bin/mysqld --defaults-file=/home/mysql80/my.cnf --daemonize $MYSQLD_OPTS
Restart=on-failure
RestartPreventExitStatus=1
PrivateTmp=false
# 设置为自动启动
systemctl enable mysql80
systemctl start mysql80
systemctl status mysql80
# 修改配置后
systemctl daemon-reload
2、数据库配置
# repl 用户创建用于复制
mysql> create user repl@'192.168.99.%' identified with mysql_native_password by  'aaronqlm'; 
mysql> grant replication slave on *.* to repl@'192.168.99.%'; 
# 创建一个普通数据库和赋予权限
create database aaronqlm
create user aaronqlm IDENTIFIED with mysql_native_password BY by 'aaronqlm';   # 在后续版本中不再可用
create user aaronqlm IDENTIFIED with caching_sha2_password BY by 'aaronqlm';   # default_authentication_plugin
grant all privileges on aaronqlm.* to aaronqlm;
# 创建表t1
CREATE TABLE t1 (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(10),
    mark VARCHAR(100)
);
# 插入100w条数据
drop PROCEDURE insert_t1_million_records;
DELIMITER //
CREATE PROCEDURE insert_t1_million_records()
BEGIN
    DECLARE counter INT DEFAULT 0;
    START TRANSACTION;
    WHILE counter < 1000000 DO
        INSERT INTO t1 (name, mark) VALUES (CONCAT('name', counter), CONCAT('mark', counter));
        SET counter = counter + 1;
    END WHILE;
    COMMIT;
END//
DELIMITER ;
call insert_t1_million_records()
3、MGR配置
# 初始化
mysqld --initialize --user=mysql80 --basedir /opt/mysql80/8.0.35 --datadir /opt/mysql80/data
# my.cnf
# node1
[mysql80@mysql01 ~]$ cat my.cnf 
[mysqld]
basedir = '/opt/mysql80/8.0.35'
datadir = '/opt/mysql80/data'
port = 3308
socket = '/opt/mysql80/run/mysql.sock'
default-time_zone = '+8:00'
pid-file = '/opt/mysql80/run/mysqld.pid'
log_error_verbosity = 3
log-error = '/opt/mysql80/log/mysqld-err.log'
secure-file-priv = '/opt/mysql80/secure-file'
table_open_cache = 8192
skip_name_resolve = ON
slave_parallel_workers=4
server_id = 1
mysqlx = OFF
gtid-mode = on
enforce-gtid-consistency = true
report_host = '192.168.99.131'
sql_require_primary_key = 1
loose-plugin_load_add = 'mysql_clone.so'
loose-plugin_load_add = 'group_replication.so'
loose-group_replication_group_name = '59831f0c-ffd6-4e06-ab6d-e2fdb0e47b25' 
loose-group_replication_start_on_boot = 0 
loose-group_replication_local_address = '192.168.99.131:13308'
loose-group_replication_group_seeds = '192.168.99.131:13308,192.168.99.132:13308,192.168.99.133:13308'
loose-group_replication_bootstrap_group = OFF
loose-group_replication_flow_control_mode = 'DISABLED'
loose-group_replication_single_primary_mode = ON
loose-group_replication_ip_whitelist = '192.168.99.0/24'
transaction_isolation = READ-COMMITTED
#node 2
[mysql80@mysql02 ~]$ cat my.cnf 
[mysqld]
basedir = '/opt/mysql80/8.0.35'
datadir = '/opt/mysql80/data'
port = 3308
socket = '/opt/mysql80/run/mysql.sock'
default-time_zone = '+8:00'
pid-file = '/opt/mysql80/run/mysqld.pid'
log_error_verbosity = 3
log-error = '/opt/mysql80/log/mysqld-err.log'
secure-file-priv = '/opt/mysql80/secure-file'
table_open_cache = 8192
skip_name_resolve = ON
slave_parallel_workers=4
server_id = 2
mysqlx = OFF
gtid-mode = on
enforce-gtid-consistency = true
report_host = '192.168.99.132'
sql_require_primary_key = 1
loose-plugin_load_add = 'mysql_clone.so'
loose-plugin_load_add = 'group_replication.so'
loose-group_replication_group_name = '59831f0c-ffd6-4e06-ab6d-e2fdb0e47b25' 
loose-group_replication_start_on_boot = 0 
loose-group_replication_local_address = '192.168.99.132:13308'
loose-group_replication_group_seeds = '192.168.99.131:13308,192.168.99.132:13308,192.168.99.133:13308'
loose-group_replication_bootstrap_group = OFF
loose-group_replication_flow_control_mode = 'DISABLED'
loose-group_replication_single_primary_mode = ON
loose-group_replication_ip_whitelist = '192.168.99.0/24'
transaction_isolation = READ-COMMITTED
# node3
[mysql80@mysql03 ~]$ cat my.cnf 
[mysqld]
basedir = '/opt/mysql80/8.0.35'
datadir = '/opt/mysql80/data'
port = 3308
socket = '/opt/mysql80/run/mysql.sock'
default-time_zone = '+8:00'
pid-file = '/opt/mysql80/run/mysqld.pid'
log_error_verbosity = 3
log-error = '/opt/mysql80/log/mysqld-err.log'
secure-file-priv = '/opt/mysql80/secure-file'
table_open_cache = 8192
skip_name_resolve = ON
slave_parallel_workers=4
server_id = 3
mysqlx = OFF
gtid-mode = on
enforce-gtid-consistency = true
report_host = '192.168.99.133'
sql_require_primary_key = 1
loose-plugin_load_add = 'mysql_clone.so'
loose-plugin_load_add = 'group_replication.so'
loose-group_replication_group_name = '59831f0c-ffd6-4e06-ab6d-e2fdb0e47b25' 
loose-group_replication_start_on_boot = 0 
loose-group_replication_local_address = '192.168.99.133:13308'
loose-group_replication_group_seeds = '192.168.99.131:13308,192.168.99.132:13308,192.168.99.133:13308'
loose-group_replication_bootstrap_group = OFF
loose-group_replication_flow_control_mode = 'DISABLED'
loose-group_replication_single_primary_mode = ON
loose-group_replication_ip_whitelist = '192.168.99.0/24'
transaction_isolation = READ-COMMITTED
# 安装复制插件(所有节点)配置文件中有了
# mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
# 设置复制账号 ( 所有节点 )  
$ mysql -S /opt/mysql80/run/mysql.sock -uroot -pmysql
SET SQL_LOG_BIN=0;  
drop user repl;
drop user repl@'localhost';
drop user repl@'127.0.0.1';
CREATE USER repl@'%' IDENTIFIED with mysql_native_password BY 'mysql';
CREATE USER repl@'localhost' IDENTIFIED with mysql_native_password BY 'mysql';
CREATE USER repl@'127.0.0.1' IDENTIFIED with mysql_native_password BY 'mysql';
GRANT REPLICATION SLAVE,replication client ON *.* TO repl@'%';
GRANT REPLICATION SLAVE,replication client on *.* to repl@'localhost';
GRANT REPLICATION SLAVE,replication client on *.* to repl@'127.0.0.1';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;
# 启动 MGR ,在主库 (99.131) 上执行  
stop slave;
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='mysql' FOR CHANNEL 'group_replication_recovery';
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SELECT * FROM performance_schema.replication_group_members;
## 等所有节点加入进来后再设置为OFF
SET GLOBAL group_replication_bootstrap_group=OFF;
# 其他节点加入 MGR ,在从库上执行  
# 默认启动了slave
stop slave;
reset master;
CHANGE MASTER TO MASTER_USER='repl' , MASTER_PASSWORD='mysql' FOR CHANNEL 'group_replication_recovery';
# CHANGE MASTER TO master_host='192.168.99.131' , MASTER_PORT=3308 , MASTER_USER='repl', MASTER_PASSWORD='mysql';
START GROUP_REPLICATION;  
三、参数说明
1. `skip_name_resolve`: 这个参数在连接授权时禁用对主机名的反向解析,可以加快客户端连接的速度。
2. `master_info_repository=TABLE`: 表示用表存储主服务器复制信息。
3. `relay_log_info_repository=TABLE`: 表示用表存储中继日志信息。
4. `report_host=10.0.0.51`: 指定MySQL实例向复制集报告的主机名或IP地址。
5. `report_port=13306`: 指定MySQL实例向复制集报告的端口号。
6. `socket=/tmp/mysql13306.sock`: 指定MySQL实例的Unix套接字文件路径。
7. `default_authentication_plugin=mysql_native_password`: 指定默认的身份验证插件为`mysql_native_password`。
8. `binlog_checksum=NONE`: 指定binlog的校验和类型为NONE,表示不进行校验和。
9. `mysqlx=off`: 禁用MySQL X协议。
## group_replication 变量使用的 loose- 前缀是指示 Server 启用时尚未加载复制插件也将继续启动  
## 指示 Server 必须为每个事务收集写集合,并使用 XXHASH64 哈希算法将其编码为散列  [8.0.35默认值]
transaction_write_set_extraction = XXHASH64  
## 表示将加入或者创建的复制组命名为 01e5fb97-be64-41f7-bafd-3afc7a6ab555  
## 可自定义 ( 通过 cat /proc/sys/kernel/random/uuid)  
loose-group_replication_group_name='01e5fb97-be64-41f7-bafd-3afc7a6ab555'  
## 设置为 Server 启动时不自动启动组复制  
loose-group_replication_start_on_boot=off  
## 绑定本地的 192.168.29.128 及 33061 端口接受其他组成员的连接, IP 地址必须为其他组成员可正常访问  
loose-group_replication_local_address='192.168.29.128:33061'  
## 本行为告诉服务器当服务器加入组时,应当连接到  
## 这些种子服务器进行配置。本设置可以不是全部的组成员服务地址。  
loose-group_replication_group_seeds='192.168.29.128:33061,192.168.29.128:33062,192.168.29.128:33063'
## 配置是否自动引导组  
# 设置group_replication_bootstrap_group为ON是为了标示以后加入集群的服务器以这台服务器为基准,以后加入的就不需要设置 (只在其中一个节点上设置)
loose-group_replication_bootstrap_group = off  
## 配置白名单,默认情况下只允许 192.168.29.128 连接到复制组,如果是其他 IP 则需要配置。  
loose-group_replication_ip_whitelist=”10.30.0.0/16,10.31.0..0/16,10.27.0.0/16″
## binlog_transaction_dependency_tracking = WRITESET  
#  提高并发度, WRITESET 要求所有的表都要有主键。  - 8.0 的新技术 。
# 建表/alter表时要求必须表必须有主键
sql_require_primary_key=1
#当退出MGR后,把该实例设置为read_only,避免误操作写入数据
loose-group_replication_exit_state_action=READ_ONLY
#一般没什么必要开启流控机制
loose-group_replication_flow_control_mode = 'DISABLED'
#【强烈】建议只用单主模式,如果是实验目的,可以尝试玩玩多主模式
loose-group_replication_single_primary_mode=ON
四、自动化建库脚本
1、删库脚本
[mysql80@mysql01 ~]$ cat rm_mysqldb.sh 
#!/bin/bash
echo "Do you want to delete all the DB? (y/n)"
read response
echo "mysql" |sudo -S /bin/systemctl stop mysql80
if [ "$response" = "y" ]; then
    echo "Deleting the file..."
    rm -rf /opt/mysql80/data/*
    rm -rf /opt/mysql80/log/*
    rm -rf /opt/mysql80/run/*
    echo "mysql" |sudo -S rm -rf /opt/mysql80/secure-file/*
    echo "All File deleted."
else
    echo "File not deleted."
fi
2、建库初始化脚本
初始主节点 mysql01
[mysql80@mysql01 ~]$ cat  createdb.sh 
#!/bin/bash
echo "Do you want to delete all the DB? (y/n)"
read response
if [ "$response" = "y" ]; then
    echo "mysql" |sudo -S /bin/systemctl stop mysql80
    sleep 2
    
    echo "Deleting the file..."
    rm -rf /opt/mysql80/data/*
    rm -rf /opt/mysql80/log/*
    rm -rf /opt/mysql80/run/*
    echo "mysql" |sudo -S rm -rf /opt/mysql80/secure-file/*
    echo "All File deleted."
    mysqld --initialize --user=mysql80 --basedir /opt/mysql80/8.0.35 --datadir /opt/mysql80/data &> createdb.tmp
    sleep 1
    rootpwd=`tail -1 createdb.tmp |sed 's/.*root@localhost: //'`
    rootpwd="'$rootpwd'"
    echo "mysql" |sudo -S /bin/systemctl start mysql80
    sleep 2
    
    mysql1="mysql -S /opt/mysql80/run/mysql.sock -uroot -p${rootpwd}"
    mysqlsh="$mysql1 --connect-expired-password -e \"alter user root@'localhost' identified by 'mysql';\""
    eval $mysqlsh &> /dev/null
    
    echo "正在创建数据库"
    mysql -S /opt/mysql80/run/mysql.sock -uroot -pmysql --connect-expired-password < mgr.sql 
    echo "mysql" |sudo -S /bin/systemctl stop mysql80
    echo "mysql" |sudo -S /bin/systemctl start mysql80
    sleep 2
    mysql -S /opt/mysql80/run/mysql.sock -uroot -pmysql --connect-expired-password < mgr2.sql
else
    echo "File not deleted."
fi
[mysql80@mysql01 ~]$ cat mgr.sql 
CREATE DATABASE IF NOT EXISTS aaronqlm;
create user aaronqlm identified by 'aaronqlm';
grant all privileges on aaronqlm.* to aaronqlm;
use aaronqlm;
CREATE TABLE t1 (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(10),
    mark VARCHAR(100)
);
commit;
DELIMITER //
CREATE PROCEDURE insert_t1_million_records()
BEGIN
    DECLARE counter INT DEFAULT 0;
    START TRANSACTION;
    WHILE counter < 1000000 DO
        INSERT INTO t1 (name, mark) VALUES (CONCAT('name', counter), CONCAT('mark', counter));
        SET counter = counter + 1;
    END WHILE;
    COMMIT;
END //
DELIMITER ;
commit;
call insert_t1_million_records();
commit;
[mysql80@mysql01 ~]$ cat mgr2.sql 
set SQL_LOG_BIN=0;
CREATE USER root  IDENTIFIED with mysql_native_password  BY 'mysql';
GRANT all privileges on *.* to root;
CREATE USER repl@'%'  IDENTIFIED with mysql_native_password  BY 'mysql';
CREATE USER repl@'localhost'  IDENTIFIED with mysql_native_password  BY 'mysql';
CREATE USER repl@'127.0.0.1'  IDENTIFIED with mysql_native_password  BY 'mysql';
GRANT REPLICATION SLAVE,replication client ON *.* TO repl@'%';
GRANT REPLICATION SLAVE,replication client on *.* to repl@'localhost';
GRANT REPLICATION SLAVE,replication client on *.* to repl@'127.0.0.1';
FLUSH PRIVILEGES;
commit;
SET SQL_LOG_BIN=1;
commit;
stop slave;
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='mysql' FOR CHANNEL 'group_replication_recovery';
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SELECT * FROM performance_schema.replication_group_members;
commit;
第二节点
[mysql80@mysql02 ~]$ cat createdb.sh
#!/bin/bash
echo "Do you want to delete all the DB? (y/n)"
read response
if [ "$response" = "y" ]; then
    echo "mysql" |sudo -S /bin/systemctl stop mysql80
    sleep 2
    
    echo "Deleting the file..."
    rm -rf /opt/mysql80/data/*
    rm -rf /opt/mysql80/log/*
    rm -rf /opt/mysql80/run/*
    echo "mysql" |sudo -S rm -rf /opt/mysql80/secure-file/*
    echo "All File deleted."
    mysqld --initialize --user=mysql80 --basedir /opt/mysql80/8.0.35 --datadir /opt/mysql80/data &> createdb.tmp
    sleep 1
    rootpwd=`tail -1 createdb.tmp |sed 's/.*root@localhost: //'`
    rootpwd="'$rootpwd'"
    echo "mysql" |sudo -S /bin/systemctl start mysql80
    sleep 2
    
    mysql1="mysql -S /opt/mysql80/run/mysql.sock -uroot -p${rootpwd}"
    mysqlsh="$mysql1 --connect-expired-password -e \"alter user root@'localhost' identified by 'mysql';\""
    eval $mysqlsh &> /dev/null
    
    sleep 2
    mysql -S /opt/mysql80/run/mysql.sock -uroot -pmysql --connect-expired-password < mgr.sql
else
    echo "File not deleted."
fi
[mysql80@mysql02 ~]$ cat mgr.sql 
set SQL_LOG_BIN=0;
CREATE USER root  IDENTIFIED with mysql_native_password  BY 'mysql';
GRANT all privileges on *.* to root;
CREATE USER repl@'%'  IDENTIFIED with mysql_native_password  BY 'mysql';
CREATE USER repl@'localhost'  IDENTIFIED with mysql_native_password  BY 'mysql';
CREATE USER repl@'127.0.0.1'  IDENTIFIED with mysql_native_password  BY 'mysql';
GRANT REPLICATION SLAVE,replication client ON *.* TO repl@'%';
GRANT REPLICATION SLAVE,replication client on *.* to repl@'localhost';
GRANT REPLICATION SLAVE,replication client on *.* to repl@'127.0.0.1';
FLUSH PRIVILEGES;
commit;
SET SQL_LOG_BIN=1;
commit;
stop slave;
reset master;
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='mysql' FOR CHANNEL 'group_replication_recovery';
START GROUP_REPLICATION;
SELECT * FROM performance_schema.replication_group_members;
commit;
第三节点
[mysql80@mysql03 ~]$ cat createdb.sh
#!/bin/bash
echo "Do you want to delete all the DB? (y/n)"
read response
if [ "$response" = "y" ]; then
    echo "mysql" |sudo -S /bin/systemctl stop mysql80
    sleep 2
    
    echo "Deleting the file..."
    rm -rf /opt/mysql80/data/*
    rm -rf /opt/mysql80/log/*
    rm -rf /opt/mysql80/run/*
    echo "mysql" |sudo -S rm -rf /opt/mysql80/secure-file/*
    echo "All File deleted."
    mysqld --initialize --user=mysql80 --basedir /opt/mysql80/8.0.35 --datadir /opt/mysql80/data &> createdb.tmp
    sleep 1
    rootpwd=`tail -1 createdb.tmp |sed 's/.*root@localhost: //'`
    rootpwd="'$rootpwd'"
    echo "mysql" |sudo -S /bin/systemctl start mysql80
    sleep 2
    
    mysql1="mysql -S /opt/mysql80/run/mysql.sock -uroot -p${rootpwd}"
    mysqlsh="$mysql1 --connect-expired-password -e \"alter user root@'localhost' identified by 'mysql';\""
    eval $mysqlsh &> /dev/null
    
    sleep 2
    mysql -S /opt/mysql80/run/mysql.sock -uroot -pmysql --connect-expired-password < mgr.sql
else
    echo "File not deleted."
fi
[mysql80@mysql03 ~]$ cat mgr.sql 
set SQL_LOG_BIN=0;
CREATE USER root  IDENTIFIED with mysql_native_password  BY 'mysql';
GRANT all privileges on *.* to root;
CREATE USER repl@'%'  IDENTIFIED with mysql_native_password  BY 'mysql';
CREATE USER repl@'localhost'  IDENTIFIED with mysql_native_password  BY 'mysql';
CREATE USER repl@'127.0.0.1'  IDENTIFIED with mysql_native_password  BY 'mysql';
GRANT REPLICATION SLAVE,replication client ON *.* TO repl@'%';
GRANT REPLICATION SLAVE,replication client on *.* to repl@'localhost';
GRANT REPLICATION SLAVE,replication client on *.* to repl@'127.0.0.1';
FLUSH PRIVILEGES;
commit;
SET SQL_LOG_BIN=1;
commit;
stop slave;
reset master;
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='mysql' FOR CHANNEL 'group_replication_recovery';
START GROUP_REPLICATION;
SELECT * FROM performance_schema.replication_group_members;
commit;
五、关/开机流程
stop group_replication;
start group_replication;
六、参考语句
SELECT * FROM performance_schema.replication_group_members;
select * from performance_schema.replication_connection_status;