一、MySQL集群核心理论

1 核心定义

MySQL集群(MySQL Cluster)是由MySQL AB公司(后被Oracle收购)开发的分布式数据库解决方案,核心是将MySQL数据库的存储、计算、连接等功能拆分到多个节点,通过节点间的协同工作,实现数据的高可用、高并发、可扩展,同时保证数据的一致性和可靠性。

本质:基于分布式架构,将数据分片存储在多个节点,节点间通过专用通信协议同步数据、协调任务,对外提供统一的数据库访问入口,屏蔽底层节点的分布式细节,让用户像使用单节点MySQL一样操作集群。

核心前提:集群中所有节点需处于同一网络环境(通常是局域网),节点间通信延迟低、稳定性高,避免因网络问题导致数据同步异常或集群故障。

2 核心价值(为什么要用集群)

2.1 高可用性(High Availability)

核心目标:避免单点故障,确保数据库服务持续可用。单节点MySQL一旦出现硬件故障、软件崩溃、网络中断等问题,服务会完全中断;而集群通过多节点冗余部署,当某一个或多个节点故障时,其他正常节点可立即接管服务,实现“无停机”或“秒级停机”切换,保障业务连续运行。

关键指标:可用性达到99.99%以上(每年停机时间不超过52分钟),核心场景(如电商、金融)可通过多副本部署进一步提升可用性。

2.2 高并发处理能力(High Concurrency)

单节点MySQL的并发连接数、QPS(每秒查询数)存在上限(受CPU、内存、IO等硬件限制),当业务并发量突破单节点瓶颈时,会出现查询延迟、连接超时等问题。

集群通过“负载均衡”将并发请求分发到多个节点,每个节点承担部分请求压力,从而整体提升集群的并发处理能力,支持 thousands 级甚至 tens of thousands 级的并发连接。

2.3 可扩展性(Scalability)

业务增长过程中,数据量会持续增加(如从GB级增长到TB级、PB级),单节点的存储和计算能力无法满足需求。MySQL集群支持“横向扩展”(增加节点数量),无需停机,即可扩展存储容量和计算能力,适配业务的动态增长。

对比:单节点只能“纵向扩展”(升级CPU、内存、硬盘),扩展成本高、上限低,且升级过程中需停机,影响业务。

2.4 数据可靠性(Data Reliability)

集群通过“数据副本”机制,将同一份数据存储在多个节点(通常是2-3个副本),当某一个节点的数据损坏或丢失时,可从其他副本节点恢复数据,避免数据丢失。同时,数据同步过程会进行校验,确保副本数据与主数据一致。

3 核心架构分类(主流类型)

MySQL集群的架构核心是“节点角色拆分”,不同角色的节点承担不同的功能,主流架构分为三类,其中主从复制架构最常用,Galera Cluster和NDB Cluster适用于特定场景。

3.1 主从复制架构(Master-Slave Replication)

(1)架构组成

  • 主节点(Master):唯一的写节点,负责接收所有写请求(INSERT、UPDATE、DELETE),并将写操作记录到二进制日志(binlog)。
  • 从节点(Slave):只读节点(可配置为读写,但不推荐),通过IO线程读取主节点的binlog,通过SQL线程将binlog中的操作在本地重放,实现与主节点的数据同步。
  • 可选组件:中继日志(relay log),从节点接收的binlog先存储到中继日志,再由SQL线程读取重放,避免直接操作主节点binlog,提升稳定性。

(2)核心原理

  1. 主节点开启binlog,每执行一次写操作,就将操作记录到binlog中(按时间顺序记录,不可篡改)。
  2. 从节点启动IO线程,与主节点建立连接,请求主节点发送binlog(从指定的位置开始读取)。
  3. 主节点启动binlog dump线程,将binlog内容逐段发送给从节点的IO线程。
  4. 从节点的IO线程将接收的binlog写入本地中继日志,SQL线程读取中继日志,将其中的操作逐行执行,实现主从数据同步。

(3)特点

  • 优点:架构简单、部署成本低、易维护,适合读多写少的场景(如博客、新闻网站),可通过增加从节点提升读并发。
  • 缺点:存在主从延迟(binlog同步需要时间,通常是毫秒级,极端情况可达秒级),主节点是单点故障(主节点故障后,需手动切换到从节点),写并发受主节点限制。

3.2 Galera Cluster(同步多主集群)

(1)架构组成

所有节点都是主节点(Multi-Master),无主从之分,每个节点都可接收写请求,节点间通过Galera协议实现数据同步,确保所有节点的数据一致。

核心组件:Galera插件(需安装在每个MySQL节点上),负责节点间的通信、数据同步和一致性校验。

(2)核心原理

采用“同步复制”机制,当某一个节点执行写操作时,会先将操作发送给集群中所有其他节点,待所有节点确认执行成功后,再向客户端返回“操作成功”,确保所有节点的数据实时一致,无主从延迟。

容错机制:集群中最多允许(节点数-1)/2个节点故障,剩余节点仍可正常提供服务(如3个节点可允许1个故障,5个节点可允许2个故障)。

(3)特点

  • 优点:无主从延迟、支持多节点写并发,故障自动切换(无需手动干预),可用性高,适合写多读少、对数据一致性要求高的场景(如金融交易、电商订单)。
  • 缺点:部署复杂、成本高,写操作性能略低(需等待所有节点确认),节点数量不宜过多(通常3-5个节点)。

3.3 NDB Cluster(内存集群)

(1)架构组成

  • 管理节点(Management Node):负责集群的配置、监控和节点管理,是集群的“大脑”,不存储数据、不处理请求。
  • 数据节点(Data Node):负责存储数据,数据存储在内存中(可配置持久化到磁盘),支持数据分片,多个数据节点共同承担存储压力。
  • SQL节点(SQL Node):负责接收客户端的SQL请求,解析SQL并分发到数据节点执行,返回结果给客户端,相当于“查询入口”。

(2)核心原理

数据分片:将表中的数据按指定规则(如哈希、范围)拆分到多个数据节点,每个数据节点存储部分数据,提升存储和查询效率;数据副本:每个数据分片会存储多个副本(通常2个),确保数据可靠性;所有操作通过管理节点协调,数据节点间通过专用协议同步数据。

(3)特点

  • 优点:读写性能极高(数据在内存中),支持海量数据分片存储,高可用、高容错,适合对性能要求极高、数据量极大的场景(如游戏、日志分析)。
  • 缺点:部署复杂、内存成本高,不适合大量写操作(内存写入虽快,但同步成本高),对SQL语法有一定限制。

4 关键技术

4.1 数据分片(Sharding)

定义:将数据库中的大表,按指定规则(分片键)拆分成多个小表,每个小表存储在不同的节点上,实现数据的分布式存储。

核心目的:解决单节点存储容量不足、查询效率低的问题,提升集群的存储和查询性能。

常见分片方式:

  • 哈希分片:以分片键(如用户ID)的哈希值为依据,将数据均匀分配到多个节点,优点是数据分布均匀,缺点是无法范围查询(如查询ID在1-1000的用户)。
  • 范围分片:以分片键的范围为依据(如时间、ID范围),将数据分配到不同节点,优点是支持范围查询,缺点是数据可能分布不均(如某一时间段数据量过大)。
  • 列表分片:按分片键的具体值列表分配数据(如按地区分片:北京、上海的数据存节点A,广州、深圳的数据存节点B),适合有明确分类的场景。

4.2 数据复制(Replication)

定义:将一个节点(主节点)的数据,复制到其他节点(从节点/副本节点),确保多个节点的数据一致,是实现高可用、数据可靠性的核心技术。

常见复制类型:

  • 异步复制(默认,主从复制常用):主节点执行写操作后,立即向客户端返回成功,同时异步将binlog发送给从节点,从节点异步重放。优点是写性能高,缺点是存在主从延迟,主节点故障可能导致数据丢失。
  • 半同步复制(主从复制优化):主节点执行写操作后,需等待至少一个从节点确认接收binlog后,再向客户端返回成功。优点是减少数据丢失风险,缺点是写性能略有下降。
  • 同步复制(Galera Cluster常用):主节点执行写操作后,需等待所有副本节点确认执行成功后,再返回客户端。优点是数据实时一致,无延迟,缺点是写性能较低。

4.3 负载均衡(Load Balancing)

定义:将客户端的请求,根据节点的负载情况(CPU、内存、IO使用率、连接数),合理分发到多个节点,避免单个节点过载,提升集群的整体并发处理能力。

常见实现方式:

  • 硬件负载均衡:通过专用硬件设备(如F5、NetScaler)分发请求,性能高、稳定性强,适合大型集群,成本高。
  • 软件负载均衡:通过软件(如Nginx、HAProxy)分发请求,成本低、配置灵活,适合中小型集群,性能略低于硬件负载均衡。
  • MySQL自带负载均衡:如Galera Cluster的内置负载均衡,可自动分发请求到不同节点,无需额外部署软件/硬件。

4.4 故障检测与自动切换(Failover)

核心目的:当集群中的节点出现故障时,自动检测故障节点,将故障节点的任务切换到正常节点,确保服务不中断,是实现高可用的关键。

核心流程:

  1. 故障检测:通过节点间的心跳机制(定期发送检测包),判断节点是否正常(如心跳中断超过阈值,判定为节点故障)。
  2. 故障隔离:将故障节点从集群中隔离,避免其影响集群正常运行(如停止向故障节点分发请求)。
  3. 任务切换:将故障节点的任务(如主节点的写任务、从节点的读任务)切换到正常节点(如主从复制中,将从节点提升为主节点)。
  4. 恢复同步:故障节点修复后,重新加入集群,同步缺失的数据,恢复正常服务。

常见工具:MHA(Master High Availability,主从复制架构的自动切换工具)、Galera Cluster内置自动切换功能。

5 核心特性与限制

5.1 核心特性

  • 透明性:对外提供统一的数据库访问入口,用户无需关心底层节点的分布和操作,像使用单节点MySQL一样操作集群。
  • 一致性:通过数据复制、校验机制,确保集群中所有节点的数据一致(不同架构的一致性级别不同,如Galera是强一致性,主从复制是最终一致性)。
  • 容错性:支持节点故障,故障节点修复后可自动重新加入集群,不影响整体服务。
  • 可管理性:通过管理工具(如MySQL Cluster Manager、MHA),可实现集群的配置、监控、运维、故障排查。

5.2 主要限制

  • 复杂度高:集群部署、配置、运维难度远高于单节点MySQL,需要专业的运维人员。
  • 成本高:需要多个服务器节点,硬件、网络成本增加;同时,运维成本也更高。
  • 性能损耗:节点间的数据同步、请求分发会产生一定的性能损耗(如同步复制的写性能损耗)。
  • 语法限制:部分MySQL语法在集群中不支持(如NDB Cluster不支持外键、存储过程),需适配集群架构。

6 适用场景与选型建议

6.1 适用场景

  • 读多写少,并发量高:如博客、新闻、电商商品列表,适合主从复制架构(主节点写,多从节点读)。
  • 写多读少,数据一致性要求高:如金融交易、电商订单、支付系统,适合Galera Cluster(同步多主,无延迟)。
  • 数据量大,性能要求极高:如游戏日志、用户行为分析,适合NDB Cluster(内存存储,分片部署)。
  • 业务连续性要求高:如核心业务系统,需避免单点故障,适合任何一种集群架构(优先Galera Cluster)。

6.2 选型建议

  • 中小型业务、读多写少、预算有限:优先选择主从复制架构(部署简单、成本低)。
  • 中大型业务、写并发高、数据一致性要求高:选择Galera Cluster(多主同步、自动故障切换)。
  • 海量数据、高并发读写、性能要求极高:选择NDB Cluster(内存存储、分片扩展)。
  • 核心业务、无停机需求:建议搭配负载均衡工具和自动切换工具,提升集群可用性。

7 核心总结

  1. MySQL集群的核心目标是解决单节点的单点故障、并发瓶颈、存储限制,实现高可用、高并发、可扩展。
  2. 三大主流架构各有侧重:主从复制(简单、低成本,读多写少)、Galera Cluster(同步多主、高一致,写多读少)、NDB Cluster(内存、高性能,海量数据)。
  3. 关键技术支撑:数据分片(扩展存储)、数据复制(保证一致)、负载均衡(提升并发)、故障切换(保证可用)。
  4. 选型核心:结合业务的读写比例、数据量、性能要求、预算,选择合适的架构,避免过度设计。

二、 MySQL 集群基础与进阶实验

1 Mysql的源码编译

1.1 下载安装包

1
wget https://downloads.mysql.com/archives/get/p/23/file/mysql-boost-8.3.0.tar.gz

1.2 源码编译

1
2
3
4
5
6
7
8
9
10
[root@mysql ~]# dnf install cmake3 gcc git bison openssl-devel ncurses-devel systemd-devel rpcgen.x86_64 libtirpc-devel-1.3.3-9.el9.x86_64.rpm  gcc-toolset-12-gcc gcc-toolset-12-gcc-c++ gcc-toolset-12-binutils gcc-toolset-12-annobin-annocheck gcc-toolset-12-annobin-plugin-gcc -y

[root@mysql ~]# tar zxf mysql-boost-8.3.0.tar.gz
[root@mysql mysql-8.3.0]# mkdir build
[root@mysql mysql-8.3.0]# cd build/

[root@mysql build]# cmake3 .. -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/data/mysql -DMYSQL_UNIX_ADDR=/data/mysql/mysql.sock -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_EXTRA_CHARSETS=all -DDEFAULT_CHARSET=utf8mb4 -DDEFAULT_COLLATION=utf8mb4_unicode_ci -DWITH_BOOST=bundled -DWITH_SSL=system -DWITH_DEBUG=OFF


[root@mysql build]# make

1.3 部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@mysql build]# make install
[root@mysql build]# cd /usr/local/mysql/

[root@mysql mysql]# vim ~/.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi

# User specific environment and startup programs
export PATH=$PATH:/usr/local/mysql/bin #设置mysql运行环境的环境变量


[root@mysql mysql]# source ~/.bash_profile

[root@mysql mysql]# useradd -r -s /sbin/nologin -M mysql

[root@mysql mysql]# mkdir -p /data/mysql
[root@mysql mysql]# chown mysql.mysql /data/mysql/

[root@mysql ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0

1.4 数据结构初始化

1
[root@mysql ~]# mysqld --initialize --user=mysql

1.5 启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@mysql ~]# dnf install initscripts-10.11.8-4.el9.x86_64 -y

[root@mysql ~]# cd /usr/local/mysql/support-files/
[root@mysql support-files]# ls
mysqld_multi.server mysql-log-rotate mysql.server
[root@mysql support-files]# cp -p mysql.server /etc/init.d/mysqld



[root@mysql support-files]# /etc/init.d/mysqld start
Starting MySQL.Logging to '/data/mysql/mysql.err'.
SUCCESS!

#开机启动
[root@mysql support-files]# chkconfig --level 35 mysqld on

1.6 安全初始化

1
2
[root@mysql ~]# mysql_secure_installation

1.7 从机部署MySQL

(1)从主机发送编译好的MySQL

1
scp -rp /usr/local/mysql root@:172.25.254.130/usr/local

(2)后续同主机[部署](#1.3 部署)

2 MySQ集群实验

2.1 主从复制(库内无数据)

(1)编写主配置文件(my.cnf)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Master
[root@mysql ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0

server-id=10
log-bin=mysql-bin

# Slave1
[root@MySQL2 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0

server-id=20
log-bin=mysql-bin

# Slave2
[root@MySQL3 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0

server-id=30
log-bin=mysql-bin


#在三台主机中重启数据库
[root@mysql ~]# /etc/init.d/mysqld restart
Shutting down MySQL. SUCCESS!
Starting MySQL. SUCCESS!

(2)建立数据库账号

  • master
1
2
3
4
5
6
[root@mysql-node1 ~]# mysql -uroot -ppasswd
mysql> SHOW VARIABLES LIKE 'default_authentication_plugin';
mysql> create user hua@'%' identified with mysql_native_password by 'hua';
mysql> select User from mysql.user;
mysql> GRANT replication slave ON *.* to 'hua'@'%';
mysql> SHOW GRANTS FOR 'hua'@'%';

  • slave1 or 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@MySQL2 ~]# mysql -uhua -phua -h172.25.254.129
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 8.3.0 Source distribution

Copyright (c) 2000, 2024, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> quit
Bye

(3)配置数据库一主一从

  • master
1
2
#查看日志文件名称及id
mysql> SHOW MASTER STATUS;

  • slave
1
2
3
4
[root@mysql-node2 ~]# mysql -uroot -ppasswd
mysql> CHANGE MASTER TO SOURCE_HOST='172.25.254.129',SOURCE_USER='hua',SOURCE_PASSWORD='hua',SOURCE_LOG_FILE='mysql-bin.000001',SOURCE_LOG_POS=158;
mysql> START REPLICA ;
mysql> SHOW REPLICA STATUS\G;

RESET REPLICA ALL; 重置副本(从机)

RESET MASTER ALL; 重置副本(主机)

(4)测试

  • master
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@mysql ~]# mysql -uroot -ppasswd
mysql> CREATE DATABASE IF NOT EXISTS test;
Query OK, 1 row affected (0.00 sec)

mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.00 sec)
  • slave
1
2
3
4
5
6
7
8
9
10
11
12
[root@MySQL2 ~]# mysql -uroot -ppasswd
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
5 rows in set (0.01 sec)

2.2 主从复制(库内有数据)

(1)向当前一主一从中加入新的数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#模拟一主一从中已经存在数据情况
[root@mysql ~]# mysql -uroot -ppasswd
mysql> CREATE TABLE test.userlist (
-> name VARCHAR(10) not null,
-> pass VARCHAR(50) not null
-> );
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO test.userlist values ('user1','123');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM test.userlist;
+-------+------+
| name | pass |
+-------+------+
| user1 | 123 |
+-------+------+
1 row in set (0.01 sec)


#加入新从库时需要手动拉平数据
[root@mysql ~]# mysqldump -uroot -ppasswd test > test.sql
[root@mysql ~]# scp test.sql root@172.25.254.131:/root/

[root@MySQL3 ~]# mysql -uroot -ppasswd -e "create database test;"
[root@MySQL3 ~]# mysql -uroot -ppasswd test < test.sql

[root@MySQL3 ~]# mysql -uroot -ppasswd
mysql> select * from test.userlist;
+-------+------+
| name | pass |
+-------+------+
| user1 | 123 |
+-------+------+
1 row in set (0.00 sec)

(2)将新库加入主从结构中

1
2
#在master中查看日志的id
mysql> SHOW MASTER STATUS;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@MySQL3 ~]# mysql -uroot -ppasswd

mysql> STOP REPLICA;
Query OK, 0 rows affected (0.00 sec)

mysql> CHANGE MASTER TO MASTER_HOST='172.25.254.129',MASTER_USER='hua',MASTER_PASSWORD='hua',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=1388;
Query OK, 0 rows affected, 8 warnings (0.00 sec)


mysql> START REPLICA;
Query OK, 0 rows affected (0.00 sec)


mysql> show replica status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 172.25.254.129
Master_User: hua
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 1388
Relay_Log_File: MySQL3-relay-bin.000002
Relay_Log_Pos: 328
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

(3)测试

1
2
3
4
5
6
7
8
9
10
11
12
#在master中建立数据
mysql> INSERT INTO test.userlist values ('user2','123');

#在新加入的slave中查看信息
mysql> select * from test.userlist;
+-------+------+
| name | pass |
+-------+------+
| user1 | 123 |
| user2 | 123 |
+-------+------+
2 rows in set (0.00 sec)

3 MySQL集群优化

3.1 延迟复制

  • slave

    1
    2
    3
    4
    5
    6
    7
    #安装数据库的版本 >= 8.0
    [root@MySQL2 ~]# mysql -uroot -ppasswd
    mysql> STOP REPLICA;
    mysql> CHANGE REPLICATION SOURCE TO SOURCE_DELAY=60;
    mysql> START REPLICA;
    mysql> SHOW REPLICA STATUS\G
    SQL_Delay: 60 # 延迟时间1min
  • master

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    [root@MySQL ~]# mysql -uroot -ppasswd
    mysql> show databases;
    +--------------------+
    | Database |
    +--------------------+
    | information_schema |
    | mysql |
    | performance_schema |
    | sys |
    | test |
    +--------------------+
    mysql> delete from test.userlist where name='user1';
    mysql> select * from test.userlist;
    +-------+------+
    | name | pass |
    +-------+------+
    | user2 | 123 |
    +-------+------+
  • slave

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #在未被延迟的slave数据库中查看是否数据操作动作被同步
    mysql> select * from timinglee.userlist;
    +-------+------+
    | name | pass |
    +-------+------+
    | user2 | 123 |
    +-------+------+

    #在被设定延迟复制的主机中查看动作是否被同步
    mysql> select * from timinglee.userlist;
    +-------+------+
    | name | pass |
    +-------+------+
    | user1 | 123 |
    | user2 | 123 |
    +-------+------+

    #等待延迟时间过后再次查看
    mysql> select * from timinglee.userlist;
    +-------+------+
    | name | pass |
    +-------+------+
    | user2 | 123 |
    +-------+------+

3.2 慢查询日志

  • master

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    #慢查询日志是否开启
    mysql> SHOW variables like "slow%";
    +---------------------+----------------------------+
    | Variable_name | Value |
    +---------------------+----------------------------+
    | slow_launch_time | 2 |
    | slow_query_log | OFF |
    | slow_query_log_file | /data/mysql/mysql-slow.log |
    +---------------------+----------------------------+


    #开启慢查询日志
    mysql> SET GLOBAL slow_query_log=ON;
    Query OK, 0 rows affected (0.01 sec)

    mysql> SHOW variables like "slow%";
    +---------------------+----------------------------+
    | Variable_name | Value |
    +---------------------+----------------------------+
    | slow_launch_time | 2 |
    | slow_query_log | ON |
    | slow_query_log_file | /data/mysql/mysql-slow.log |
    +---------------------+----------------------------+
    3 rows in set (0.00 sec)



    #检测慢查询日志
    mysql> SHOW VARIABLES like "long%"; #慢查询阈值
    +-----------------+-----------+
    | Variable_name | Value |
    +-----------------+-----------+
    | long_query_time | 10.000000 |
    +-----------------+-----------+
    1 row in set (0.01 sec)
    mysql> SET long_query_time=4;
    Query OK, 0 rows affected (0.00 sec)

    mysql> SHOW VARIABLES like "long%";
    +-----------------+----------+
    | Variable_name | Value |
    +-----------------+----------+
    | long_query_time | 4.000000 |
    +-----------------+----------+
    1 row in set (0.00 sec)

    mysql> select sleep (3); #不会生成慢查询日志
    +-----------+
    | sleep (3) |
    +-----------+
    | 0 |
    +-----------+
    1 row in set (3.00 sec)

    mysql> select sleep (4);
    +-----------+
    | sleep (4) |
    +-----------+
    | 0 |
    +-----------+
    1 row in set (4.00 sec)

    [root@MySQL ~]# cat /data/mysql/mysql-slow.log
    /usr/local/mysql/bin/mysqld, Version: 8.3.0 (Source distribution). started with:
    Tcp port: 3306 Unix socket: /data/mysql/mysql.sock
    Time Id Command Argument
    # Time: 2026-02-27T02:30:07.869255Z
    # User@Host: root[root] @ localhost [] Id: 12
    # Query_time: 4.001001 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 1
    SET timestamp=1772159403;
    select sleep (4);

3.3 gtid模式

在master和slave中默认gtid模式是未开启的

1
show variables like '%gtid%';
image-20260227105433474
  • master + slave

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    [root@MySQL1~3 ~]# vim /etc/my.cnf
    gtid_mode=ON
    enforce-gtid-consistency=ON

    [root@MySQL1~3 ~]# /etc/init.d/mysqld restart

    #在三台主机中分别查看gtid模式是否开启
    mysql> show variables like '%gtid%';
    +----------------------------------+-----------+
    | Variable_name | Value |
    +----------------------------------+-----------+
    | binlog_gtid_simple_recovery | ON |
    | enforce_gtid_consistency | ON |
    | gtid_executed | |
    | gtid_executed_compression_period | 0 |
    | gtid_mode | ON |
    | gtid_next | AUTOMATIC |
    | gtid_owned | |
    | gtid_purged | |
    | session_track_gtids | OFF |
    +----------------------------------+-----------+
    9 rows in set (0.00 sec)
  • slave

    1
    2
    3
    4
    5
    6
    7
    #在从库中停止slave功能;
    mysql> STOP REPLICA;

    mysql> CHANGE MASTER TO MASTER_HOST='172.25.254.129', MASTER_USER='hua', MASTER_PASSWORD='hua', MASTER_AUTO_POSITION=1;

    mysql> START REPLICA;
    mysql> SHOW REPLICA STATUS \G;

    image-20260227111009046

3.4 多线程回放

  • slave

    1
    2
    #在slave主机中默认回方日志时使用单线程回放
    mysql> show processlist;

    image-20260227111244818

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #开启多线程回放日志
    [root@MySQL2 ~]# vim /etc/my.cnf
    slave-parallel-type=LOGICAL_CLOCK
    slave-parallel-workers=16
    relay_log_recovery=ON

    [root@MySQL2 ~]# /etc/init.d/mysqld restart

    #查看更改生效信息
    mysql> show processlist;

    image-20260227111502378

3.5 半同步模式

  • master

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #在master主机中操作
    [root@mysql-node1~3 ~]# vim /etc/my.cnf
    rpl_semi_sync_master_enabled=1 # 启用半同步复制

    mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; # 安装半同步复制的主库插件
    mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;

    mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%'; #验证安装
    +----------------------+---------------+
    | PLUGIN_NAME | PLUGIN_STATUS |
    +----------------------+---------------+
    | rpl_semi_sync_master | ACTIVE |
    +----------------------+---------------+

    mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%';
    +-------------------------------------------+------------+
    | Variable_name | Value |
    +-------------------------------------------+------------+
    | rpl_semi_sync_master_enabled | ON | # 主库半同步开关是否开启(ON=开启,OFF=关闭)
    | rpl_semi_sync_master_timeout | 10000 | # 主库等待从库确认的超时时间(单位:毫秒,默认10秒)
    | rpl_semi_sync_master_trace_level | 32 | # 调试跟踪级别(默认值,无需修改)
    | rpl_semi_sync_master_wait_for_slave_count | 1 | # 主库需要等待至少多少个从库确认(默认1个)
    | rpl_semi_sync_master_wait_no_slave | ON | # 无可用从库时,是否等待后降级为异步(ON=是)
    | rpl_semi_sync_master_wait_point | AFTER_SYNC | # 主库等待时机(AFTER_SYNC=写binlog后等,更安全)
    +-------------------------------------------+------------+

    mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
    +--------------------------------------------+-------+
    | Variable_name | Value |
    +--------------------------------------------+-------+
    | Rpl_semi_sync_master_clients | 1 | # 已连接的半同步从库数量(至少1个才会走半同步)
    | Rpl_semi_sync_master_net_avg_wait_time | 0 | # 等待从库确认的平均网络时间
    | Rpl_semi_sync_master_net_wait_time | 0 | # 累计等待从库确认的网络时间
    | Rpl_semi_sync_master_net_waits | 0 | # 累计等待从库确认的次数
    | Rpl_semi_sync_master_no_times | 0 | # 降级为异步的次数(超时/无从库)
    | Rpl_semi_sync_master_no_tx | 0 | # 未走半同步的事务数
    | Rpl_semi_sync_master_status | ON | # 当前主库是否处于半同步模式(核心字段)
    | Rpl_semi_sync_master_timefunc_failures | 0 | # 时间函数失败次数(异常排查用)
    | Rpl_semi_sync_master_tx_avg_wait_time | 0 | # 事务等待从库确认的平均时间
    | Rpl_semi_sync_master_tx_wait_time | 0 | # 累计事务等待时间
    | Rpl_semi_sync_master_tx_waits | 0 | # 累计事务等待次数
    | Rpl_semi_sync_master_wait_pos_backtraverse | 0 | # 等待位置回退次数
    | Rpl_semi_sync_master_wait_sessions | 0 | # 正在等待从库确认的会话数
    | Rpl_semi_sync_master_yes_tx | 0 | # 成功走半同步的事务数
    +--------------------------------------------+-------+
  • slave

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    [root@MySQL2+3 ~]# vim /etc/my.cnf
    rpl_semi_sync_slave_enabled=1

    mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
    mysql> SET GLOBAL rpl_semi_sync_slave_enabled =1;
    mysql> STOP SLAVE IO_THREAD;
    mysql> START SLAVE IO_THREAD;

    mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'rpl_semi_sync_slave';
    +---------------------+---------------+
    | PLUGIN_NAME | PLUGIN_STATUS |
    +---------------------+---------------+
    | rpl_semi_sync_slave | ACTIVE |
    +---------------------+---------------+
  • 测试

    • master

      1
      2
      3
      4
      mysql> create database test2;
      Query OK, 1 row affected (10.01 sec) #有等待ack时间

      mysql> INSERT INTO test.userlist values ('user3','123'); # 写入数据
    • slave

      1
      mysql> STOP SLAVE IO_THREAD;  #模拟ack故障
    • master

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      # 查看效果
      mysql> INSERT INTO test.userlist values ('user3','123');
      Query OK, 1 row affected (10.01 sec) # ack故障时间

      mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
      +--------------------------------------------+-------+
      | Variable_name | Value |
      +--------------------------------------------+-------+
      | Rpl_semi_sync_master_clients | 0 |
      | Rpl_semi_sync_master_net_avg_wait_time | 0 |
      | Rpl_semi_sync_master_net_wait_time | 0 |
      | Rpl_semi_sync_master_net_waits | 4 |
      | Rpl_semi_sync_master_no_times | 1 |
      | Rpl_semi_sync_master_no_tx | 1 |
      | Rpl_semi_sync_master_status | OFF |
      | Rpl_semi_sync_master_timefunc_failures | 0 |
      | Rpl_semi_sync_master_tx_avg_wait_time | 570 |
      | Rpl_semi_sync_master_tx_wait_time | 1712 |
      | Rpl_semi_sync_master_tx_waits | 3 |
      | Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
      | Rpl_semi_sync_master_wait_sessions | 0 |
      | Rpl_semi_sync_master_yes_tx | 3 |
      +--------------------------------------------+-------+
    • slave

      1
      2
      #恢复故障
      mysql> START SLAVE IO_THREAD;

4 MySQL高可用

4.1 MHA

(1) 配置Mha-manager

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
[root@MHA ~]# unzip MHA-7.zip
Archive: MHA-7.zip
creating: MHA-7/
inflating: MHA-7/master_ip_failover
inflating: MHA-7/master_ip_online_change
inflating: MHA-7/mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
inflating: MHA-7/mha4mysql-manager-0.58.tar.gz
inflating: MHA-7/mha4mysql-node-0.58-0.el7.centos.noarch.rpm
inflating: MHA-7/perl-Config-Tiny-2.14-7.el7.noarch.rpm
inflating: MHA-7/perl-Email-Date-Format-1.002-15.el7.noarch.rpm
inflating: MHA-7/perl-Log-Dispatch-2.41-1.el7.1.noarch.rpm
inflating: MHA-7/perl-Mail-Sender-0.8.23-1.el7.noarch.rpm
inflating: MHA-7/perl-Mail-Sendmail-0.79-21.el7.noarch.rpm
inflating: MHA-7/perl-MIME-Lite-3.030-1.el7.noarch.rpm
inflating: MHA-7/perl-MIME-Types-1.38-2.el7.noarch.rpm
inflating: MHA-7/perl-Net-Telnet-3.03-19.el7.noarch.rpm
inflating: MHA-7/perl-Parallel-ForkManager-1.18-2.el7.noarch.rpm
[root@MHA ~]# dnf install perl perl-DBD-MySQL perl-CPAN -y
[root@MHA ~]# cd MHA-7/
[root@mha MHA-7]# cpan
Loading internal logger. Log::Log4perl recommended for better logging

CPAN.pm requires configuration, but most of it can be done automatically.
If you answer 'no' below, you will enter an interactive dialog for each
configuration option instead.

Would you like to configure as much as possible automatically? [yes] yes

cpan[1]> install Config::Tiny

cpan[2]> install Log::Dispatch

cpan[3]> install Mail::Sender
Specify defaults for Mail::Sender? (y/N) y
Default encoding of message bodies (N)one, (Q)uoted-printable, (B)ase64: n

cpan[4]> install Parallel::ForkManager
cpan[5]> exit

[root@mha MHA-7]# rpm -ivh mha4mysql-manager-0.58-0.el7.centos.noarch.rpm mha4mysql-node-0.58-0.el7.centos.noarch.rpm --nodeps

在slave中安装相应软件

1
2
3
4
5
6
[root@MHA MHA-7]# for i in 129 130 131
> do
> scp mha4mysql-node-0.58-0.el7.centos.noarch.rpm root@172.25.254.$i:/mnt
> ssh -l root 172.25.254.$i "rpm -ivh /mnt/mha4mysql-node-0.58-0.el7.centos.noarch.rpm --nodeps"
> done

修改MHA-Manager中的检测代码

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@mha MHA-7]# vim /usr/share/perl5/vendor_perl/MHA/NodeUtil.pm
199 #sub parse_mysql_major_version($) {
200 # my $str = shift;
201 # my $result = sprintf( '%03d%03d', $str =~ m/(\d+)/g );
202 # return $result;
203 #}

sub parse_mysql_major_version($) {
my $str = shift;
my @nums = $str =~ m/(\d+)/g;
my $result = sprintf( '%03d%03d', $nums[0]//0, $nums[1]//0);
return $result;
}

未MHA建立远程登录用户

1
2
3
4
5
6
#在master主机中
mysql> create user root@'%' identified with mysql_native_password by 'lee';
Query OK, 0 rows affected (0.01 sec)

mysql> GRANT ALL ON *.* TO root@'%' ;
Query OK, 0 rows affected (0.00 sec)

生成MHA-manager的配置文件模板

1
2
3
4
5
[root@mha MHA-7]# tar zxf mha4mysql-manager-0.58.tar.gz
[root@mha MHA-7]# cd mha4mysql-manager-0.58
[root@mha mha4mysql-manager-0.58]# mkdir /etc/masterha/ -p

[root@mha mha4mysql-manager-0.58]# cat samples/conf/masterha_default.cnf samples/conf/app1.cnf > /etc/masterha/app1.cnf

修改配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
user=root
password=passwd
ssh_user=root
repl_user=hua
repl_password=hua
master_binlog_dir=/data/mysql
remote_workdir=/tmp
secondary_check_script= masterha_secondary_check -s 172.25.254.129 -s 172.25.254
.2
ping_interval=3
# master_ip_failover_script= /script/masterha/master_ip_failover
# shutdown_script= /script/masterha/power_manager
# report_script= /script/masterha/send_report
# master_ip_online_change_script= /script/masterha/master_ip_online_change
[server default]
manager_workdir=/etc/masterha
manager_log=/etc/masterha/mha.log

[server1]
hostname=172.25.254.129
candidate_master=1
check_repl_delay=0

[server2]
hostname=172.25.254.130
candidate_master=1
check_repl_delay=0

[server3]
hostname=172.25.254.131
no_master=1

检测环境

1
2
masterha_check_ssh  --conf=/etc/masterha/app1.cnf
masterha_check_repl --conf=/etc/masterha/app1.cnf

特:

1
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'passwd';

4.2 MGA

I. 通过Ansible控制子节点实现还原

  • ansible安装与配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # 配置仓库
    [root@MHA ~]# cat > /etc/yum.repos.d/epel.repo <<EOF
    > [epel]
    > name = epel
    > baseurl = https://mirrors.aliyun.com/epel-archive/9.6/Everything/x86_64/
    > gpgcheck = 0
    > EOF
    # 安装软件包
    [root@MHA ~]# dnf install ansible -y
    # 验证安装
    [root@MHA ~]# ansible --version
    ansible [core 2.14.18]
    config file = /etc/ansible/ansible.cfg
    configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
    ansible python module location = /usr/lib/python3.9/site-packages/ansible
    ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
    executable location = /usr/bin/ansible
    python version = 3.9.21 (main, Feb 10 2025, 00:00:00) [GCC 11.5.0 20240719 (Red Hat 11.5.0-5)] (/usr/bin/python3)
    jinja version = 3.1.2
    libyaml = True
  • 创建普通用户与密码,保障权限安全问题

    1
    2
    3
    4
    5
    [root@MHA ~]# useradd devops
    [root@MHA ~]# echo hua | passwd --stdin devops
    更改用户 devops 的密码 。
    [root@MHA ~]# su - devops
    [devops@MHA ~]$ mkdir ansible
  • 创建配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    [devops@MHA ansible]$ vim inventory
    [mysql]
    172.25.254.129
    172.25.254.130
    172.25.254.131

    [devops@MHA ansible]$ cat >ansible.cfg <<EOF
    > [defaults]
    > inventory=./inventory
    > remote_user=root
    > host_key_checking=false
    > [privilege_escalation]
    > become=False
    > EOF


  • 通过主节点控制子节点

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 创建 devops 用户
    ansible mysql -m user -a 'name=devops'
    # 设置 devops 用户密码
    ansible mysql -m shell -a 'echo devops | passwd --stdin devops'
    # 配置 devops 用户免密 sudo 权限
    ansible mysql -m shell -a 'echo "devops ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers'
    # 创建 devops 用户的 .ssh 目录并设置权限
    ansible all -m file -a 'path=/home/devops/.ssh owner=devops group=devops mode="0700" state=directory'
    # 复制 SSH 公钥到 devops 用户的 authorized_keys 文件
    ansible all -m copy -a 'src=/home/devops/.ssh/authorized_keys dest=/home/devops/.ssh/authorized_keys owner=devops group=devops mode="0600"'
  • 配置免密

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [devops@MHA ansible]$ cat >ansible.cfg <<EOF
    > [defaults]
    > inventory=./inventory
    > remote_user=devops
    > host_key_checking=false
    >
    > [privilege_escalation]
    > become=True
    > become_ask_pass=False
    > become_method=sudo
    > become_user=root
    > EOF
  • 验证

    1
    2
    3
    4
    5
    6
    7
    [devops@mha ansible]$ ansible all -m shell -a 'whoami'
    172.25.254.20 | CHANGED | rc=0 >>
    root
    172.25.254.30 | CHANGED | rc=0 >>
    root
    172.25.254.10 | CHANGED | rc=0 >>
    root
  • 编辑自动部署配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    [devops@mha ansible]$ vim clear_mysql.yml
    - name: 重 新 部 署 MySQL
    hosts: mysql
    tasks:
    - name: 停 止 MySQL
    shell: '/etc/init.d/mysqld stop'
    ignore_errors: yes

    - name: 删 除 MySQL 数 据
    file:
    path: /data/mysql
    state: absent

    - name: 创 建 MySQL 数 据 文 件
    file:
    path: /data/mysql
    state: directory
    owner: mysql
    group: mysql

    - name: 初 始 化 MySQL
    shell: '/usr/local/mysql/bin/mysqld --initialize --user=mysql'

    [devops@mha ansible]$ ansible-playbook clear_mysql.yml -vv | grep password

II. 手动还原方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#所有节点初始化数据
[root@MySQL ~]# /etc/init.d/mysqld stop
[root@MySQL ~]# rm -rf /data/mysql/*

[root@MySQL ~]# cat > /etc/my.cnf <<EOF
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0

server-id=131 #不同主机server-id一定要根据实际情况做相应改变
log-bin=mysql-bin

gtid_mode=ON
enforce-gtid-consistency=ON
default_authentication_plugin=mysql_native_password
log_slave_updates=ON
binlog_format=ROW
binlog_checksum=NONE
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
EOF

[root@MySQL ~]# mysqld --user=mysql --initialize

III. 部署组复制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#设置所有mysql节点的解析
[root@MySQL ~]# cat > /etc/hosts <<EOF
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.129 MySQL
172.25.254.130 MySQL2
172.25.254.131 MySQL3
EOF


[root@MySQL ~]# cat >> /etc/my.cnf <<EOF
plugin_load_add='group_replication.so'
group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
group_replication_start_on_boot=off
group_replication_local_address="172.25.254.129:33061" #其他两台主机一定要根据ip进行修改
group_replication_group_seeds="172.25.254.129:33061,172.25.254.130:33061,172.25.254.131:33061"
group_replication_bootstrap_group=off
group_replication_single_primary_mode=OFF
EOF
[root@MySQL ~]# /etc/init.d/mysqld start

#配置组复制-在首台主机中
[root@MySQL ~]# mysql -uroot -p't,Wr(Llw8iJ%'
# 修改 root 本地登录密码
mysql> alter user root@localhost identified by 'passwd';
# 临时关闭二进制日志
mysql> SET SQL_LOG_BIN=0;
# 创建组复制专用账号
mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'hua';
# 授权复制从库权限
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;
# 配置组复制恢复通道的认证信息
mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user', SOURCE_PASSWORD='hua' FOR CHANNEL 'group_replication_recovery';
# 查看组复制插件是否激活
mysql> SHOW PLUGINS;
| group_replication | ACTIVE | GROUP REPLICATION | group_replication.so | GPL |

# 开启组复制集群引导模式
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
# 启动组复制 (初始化集群)
mysql> START GROUP_REPLICATION USER='rpl_user', PASSWORD='hua';
# 关闭集群引导模式
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
# 查看集群成员状态
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | MEMBER_COMMUNICATION_STACK |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
| group_replication_applier | 9deb2f12-1d36-11f1-8bcf-000c290a9be9 | MySQL | 3306 | ONLINE | PRIMARY | 8.3.0 | XCom |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+


#配置组复制在其余主机中
[root@MySQL2 ~]# mysql -uroot -p'TL-i#p7jmm7g'
mysql> alter user root@localhost identified by 'passwd';
mysql> SET SQL_LOG_BIN=0;
mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'hua';
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> SET SQL_LOG_BIN=1;
mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user',SOURCE_PASSWORD='hua' FOR CHANNEL 'group_replication_recovery';


mysql> START GROUP_REPLICATION USER='rpl_user', PASSWORD='hua';
ERROR 3092 (HY000): The server is not configured properly to be an active member of the group. Please see more details on error log. #出现此处报错可以初始化下master
mysql> reset master; #用过此命令解决以上报错
mysql> START GROUP_REPLICATION USER='rpl_user', PASSWORD='hua';


mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | MEMBER_COMMUNICATION_STACK |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+
| group_replication_applier | 9dd0ef97-1d36-11f1-b9bd-000c2945f2a1 | MySQL3 | 3306 | ONLINE | PRIMARY | 8.3.0 | XCom |
| group_replication_applier | 9dd19686-1d36-11f1-b889-000c29cad506 | MySQL2 | 3306 | ONLINE | PRIMARY | 8.3.0 | XCom |
| group_replication_applier | 9deb2f12-1d36-11f1-8bcf-000c290a9be9 | MySQL | 3306 | ONLINE | PRIMARY | 8.3.0 | XCom |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+----------------------------+


#看到主机online表示成功