MySQL 8.3.0 运维与集群架构实战

实验目标回顾

通过本章实验,我们将系统掌握以下内容:

  • MySQL 8.3.0 源码编译与部署
  • 主从复制架构搭建(异步、GTID、半同步、延迟复制、多线程回放)
  • MHA 高可用集群部署与手动/自动切换
  • MySQL Group Replication(MGR)多主模式部署
  • MySQL Router 读写分离配置
  • 使用 Ansible 批量重置 MySQL 环境

核心知识点梳理

模块 关键知识点
源码编译 cmake3 参数、boost 依赖、数据目录初始化
主从复制 binlog、relay log、IO/SQL 线程、CHANGE MASTER TO
GTID MASTER_AUTO_POSITION=1、故障切换便利性
半同步复制 rpl_semi_sync_master/slave 插件、ACK 超时降级
延迟复制 SOURCE_DELAY=N、误操作快速恢复
多线程回放 slave_parallel_workersLOGICAL_CLOCK
MHA Manager/Node 架构、VIP 漂移、死主切换与活主切换
MGR 组复制多主模式、Paxos 一致性、节点 ONLINE 状态
Router 读写分离端口、round-robin/first-available 策略
Ansible inventory、playbook、批量初始化 MySQL

实验过程中遇到的问题及解决方法

(文章末尾)

一、Mysql的源码编译

下载安装包

bash 复制代码
[root@mysql-node1 ~]# wget https://downloads.mysql.com/archives/get/p/23/file/mysql-boost-8.3.0.tar.gz

源码编译

bash 复制代码
[root@mysql-node1 ~]# 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-node1 ~]# tar zxf mysql-boost-8.3.0.tar.gz
[root@mysql-node1 ~]# cd mysql-8.3.0/
[root@mysql-node1 mysql-8.3.0]# mkdir  build
[root@mysql-node1 mysql-8.3.0]# cd build/

[root@mysql-node1 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-node1 build]# make

部署mysql

bash 复制代码
[root@mysql-node1 build]# make install
[root@mysql-node1 build]# cd /usr/local/mysql/

[root@mysql-node1 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-node1 mysql]# source  ~/.bash_profile

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

[root@mysql-node1 mysql]# mkdir  -p /data/mysql
[root@mysql-node1 mysql]# chown mysql.mysql /data/mysql
#或者
[root@mysql-node1 mysql]# chown mysql:mysql /data/mysql

[root@mysql-node1 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=10

mysql数据结构初始化

bash 复制代码
[root@mysql-node1 build]# mysqld --initialize --user=mysql
2026-02-26T02:33:31.103872Z 0 [System] [MY-015017] [Server] MySQL Server Initialization - start.
2026-02-26T02:33:31.105547Z 0 [System] [MY-013169] [Server] /usr/local/mysql/bin/mysqld (mysqld 8.3.0) initializing of server in progress as process 40379
2026-02-26T02:33:31.116172Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2026-02-26T02:33:31.472616Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2026-02-26T02:33:32.329569Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: *cpw*U8whdXh
2026-02-26T02:33:34.042537Z 0 [System] [MY-015018] [Server] MySQL Server Initialization - end.

启动mysql

bash 复制代码
[root@mysql-node1 support-files]# dnf install initscripts-10.11.8-4.el9.x86_64 -y

[root@mysql-node1 support-files]# cd /usr/local/mysql/support-files/
[root@mysql-node1 support-files]# cp -p mysql.server  /etc/init.d/mysqld

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

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

注:该输出结果只显示 SysV 服务,并不包含
原生 systemd 服务。SysV 配置数据
可能被原生 systemd 配置覆盖。

      要列出 systemd 服务,请执行 'systemctl list-unit-files'。
      查看在具体 target 启用的服务请执行
      'systemctl list-dependencies [target]'。

mysqld          0:关    1:关    2:开    3:开    4:开    5:开    6:关

mysql的安全初始化

bash 复制代码
[root@mysql-node1 ~]# mysql_secure_installation
Securing the MySQL server deployment.

Enter password for user root:

The existing password for the user account root has expired. Please set a new password.

New password:

Re-enter new password:

VALIDATE PASSWORD COMPONENT can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD component?

Press y|Y for Yes, any other key for No: no
Using existing password for root.
Change the password for root ? ((Press y|Y for Yes, any other key for No) : no

Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Success.

Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Success.

By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.

Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
 - Dropping test database...
Success.

 - Removing privileges on test database...
Success.

Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.

All done!

mysql-node2完整配置

mysql-node3配置和2完全一致

开始前,在node1中执行

bash 复制代码
[root@mysql-node1 ~]# scp -rp /usr/local/mysql/ root@172.25.254.20:/usr/local/
bash 复制代码
[root@mysql-node2 ~]# useradd -r -s /sbin/nologin mysql
[root@mysql-node2 ~]# mkdir -p /data/mysql
[root@mysql-node2 ~]# chown mysql:mysql /data/mysql
[root@mysql-node2 ~]# vim ~/.bash_profile
#添加下面的内容
export PATH=$PATH:/usr/local/mysql/bin

[root@mysql-node2 ~]# source ~/.bash_profile
[root@mysql-node2 ~]# dnf whatprovides /etc/init.d
正在更新 Subscription Management 软件仓库。
无法读取客户身份

本系统尚未在权利服务器中注册。可使用 "rhc" 或 "subscription-manager" 进行注册。

上次元数据过期检查:42 days, 22:48:44 前,执行于 2026年01月14日 星期三 11时52分50秒。
chkconfig-1.24-2.el9.x86_64 : A system tool for maintaining the /etc/rc*.d hierarchy
仓库        :BaseOS
匹配来源:
文件名    :/etc/init.d

initscripts-10.11.8-4.el9.x86_64 : Basic support for legacy System V init scripts
仓库        :BaseOS
匹配来源:
文件名    :/etc/init.d

[root@mysql-node2 ~]# dnf install initscripts-10.11.8-4.el9.x86_64 -y
正在更新 Subscription Management 软件仓库。
无法读取客户身份

本系统尚未在权利服务器中注册。可使用 "rhc" 或 "subscription-manager" 进行注册。

AppStream                                            3.1 MB/s | 3.2 kB     00:00
BaseOS                                               2.7 MB/s | 2.7 kB     00:00
依赖关系解决。
=====================================================================================
 软件包               架构            版本                     仓库             大小
=====================================================================================
安装:
 initscripts          x86_64          10.11.8-4.el9            BaseOS          232 k
安装依赖关系:
 chkconfig            x86_64          1.24-2.el9               BaseOS          182 k

事务概要
=====================================================================================
安装  2 软件包

总计:414 k
安装大小:1.8 M
下载软件包:
运行事务检查
事务检查成功。
运行事务测试
事务测试成功。
运行事务
  准备中  :                                                                      1/1
  安装    : chkconfig-1.24-2.el9.x86_64                                          1/2
  安装    : initscripts-10.11.8-4.el9.x86_64                                     2/2
  运行脚本: initscripts-10.11.8-4.el9.x86_64                                     2/2
Created symlink /etc/systemd/system/sysinit.target.wants/import-state.service → /usr/                 lib/systemd/system/import-state.service.
Created symlink /etc/systemd/system/sysinit.target.wants/loadmodules.service → /usr/l                 ib/systemd/system/loadmodules.service.

  验证    : chkconfig-1.24-2.el9.x86_64                                          1/2
  验证    : initscripts-10.11.8-4.el9.x86_64                                     2/2
已更新安装的产品。

已安装:
  chkconfig-1.24-2.el9.x86_64            initscripts-10.11.8-4.el9.x86_64

完毕!
[root@mysql-node2 ~]# cp -p /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
[root@mysql-node2 ~]# mysqld --initialize --user=mysql
2026-02-26T02:45:08.428229Z 0 [System] [MY-015017] [Server] MySQL Server Initialization - start.
2026-02-26T02:45:08.430297Z 0 [System] [MY-013169] [Server] /usr/local/mysql/bin/mysqld (mysqld 8.3.0) initializing of server in progress as process 30340
2026-02-26T02:45:08.455321Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2026-02-26T02:45:09.587016Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2026-02-26T02:45:10.880631Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: dYrYIS,!S2G,
2026-02-26T02:45:13.183911Z 0 [System] [MY-015018] [Server] MySQL Server Initialization - end.
[root@mysql-node2 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=20

[root@mysql-node2 ~]# chkconfig mysqld on
[root@mysql-node2 ~]# /etc/init.d/mysqld start
Starting MySQL.Logging to '/data/mysql/mysql-node2.err'.
. SUCCESS!
[root@mysql-node2 ~]# mysql_secure_installation

Securing the MySQL server deployment.

Enter password for user root:

The existing password for the user account root has expired. Please set a new password.

New password:

Re-enter new password:

VALIDATE PASSWORD COMPONENT can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD component?

Press y|Y for Yes, any other key for No: no
Using existing password for root.
Change the password for root ? ((Press y|Y for Yes, any other key for No) : no

 ... skipping.
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.

Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Success.

Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Success.

By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.

Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
 - Dropping test database...
Success.

 - Removing privileges on test database...
Success.

Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.

All done!

[root@mysql-node2 ~]# mysql -uroot -pyu
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 8
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> \q
Bye

测试


二、Mysql集群实战--主从复制

编写my.cnf 主配置文件

bash 复制代码
[root@mysql-node1 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0

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

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

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

[root@mysql-node3 ~]# 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-node1 ~]# /etc/init.d/mysqld restart
Shutting down MySQL. SUCCESS!
Starting MySQL. SUCCESS!
[root@mysql-node2 ~]# /etc/init.d/mysqld restart
Shutting down MySQL. SUCCESS!
Starting MySQL. SUCCESS!
[root@mysql-node3 ~]# /etc/init.d/mysqld restart
Shutting down MySQL. SUCCESS!
Starting MySQL. SUCCESS!

建立同步时需要用到的数据库账号

bash 复制代码
[root@mysql-node1 ~]# mysql -uroot -pyu
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 8
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> show variables like 'default_authentication_plugin';
+-------------------------------+-----------------------+
| Variable_name                 | Value                 |
+-------------------------------+-----------------------+
| default_authentication_plugin | caching_sha2_password |
+-------------------------------+-----------------------+
1 row in set (0.00 sec)

mysql> create user yu@'%' identified with mysql_native_password by 'yu';
Query OK, 0 rows affected (0.01 sec)

mysql> select user from mysql.user;
+------------------+
| user             |
+------------------+
| yu               |
| mysql.infoschema |
| mysql.session    |
| mysql.sys        |
| root             |
+------------------+
5 rows in set (0.00 sec)

mysql> grant replication slave on *.* to yu@'%';
Query OK, 0 rows affected (0.00 sec)

mysql> show grants for yu@'%';
+--------------------------------------------+
| Grants for yu@%                            |
+--------------------------------------------+
| GRANT REPLICATION SLAVE ON *.* TO `yu`@`%` |
+--------------------------------------------+
1 row in set (0.00 sec)

mysql> \q
Bye

配置数据库一主一从

开始前需要在master主机中查看一下,找出bin文件和position

mysql 复制代码
[root@mysql-node1 ~]# mysql -uroot -pyu
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      657 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set, 1 warning (0.00 sec)
mysql 复制代码
#在slave主机中
[root@mysql-node2 ~]# mysql -uroot -pyu
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 8
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> change master to MASTER_HOST='172.25.254.10',MASTER_USER='yu',MASTER_PASSWORD='yu',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=657;
Query OK, 0 rows affected, 8 warnings (0.03 sec)

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 172.25.254.10
                  Master_User: yu
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 657
               Relay_Log_File: mysql-node2-relay-bin.000002
                Relay_Log_Pos: 328
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes					#数据同步成功
            Slave_SQL_Running: Yes					#通过同步过来的数据做日志回访成功

测试

mysql 复制代码
[root@mysql-node1 ~]# mysql -uroot -lee			#在master中建立库
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.01 sec)

mysql> create database liouo;
Query OK, 1 row affected (0.01 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| liouo              |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)

在slave主机中可以查看到数据

mysql 复制代码
[root@mysql-node2 ~]# mysql -uroot -pyu
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| liouo              |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)

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

mysql 复制代码
#模拟一主一从中已经存在数据情况
[root@mysql-node1 ~]# mysql -uroot -pyu
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 11
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> create table liouo.userlist (
    -> name varchar(10) not null,
    -> pass varchar(50) not null
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> use liouo;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> desc liouo.userlist;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| name  | varchar(10) | NO   |     | NULL    |       |
| pass  | varchar(50) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.01 sec)

mysql> insert into liouo.userlist values ('user1','123');
Query OK, 1 row affected (0.00 sec)

mysql> select * from liouo.userlist;
+-------+------+
| name  | pass |
+-------+------+
| user1 | 123  |
+-------+------+
1 row in set (0.00 sec)

# 加入新从库时需要手动拉平数据
[root@mysql-node1 ~]# mysqldump -uroot -pyu liouo > liouo.sql
[root@mysql-node1 ~]# scp liouo.sql root@172.25.254.30:/root/
liouo.sql                                                           100% 1939   946.4KB/s   00:00

# 在新加入的mysql-node3中
[root@mysql-node3 ~]# mysql -uroot -pyu -e "create database liouo;"
[root@mysql-node3 ~]# mysql -uroot -pyu liouo < liouo.sql

[root@mysql-node3 ~]# mysql -uroot -pyu

mysql> select * from liouo.userlist;
+-------+------+
| name  | pass |
+-------+------+
| user1 | 123  |
+-------+------+
1 row in set (0.00 sec)

将新库加入主从结构中

mysql 复制代码
#在master中查看日志的id
[root@mysql-node1 ~]# mysql -uroot -pyu
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |     1382 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set, 1 warning (0.00 sec)

[root@mysql-node3 ~]# mysql -uroot -pyu

mysql> change master to MASTER_HOST='172.25.254.10',MASTER_USER='yu',MASTER_PASSWORD='yu',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=1382;
Query OK, 0 rows affected, 8 warnings (0.03 sec)

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 172.25.254.10
                  Master_User: yu
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 1382
               Relay_Log_File: mysql-node3-relay-bin.000002
                Relay_Log_Pos: 328
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

测试一主两从

bash 复制代码
#在master中建立数据
[root@mysql-node1 ~]# mysqldump -uroot -pyu
mysql> insert into liouo.userlist values ('user2','123');
Query OK, 1 row affected (0.00 sec)

mysql> select * from liouo.userlist;
+-------+------+
| name  | pass |
+-------+------+
| user1 | 123  |
| user2 | 123  |
+-------+------+
2 rows in set (0.00 sec)

在新加入的slave中查看信息


三、mysql主从架构中的使用技巧及优化

延迟复制

mysql 复制代码
#在指定需要延迟同步的slave主机中,如果主机中安装数据库的版本是8以上
[root@mysql-node2 ~]# mysql -uroot -pyu
mysql> show slave status \G
*************************** 1. row ***************************
                    SQL_Delay: 0

mysql> stop replica;
Query OK, 0 rows affected (0.02 sec)

mysql> change replication source to SOURCE_DELAY=60;
Query OK, 0 rows affected (0.03 sec)

mysql> start replica;
Query OK, 0 rows affected (0.01 sec)

mysql> show slave status \G
*************************** 1. row ***************************
                    SQL_Delay: 60
# 或者直接执行
[root@mysql-node2 ~]# mysql -uroot -plee -e "show slave status\G;" | grep SQL_Delay
mysql: [Warning] Using a password on the command line interface can be insecure.
                    SQL_Delay: 60

在master主机中对数据进行更改

mysql 复制代码
[root@mysql-node1 ~]# mysql -uroot -pyu

mysql> delete from liouo.userlist where name='user1';
Query OK, 1 row affected (0.04 sec)

mysql> select * from liouo.userlist;
+-------+------+
| name  | pass |
+-------+------+
| user2 | 123  |
+-------+------+
1 row in set (0.00 sec)

在未被延迟的slave数据库中查看是否数据操作动作被同步

mysql 复制代码
[root@mysql-node3 ~]# mysql -uroot -pyu

mysql> show slave status \G
*************************** 1. row ***************************
                    SQL_Delay: 0

mysql> select * from liouo.userlist;
+-------+------+
| name  | pass |
+-------+------+
| user2 | 123  |
+-------+------+
1 row in set (0.00 sec)

直接在被设定延迟复制的主机mysql-node2上测试,看是否同步;等待延迟时间过后再次查看,信息是否同步

慢查询日志

mysql 复制代码
[root@mysql-node1 ~]# mysql -uroot -pyu

# 查看慢查询日志是否开启
mysql> show variables like "slow%";
+---------------------+----------------------------------+
| Variable_name       | Value                            |
+---------------------+----------------------------------+
| slow_launch_time    | 2                                |
| slow_query_log      | OFF                              |
| slow_query_log_file | /data/mysql/mysql-node1-slow.log |
+---------------------+----------------------------------+
3 rows in set (0.02 sec)

# 开启慢查询日志
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-node1-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.00 sec)

# 修改慢查询的阈值,注意此处不用加global
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 复制代码
[root@mysql-node1 ~]# mysql -uroot -pyu
mysql> select sleep (4);
+-----------+
| sleep (4) |
+-----------+
|         0 |
+-----------+
1 row in set (4.01 sec)

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

gtid模式

mysql 复制代码
#在master和slave中默认gtid模式是未开启的
[root@mysql-node1 ~]# mysql -uroot -pyu

在所有主机中加入参数

bash 复制代码
[root@mysql-node1 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock

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

gtid_mode=ON
enforce-gtid-consistency=ON

[root@mysql-node1 ~]# /etc/init.d/mysqld restart
Shutting down MySQL........... SUCCESS!
Starting MySQL. SUCCESS!

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

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

gtid_mode=ON
enforce-gtid-consistency=ON

[root@mysql-node2 ~]# /etc/init.d/mysqld restart
Shutting down MySQL........... SUCCESS!
Starting MySQL. SUCCESS!

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

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

gtid_mode=ON
enforce-gtid-consistency=ON

[root@mysql-node3 ~]# /etc/init.d/mysqld restart
Shutting down MySQL........... SUCCESS!
Starting MySQL. SUCCESS!
mysql 复制代码
#在三台主机中分别查看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.01 sec)

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000004 |      158 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set, 1 warning (0.01 sec)
mysql 复制代码
[root@mysql-node2 ~]# mysql -uroot -pyu

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.04 sec)

#在从库中停止slave功能;
mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> change master to MASTER_HOST='172.25.254.10',MASTER_USER='yu',MASTER_PASSWORD='yu',MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected, 7 warnings (0.04 sec)

mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State:
                  Master_Host: 172.25.254.10
                  Master_User: yu
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File:
          Read_Master_Log_Pos: 4
               Relay_Log_File: mysql-node2-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File:
             Slave_IO_Running: No
            Slave_SQL_Running: No

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 172.25.254.10
                  Master_User: yu
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000004
          Read_Master_Log_Pos: 158
               Relay_Log_File: mysql-node2-relay-bin.000002
                Relay_Log_Pos: 375
        Relay_Master_Log_File: mysql-bin.000004
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
mysql 复制代码
[root@mysql-node3 ~]# mysql -uroot -pyu

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.03 sec)

#在从库中停止slave功能;
mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> change master to MASTER_HOST='172.25.254.10',MASTER_USER='yu',MASTER_PASSWORD='yu',MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected, 7 warnings (0.05 sec)

mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State:
                  Master_Host: 172.25.254.10
                  Master_User: yu
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File:
          Read_Master_Log_Pos: 4
               Relay_Log_File: mysql-node3-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File:
             Slave_IO_Running: No
            Slave_SQL_Running: No

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.02 sec)

mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 172.25.254.10
                  Master_User: yu
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000004
          Read_Master_Log_Pos: 158
               Relay_Log_File: mysql-node3-relay-bin.000002
                Relay_Log_Pos: 375
        Relay_Master_Log_File: mysql-bin.000004
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

多线程回放

mysql 复制代码
#在slave主机中默认回方日志时使用单线程回放
mysql> show processlist;
bash 复制代码
#开启多线程回放日志(在slave主中)
[root@mysql-node2 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock

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

gtid_mode=ON
enforce-gtid-consistency=ON

slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
relay_log_recovery=ON

[root@mysql-node2 ~]# /etc/init.d/mysqld restart
Shutting down MySQL. SUCCESS!
Starting MySQL. SUCCESS!

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

半同步模式

mysql 复制代码
#在master主机中操作
[root@mysql-node1 ~]# 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 复制代码
#在slave主机中
[root@mysql-node2~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 like '%semi%';
+---------------------+---------------+
| plugin_name         | plugin_status |
+---------------------+---------------+
| rpl_semi_sync_slave | ACTIVE        |
+---------------------+---------------+
1 row in set (0.00 sec)

mysql> show variables like 'rpl_semi_sync%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | ON    |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
2 rows in set (0.00 sec)

mysql> show status like 'rpl_semi_sync%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |
+----------------------------+-------+
1 row in set (0.00 sec)
mysql 复制代码
#测试:
#在主库中
mysql> insert into liouo.userlist values ('user7','123');
Query OK, 1 row affected (0.02 sec)

mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 10000      |
| rpl_semi_sync_master_trace_level          | 32         |
| rpl_semi_sync_master_wait_for_slave_count | 1          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
+-------------------------------------------+------------+
6 rows in set (0.01 sec)
mysql> show status like 'rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 1     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 1     |
| 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      | 2013  |
| Rpl_semi_sync_master_tx_wait_time          | 2013  |
| Rpl_semi_sync_master_tx_waits              | 1     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 1     |
+--------------------------------------------+-------+
14 rows in set (0.01 sec)

#模拟ack故障 在所有slave主机中
mysql> stop slave IO_THREAD;
Query OK, 0 rows affected, 1 warning (0.00 sec)

#在主库写入数据
mysql> insert into liouo.userlist values ('user8','123');
Query OK, 1 row affected (10.01 sec)

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             | 2     |
| 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      | 3598  |
| Rpl_semi_sync_master_tx_wait_time          | 7197  |
| Rpl_semi_sync_master_tx_waits              | 2     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 2     |
+--------------------------------------------+-------+
14 rows in set (0.01 sec)

#恢复故障 在所有slave主机中
mysql> start SLAVE IO_THREAD;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql 复制代码
[root@mysql-node1 ~]# mysql -uroot -pyu

mysql> insert into liouo.userlist values ('user6','123');
Query OK, 1 row affected (0.04 sec)

mysql> show status like 'rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 1     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 1     |
| 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      | 2013  |
| Rpl_semi_sync_master_tx_wait_time          | 2013  |
| Rpl_semi_sync_master_tx_waits              | 1     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 1     |
+--------------------------------------------+-------+
14 rows in set (0.01 sec)

mysql> insert into liouo.userlist values ('user7','123');
Query OK, 1 row affected (0.02 sec)

[root@mysql-node2 ~]# mysql -uroot -pyu
mysql> stop slave IO_THREAD;
Query OK, 0 rows affected, 1 warning (0.01 sec)

[root@mysql-node1 ~]# mysql -uroot -pyu
mysql> insert into liouo.userlist values ('user8','123');
Query OK, 1 row affected (10.01 sec)

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             | 2     |
| 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      | 3598  |
| Rpl_semi_sync_master_tx_wait_time          | 7197  |
| Rpl_semi_sync_master_tx_waits              | 2     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 2     |
+--------------------------------------------+-------+
14 rows in set (0.01 sec)

四、Mysql-MHA高可用集群

配置Mha-manager

bash 复制代码
[root@mha ~]# unzip MHA-7.zip
[root@mha ~]# cd MHA-7/
[root@mha MHA-7]# dnf install perl perl-DBD-MySQL perl-CPAN  -y

[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中安装相应软件

bash 复制代码
[root@mha MHA-7]# for i in 10 20 30
> 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
Warning: Permanently added '172.25.254.10' (ED25519) to the list of known hosts.
mha4mysql-node-0.58-0.el7.centos.noarch.rpm                     100%   35KB  16.9MB/s   00:00
Verifying...                          ########################################
准备中...                          ########################################
正在升级/安装...
mha4mysql-node-0.58-0.el7.centos      ########################################
Warning: Permanently added '172.25.254.20' (ED25519) to the list of known hosts.
mha4mysql-node-0.58-0.el7.centos.noarch.rpm                     100%   35KB  28.2MB/s   00:00
Verifying...                          ########################################
准备中...                          ########################################
正在升级/安装...
mha4mysql-node-0.58-0.el7.centos      ########################################
Warning: Permanently added '172.25.254.30' (ED25519) to the list of known hosts.
mha4mysql-node-0.58-0.el7.centos.noarch.rpm                     100%   35KB  20.1MB/s   00:00
Verifying...                          ########################################
准备中...                          ########################################
正在升级/安装...
mha4mysql-node-0.58-0.el7.centos      ########################################

修改MHA-Manager中的检测代码

bash 复制代码
[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建立远程登录用户

bash 复制代码
#在master主机中
[root@mysql-node1 ~]# mysql -uroot -pyu

mysql> create user root@'%' identified with mysql_native_password by 'yu';
Query OK, 0 rows affected (0.01 sec)

mysql> grant all on *.* tO root@'%' ;
Query OK, 0 rows affected (0.00 sec)

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

bash 复制代码
[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

修改配置文件

bash 复制代码
[root@mha mha4mysql-manager-0.58]# vim /etc/masterha/app1.cnf
[server default]
user=root
password=yu
ssh_user=root
repl_user=root
repl_password=yu

master_binlog_dir= /data/mysql
remote_workdir=/tmp

secondary_check_script= masterha_secondary_check -s 172.25.254.10 -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/app1/mha.log

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

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

[server3]
hostname=172.25.254.30
no_master=1                 

检测环境

bash 复制代码
[root@mha mha4mysql-manager-0.58]# masterha_check_ssh --conf=/etc/masterha/app1.cnf

[root@mha mha4mysql-manager-0.58]# masterha_check_repl --conf=/etc/masterha/app1.cnf

在slave中安装mha-node软件依赖

bash 复制代码
#在所有的数据库主机中安装依赖
[root@mysql-node1~3 ~]# dnf install perl perl-DBD-MySQL perl-CPAN  -y

[root@mysql-node1~3 ~]# tar zxf cpan_plugin.tar.gz

[root@mysql-node1~3 ~]# 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@mysql-node1~3 ~]# perl -MConfig::Tiny -e 'print "OK\n"'
OK
[root@mysql-node1~3 ~]# perl -MLog::Dispatch -e 'print "OK\n"'
OK
[root@mysql-node1~3 ~]# perl -MMail::Sender -e 'print "OK\n"'
Mail::Sender is deprecated and you should look to Email::Sender instead at -e line 0.
OK
[root@mysql-node1~3 ~]# perl -MParallel::ForkManager -e 'print "OK\n"'
OK

五、集群切换操作

手动切换

master无故障切换

默认状态下:10是主库,20和30是从库;即在10上输入下面命令时,返回空;在20和30上查看时,显示如下

bash 复制代码
#执行切换,把master切换到20
[root@mha ~]#  masterha_master_switch \
> --conf=/etc/masterha/app1.cnf \
> --master_state=alive \
> --new_master_host=172.25.254.20 \
> --new_master_port=3306 \
> --orig_master_is_new_slave \
> --running_updates_limit=10000
# 或者是
[root@mha ~]# masterha_master_switch --conf=/etc/masterha/app1.cnf --master_state=alive --new_master_host=172.25.254.20 --new_master_port=3306 --orig_master_is_new_slave --running_updates_limit=10000
[root@mha ~]# masterha_master_switch \
> --conf=/etc/masterha/app1.cnf \
> --master_state=alive \
> --new_master_host=172.25.254.20 \
> --new_master_port=3306 \
> --orig_master_is_new_slave \
> --running_updates_limit=10000

It is better to execute FLUSH NO_WRITE_TO_BINLOG TABLES on the master before switching. Is it ok to execute on 172.25.254.10                                                        (172.25.254.10:3306)? (YES/no): yes	# 输入

Starting master switch from 172.25.254.10(172.25.254.10:3306) to 172.25.254.20(172.25.254.20:3306)? (yes/NO): yes	 # 输入

Sat Mar  7 11:31:32 2026 - [info]  All other slaves should start replication from here. Statement should be: CHANGE MASTER T                                                        O MASTER_HOST='172.25.254.20', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='root', MASTER_PASSWORD='xxx';
172.25.254.20(172.25.254.20:3306) completed successfully.

看到successfully即为成功

效果:

查看集群状态

master故障后切换

(1)检查环境

bash 复制代码
# 在执行前可以在mha节点执行下面语句,为验证当前集群健康
masterha_check_repl --conf=/etc/masterha/app1.cnf
# 输出MySQL Replication Health is OK.即为健康

(2)模拟当前主库172.25.254.20宕机

bash 复制代码
[root@mysql-node2 ~]# /etc/init.d/mysqld stop
Shutting down MySQL......... SUCCESS!

(3)执行手动故障切换

bash 复制代码
[root@mha ~]# masterha_master_switch --master_state=dead --conf=/etc/masterha/app1.cnf --dead_master_host=172.25.254.20 --dead_master_port=3306 --new_master_host=172.25.254.10 --new_master_port=3306 --ignore_last_failover
--dead_master_ip=<dead_master_ip> is not set. Using 172.25.254.20.

Master 172.25.254.20(172.25.254.20:3306) is down!

Started manual(interactive) failover.
Selected 172.25.254.10(172.25.254.10:3306) as a new master.
172.25.254.10(172.25.254.10:3306): OK: Applying all logs succeeded.
172.25.254.30(172.25.254.30:3306): ERROR: Failed on waiting gtid exec set on master.
Master failover to 172.25.254.10(172.25.254.10:3306) done, but recovery on slave partially failed.

(4)删除锁文件

bash 复制代码
[root@mha ~]# ls /etc/masterha/
app1.cnf  app1.failover.complete---->#(锁文件)

[root@mha ~]# rm -rf /etc/masterha/app1.failover.complete
[root@mha ~]# ls /etc/masterha/
app1.cnf
mysql 复制代码
[root@mysql-node1 ~]# mysql -uroot -pyu
mysql> stop slave;
Query OK, 0 rows affected, 2 warnings (0.00 sec)

mysql> reset slave all;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show slave status \G;
Empty set, 1 warning (0.00 sec)

在20上

mysql 复制代码
[root@mysql-node2 ~]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!

[root@mysql-node2 ~]# mysql -uroot -pyu
mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> reset slave all;
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> CHANGE MASTER TO MASTER_HOST='172.25.254.10', MASTER_USER='root', MASTER_PASSWORD='yu', MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected, 7 warnings (0.02 sec)

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> \q
Bye
[root@mysql-node2 ~]# mysql -uroot -pyu -e "show slave status\G;"  | head -n 15
mysql: [Warning] Using a password on the command line interface can be insecure.
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 172.25.254.10
                  Master_User: root
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000008
          Read_Master_Log_Pos: 422
               Relay_Log_File: mysql-node2-relay-bin.000002
                Relay_Log_Pos: 422
        Relay_Master_Log_File: mysql-bin.000008
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

最后查看三个节点的状态

1.node1返回空值,172.25.254.10为主库

2.node2和node3返回值一致,均为从库

自动切换

方便观察建议开启两个shell

bash 复制代码
[root@mha ~]# > /etc/masterha/*.log
[root@mha ~]# watch -n 1 cat /etc/masterha/mha.log

检查配置文件书写路径是否正确

bash 复制代码
[root@mha ~]# vim /etc/masterha/app1.cnf
[server default]
user=root
password=yu
ssh_user=root
repl_user=root
repl_password=yu

master_binlog_dir= /data/mysql
remote_workdir=/tmp

secondary_check_script= masterha_secondary_check -s 172.25.254.10 -s 172.25.254.2
ping_interval=3

[server default]
manager_workdir=/etc/masterha			# 日志文件存储路径
manager_log=/etc/masterha/mha.log		# 日志文件

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

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

[server3]
hostname=172.25.254.30
no_master=1

开启自动切换功能

bash 复制代码
[root@mha ~]# masterha_manager --conf=/etc/masterha/app1.cnf  &
[root@mha ~]# jobs
[1]+  运行中               masterha_manager --conf=/etc/masterha/app1.cnf &

模拟故障

bash 复制代码
[root@mysql-node1 ~]# /etc/init.d/mysqld stop

vip功能及vip的启动切换

bash 复制代码
[root@mha ~]# ll MHA-7/master_ip_*
-rw-r--r-- 1 root root 2156  1月 14  2021 MHA-7/master_ip_failover
-rw-r--r-- 1 root root 3813  1月 14  2021 MHA-7/master_ip_online_change

[root@mha ~]# mkdir  /etc/masterha/scripts
[root@mha ~]# cp  MHA-7/master_ip_*  /etc/masterha/scripts

[root@mha ~]# vim /etc/masterha/app1.cnf
master_ip_failover_script= /etc/masterha/scripts/master_ip_failover

master_ip_online_change_script= /etc/masterha/scripts/master_ip_online_change

[root@mha ~]# vim /etc/masterha/scripts/master_ip_failover
my $vip = '172.25.254.100/24';

[root@mha ~]# vim /etc/masterha/scripts/master_ip_online_change
my $vip = '172.25.254.100/24';

# 注释掉下面这行 
[root@mha ~]# vim /etc/masterha/app1.cnf
# secondary_check_script= masterha_secondary_check -s 172.25.254.10 -s 172.25.254.2

[root@mysql-node1 ~]# ip a a 172.25.254.100/24 dev eth0

测试

bash 复制代码
[root@mha ~]# masterha_manager  --conf=/etc/masterha/app1.cnf &
[root@mha ~]# jobs
[1]+  运行中               masterha_manager --conf=/etc/masterha/app1.cnf &

模拟故障,关闭mysql master

bash 复制代码
[root@mysql-node1 ~]# /etc/init.d/mysqld stop
Shutting down MySQL........... SUCCESS!

观察监控中的状态,此时vip漂移到20上


六、还原mysql所有节点

利用ansible还原所有节点

bash 复制代码
#利用ansible还原所有节点
[root@mha ~]# vim /etc/yum.repos.d/epel.repo 
[epel]
name = epel
baseurl = https://mirrors.aliyun.com/epel-archive/9.6/Everything/x86_64/
gpgcheck = 0

[root@mha yum.repos.d]# dnf install ansible -y

[root@mha yum.repos.d]# 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

[root@mha ~]# useradd devops
[root@mha ~]# echo yu | passwd --stdin devops
更改用户 devops 的密码 。
passwd:所有的身份验证令牌已经成功更新。

[devops@mha ansible]$ vim ansible.cfg
[defaults]
inventory=./inventory
remote_user=root
host_key_checking=false
[privilege_escalation]
become=False
[devops@mha ansible]$ vim inventory
[mysql]
172.25.254.10
172.25.254.20
172.25.254.30

[devops@mha ansible]$ ansible mysql -m ping
172.25.254.30 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
172.25.254.20 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
172.25.254.10 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
[devops@mha ansible]$ ansible mysql -m shell -a "whoami"
172.25.254.30 | CHANGED | rc=0 >>
root
172.25.254.20 | CHANGED | rc=0 >>
root
172.25.254.10 | CHANGED | rc=0 >>
root

[devops@mha ansible]$ ansible mysql -m user -a 'name=devops'
[devops@mha ansible]$  ansible mysql -m shell -a 'echo devops | passwd --stdin devops'
[devops@mha ansible]$ ansible mysql -m shell -a 'echo "devops   ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers'
[devops@mha ansible]$ ansible all -m file -a 'path=/home/devops/.ssh owner=devops group=devops mode="0700" state=directory'
[devops@mha ansible]$ ansible all -m copy -a 'src=/home/devops/.ssh/authorized_keys dest=/home/devops/.ssh/authorized_keys owner=devops group=devops mode='0600''

[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

[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

[devops@mha ansible]$ vim clear_mysql.yml
- name: reset mysql
  hosts: mysql
  tasks:
  - name: stop mysql
    shell: '/etc/init.d/mysqld stop'
    ignore_errors: yes

  - name: delete mysql data
    file:
      path: /data/mysql
      state: absent

  - name: crate data directroy
    file:
      path: /data/mysql
      state: directory
      owner: mysql
      group: mysql

  - name: initialize mysql
    shell: '/usr/local/mysql/bin/mysqld --initialize --user=mysql'

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

续6.1(未修改的)

bash 复制代码
[devops@mha ansible]$
[devops@mha ansible]$ ansible mysql -m user -a 'name=devops'
172.25.254.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "comment": "",
    "create_home": true,
    "group": 1000,
    "home": "/home/devops",
    "name": "devops",
    "shell": "/bin/bash",
    "state": "present",
    "system": false,
    "uid": 1000
}
172.25.254.30 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "comment": "",
    "create_home": true,
    "group": 1000,
    "home": "/home/devops",
    "name": "devops",
    "shell": "/bin/bash",
    "state": "present",
    "system": false,
    "uid": 1000
}
172.25.254.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "comment": "",
    "create_home": true,
    "group": 1000,
    "home": "/home/devops",
    "name": "devops",
    "shell": "/bin/bash",
    "state": "present",
    "system": false,
    "uid": 1000
}
[devops@mha ansible]$ ansible mysql -m shell -a 'id devops'
172.25.254.20 | CHANGED | rc=0 >>
用户id=1000(devops) 组id=1000(devops) 组=1000(devops)
172.25.254.30 | CHANGED | rc=0 >>
用户id=1000(devops) 组id=1000(devops) 组=1000(devops)
172.25.254.10 | CHANGED | rc=0 >>
用户id=1000(devops) 组id=1000(devops) 组=1000(devops)
[devops@mha ansible]$ ansible mysql -m shell -a 'echo devops | passwd --stdin devops'
172.25.254.20 | CHANGED | rc=0 >>
更改用户 devops 的密码 。
passwd:所有的身份验证令牌已经成功更新。
172.25.254.30 | CHANGED | rc=0 >>
更改用户 devops 的密码 。
passwd:所有的身份验证令牌已经成功更新。
172.25.254.10 | CHANGED | rc=0 >>
更改用户 devops 的密码 。
passwd:所有的身份验证令牌已经成功更新。
[devops@mha ansible]$ ansible mysql -m shell -a 'echo "devops  ALL=(ALL) NOPASSWD: ALL" > /etc/sudoer.d'
172.25.254.30 | CHANGED | rc=0 >>

172.25.254.20 | CHANGED | rc=0 >>

172.25.254.10 | CHANGED | rc=0 >>

[devops@mha ansible]$ exit

手动还原方式

mysql-node1---172.25.254.10

bash 复制代码
#所有节点初始化数据
[root@mysql-node1 ~]# /etc/init.d/mysqld stop
Shutting down MySQL... SUCCESS!
[root@mysql-node1 ~]# rm -rf /data/mysql/*

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

#不同主机server-id一定要根据实际情况做相应改变
server-id=10
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-node1 ~]# mysqld --user=mysql --initialize
A temporary password is generated for root@localhost: 7K1Nep7X>LYw

mysql-node2---172.25.254.20

bash 复制代码
[root@mysql-node2 ~]# /etc/init.d/mysqld stop
Shutting down MySQL.... SUCCESS!
[root@mysql-node2 ~]# rm -rf /data/mysql/*

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

server-id=20
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"

[root@mysql-node2 ~]# mysqld --user=mysql --initialize
A temporary password is generated for root@localhost: X9hm>lDF3qyr

mysql-node3---172.25.254.30

bash 复制代码
[root@mysql-node3 ~]# /etc/init.d/mysqld stop
Shutting down MySQL.... SUCCESS!
[root@mysql-node3 ~]# rm -rf /data/mysql/*

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

server-id=30
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"

[root@mysql-node3 ~]# mysqld --user=mysql --initialize
A temporary password is generated for root@localhost: +7)MF6%OtD6s

七、部署组复制

mysql-node1--172.25.254.10

bash 复制代码
#设置所有mysql节点的解析
[root@mysql-node1 ~]# vim /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.10     mysql-node1
172.25.254.20     mysql-node2
172.25.254.30     mysql-node3

[root@mysql-node1 ~]# 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.10:33061"   #其他两台主机一定要根据ip进行修改
group_replication_group_seeds="172.25.254.10:33061,172.25.254.20:33061,172.25.254.30:33061"
group_replication_bootstrap_group=off
group_replication_single_primary_mode=OFF
EOF

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

#配置组复制
[root@mysql-node1 ~]# mysql -uroot -p'7K1Nep7X>LYw'
mysql> alter user root@localhost identified   by 'yu';
Query OK, 0 rows affected (0.00 sec)

mysql> SET SQL_LOG_BIN=0;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'yu';
Query OK, 0 rows affected (0.01 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
Query OK, 0 rows affected (0.01 sec)

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

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

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

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

mysql> SET SQL_LOG_BIN=1;
Query OK, 0 rows affected (0.00 sec)

mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user', SOURCE_PASSWORD='yu' FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.02 sec)

mysql> SHOW PLUGINS;     #查看组复制插件是否激活
| group_replication               | ACTIVE   | GROUP REPLICATION  | group_replication.so | GPL     |

mysql> SET GLOBAL group_replication_bootstrap_group=ON;
Query OK, 0 rows affected (0.00 sec)

mysql> START GROUP_REPLICATION USER='rpl_user', PASSWORD='yu';
Query OK, 0 rows affected (1.50 sec)

mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM performance_schema.replication_group_members;
#看到主机online表示成功

mysql-node2--172.25.254.20

bash 复制代码
#设置所有mysql节点的解析
[root@mysql-node2 ~]# vim /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.10     mysql-node1
172.25.254.20     mysql-node2
172.25.254.30     mysql-node3

[root@mysql-node2 ~]# 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.20:33061"   
group_replication_group_seeds="172.25.254.10:33061,172.25.254.20:33061,172.25.254.30:33061"
group_replication_bootstrap_group=off
group_replication_single_primary_mode=OFF
EOF

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

[root@mysql-node2 ~]# mysql -uroot -p'X9hm>lDF3qyr'
mysql> alter user root@localhost identified   by 'yu';
Query OK, 0 rows affected (0.02 sec)

mysql> SET SQL_LOG_BIN=0;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'yu';
Query OK, 0 rows affected (0.01 sec)

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

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

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

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

mysql> SET SQL_LOG_BIN=1;
Query OK, 0 rows affected (0.00 sec)

mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user',SOURCE_PASSWORD='yu' FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.03 sec)

mysql> START GROUP_REPLICATION USER='rpl_user', PASSWORD='yu';
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;			#用过此命令解决以上报错
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> START GROUP_REPLICATION USER='rpl_user', PASSWORD='yu';
Query OK, 0 rows affected (2.27 sec)

mysql> SELECT * FROM performance_schema.replication_group_members;
#看到主机online表示成功

msyql-node3--172.25.254.30

bash 复制代码
#设置所有mysql节点的解析
[root@mysql-node3 ~]# vim /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.10     mysql-node1
172.25.254.20     mysql-node2
172.25.254.30     mysql-node3

[root@mysql-node3 ~]# 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.30:33061"   
group_replication_group_seeds="172.25.254.10:33061,172.25.254.20:33061,172.25.254.30:33061"
group_replication_bootstrap_group=off
group_replication_single_primary_mode=OFF
EOF

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

[root@mysql-node3 ~]# mysql -uroot -p'+7)MF6%OtD6s'
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 10
Server version: 8.3.0

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> alter user root@localhost identified   by 'yu';
Query OK, 0 rows affected (0.01 sec)

mysql> SET SQL_LOG_BIN=0;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'yu';
Query OK, 0 rows affected (0.01 sec)

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

mysql> GRANT CONNECTION_ADMIN ON *.* TO rpl_user@'%';
Query OK, 0 rows affected (0.01 sec)

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

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

mysql> SET SQL_LOG_BIN=1;
Query OK, 0 rows affected (0.00 sec)

mysql> CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user',SOURCE_PASSWORD='yu' FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.02 sec)

mysql> START GROUP_REPLICATION USER='rpl_user', PASSWORD='yu';
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;			 #用过此命令解决以上报错
Query OK, 0 rows affected, 1 warning (0.02 sec)

mysql> START GROUP_REPLICATION USER='rpl_user', PASSWORD='yu';
Query OK, 0 rows affected (6.07 sec)

mysql> SELECT * FROM performance_schema.replication_group_members;

三台主机部署成功后的效果

均为online和primary

测试

bash 复制代码
#测试所有节点是否可以执行读写并数据是否同步
#node3中
[root@mysql-node3 ~]# mysql -uroot -pyu
mysql> create database liouo;
Query OK, 1 row affected (0.01 sec)

mysql> create table liouo.userlist (
    -> username varchar(10) primary key not null,
    -> password varchar(50) not null
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> insert into liouo.userlist values ('user1','111');
Query OK, 1 row affected (0.03 sec)

#在node2中查看并插入新的数据
[root@mysql-node2 ~]# mysql -uroot -pyu
mysql> select * from liouo.userlist;
+----------+----------+
| username | password |
+----------+----------+
| user1    | 111      |
+----------+----------+
1 row in set (0.00 sec)

mysql> insert into liouo.userlist values ('user2','222');
Query OK, 1 row affected (0.00 sec)

#在node1中查看并插入数据
[root@mysql-node1 ~]# mysql -uroot -pyu
mysql> select * from liouo.userlist;
+----------+----------+
| username | password |
+----------+----------+
| user1    | 111      |
| user2    | 222      |
+----------+----------+
2 rows in set (0.00 sec)

mysql> insert into liouo.userlist values ('user3','333');
Query OK, 1 row affected (0.01 sec)

在node1、2、3中均可以看到以上数据


八、Mysqlrouter

MySQLrouter软件下载

bash 复制代码
[root@mysqlrouter ~]# wget https://downloads.mysql.com/archives/get/p/41/file/mysql-router-community-8.4.7-1.el9.x86_64.rpm

安装mysqlrouter

bash 复制代码
[root@mysqlrouter ~]# dnf install mysql-router-community-8.4.7-1.el9.x86_64.rpm -y

mysqlrouter配置文件

bash 复制代码
[root@mysqlrouter ~]# rpm -qc mysql-router-community
/etc/logrotate.d/mysqlrouter				#日志轮询及日志截断策略
/etc/mysqlrouter/mysqlrouter.conf			#主配置文件

[root@mysqlrouter ~]# systemctl status mysqlrouter.service		#启动脚本

配置mysqlrouter

bash 复制代码
[root@mysqlrouter ~]# vim /etc/mysqlrouter/mysqlrouter.conf
[routing:ro]
bind_address = 0.0.0.0
bind_port = 7001
destinations = 172.25.254.10:3306,172.25.254.20:3306,172.25.254.30:3306
routing_strategy = round-robin

[routing:rw]
bind_address = 0.0.0.0
bind_port = 7002
destinations = 172.25.254.30:3306,172.25.254.20:3306,172.25.254.10:3306
routing_strategy = first-available

[root@mysqlrouter ~]# systemctl enable --now mysqlrouter.service
Created symlink /etc/systemd/system/multi-user.target.wants/mysqlrouter.service → /usr/lib/systemd/system/mysqlrouter.service.

[root@mysqlrouter ~]# netstat -antlupe | grep mysql
tcp        0      0 0.0.0.0:7001            0.0.0.0:*               LISTEN      991        176991     39587/mysqlrouter
tcp        0      0 0.0.0.0:7002            0.0.0.0:*               LISTEN      991        176009     39587/mysqlrouter

测试

bash 复制代码
#在mysql节点的任意主机中添加root远程登录
[root@mysql-node1 ~]# mysql -uroot -pyu

mysql> CREATE USER root@'%' identified by 'yu';
Query OK, 0 rows affected (0.00 sec)

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

[root@mysql-node1 ~]# mysql -uroot -plee -h172.25.254.10
mysql> quit
Bye

[root@mysql-node1 ~]# mysql -uroot -plee -h172.25.254.20
mysql> quit
Bye

[root@mysql-node1 ~]# mysql -uroot -plee -h172.25.254.30
mysql> quit
Bye

#查看调度效果
[root@mysql-node1 ~]# watch -n1 lsof -i :3306

[root@mysql-node2 ~]# watch -n1 lsof -i :3306

[root@mysql-node3 ~]# watch -n1 lsof -i :3306

可以使用mysqlnode1、2、3三台任意一台主机进行测试,这里使用另外一台客户端172.25.254.99进行测试

使用端口7001是轮询,效果如下

  • 第一次测试
  • 第二次测试
  • 第三次测试

使用端口7002是最快相应,效果如下

九.实验中常遇到的问题及解决芳芳

问题1:源码编译时 make 失败,提示缺少 Boost 库

现象 :cmake 过程中报错 Could not find Boost

原因 :未使用 -DWITH_BOOST=bundled 或系统中未安装 Boost。

解决 :在 cmake 命令中添加 -DWITH_BOOST=bundled,让 MySQL 源码自带的 boost 被使用。


问题2:初始化后临时密码无法登录

现象mysql -uroot -p 输入临时密码提示 Access denied

原因 :密码中包含特殊字符(如 *cpw*U8whdXh),未正确转义。

解决 :使用单引号包裹密码,或先修改 .bash_history 再输入。建议直接复制粘贴并注意 * 符号。


问题3:从库 START SLAVESlave_IO_Running: Connecting 一直不变成 Yes

现象Last_IO_Errorerror connecting to master ...

可能原因与解决

  • 网络不通 → ping 测试,检查防火墙
  • 复制用户权限不足 → 确保 GRANT REPLICATION SLAVE
  • MASTER_LOG_FILE / MASTER_LOG_POS 错误 → 重新在主库 SHOW MASTER STATUS
  • bind-address 未监听外网 → 修改 my.cnf 中 bind-address=0.0.0.0 或注释掉

问题4:开启 GTID 后 START SLAVE 报错 Slave failed to initialize ...

现象ERROR 1872Slave failed to initialize relay log info structure from the repository

原因:从库之前有基于 binlog+position 的复制残留。

解决

sql 复制代码
STOP SLAVE;
RESET SLAVE ALL;
CHANGE MASTER TO MASTER_HOST=..., MASTER_AUTO_POSITION=1;
START SLAVE;

问题5:半同步复制中主库写入延迟变大(10秒)

现象INSERT 耗时 10 秒后才返回。

原因 :所有从库的 IO 线程停止,主库等待 rpl_semi_sync_master_timeout(默认 10000ms)超时后降级为异步。

解决:检查从库半同步插件是否激活、网络是否正常。可调整超时时间或确保至少一个从库正常。


问题6:MHA 检测失败,报 MySQL Replication Health is NOT OK!

现象masterha_check_repl 提示复制线程异常或 SSH 互信失败。

解决

  • 检查所有节点 SHOW SLAVE STATUS 确保 Slave_IO/SQL_Running 均为 Yes
  • 配置 SSH 免密登录(包括 Manager 到各 Node 以及 Node 之间)
  • 确保 MHA 管理用户(如 root@'%')在 master 上已创建且密码正确

问题7:MHA 手动切换时卡住或报 Can't locate MHA/NodeUtil.pm

现象:Perl 模块缺失。

解决 :在 Manager 和所有 Node 上安装 perl-CPAN 并通过 cpan 安装 Config::TinyLog::DispatchMail::SenderParallel::ForkManager。并修改 NodeUtil.pm 适配 MySQL 8.0 版本解析。


问题8:组复制(MGR)启动时报 ERROR 3092

现象START GROUP_REPLICATION 失败,提示 server is not configured properly

原因:新节点未重置 binlog,旧 GTID 执行记录冲突。

解决

sql 复制代码
RESET MASTER;
START GROUP_REPLICATION USER='rpl_user', PASSWORD='xxx';

问题9:MySQL Router 连接后一直返回同一个 server_id(没有轮询)

现象:读端口 7001 多次查询始终访问同一台 MySQL。

原因routing_strategy = first-available 被误用在读端口。

解决 :读端口使用 round-robin,写端口使用 first-available


问题10:Ansible playbook 执行 mysqld --initialize 后无法获取临时密码

现象:初始化成功但密码被掩码,日志中不显示。

解决 :使用 -vv 详细输出并用 grep password 过滤,或预先将 initialize 的输出重定向到文件再 cat


十.经验与建议

  1. 环境准备阶段:务必关闭防火墙或开放相应端口(3306、26379、33061、7001/2),否则各种连接问题难以排查。
  2. 日志为王 :MySQL 错误日志(默认 /data/mysql/*.err)和 MHA 日志(/etc/masterha/mha.log)是定位问题的第一手资料。
  3. 逐步验证 :每完成一个复制拓扑(如 GTID、半同步),先用 SHOW SLAVE STATUS 确认关键字段,再插入测试数据。
  4. 备份与恢复技能 :使用 mysqldump + scp 手动拉平数据是加入新从库的标准操作,务必掌握。
  5. 自动化思维:当需要重置三台以上节点时,Ansible 比手动操作效率提升百倍,建议多场景练习。
相关推荐
凌云拓界2 小时前
青创赛终评手记:最后的成功
运维·科技·职场和发展·架构·创业创新
zjeweler2 小时前
宝藏网站推荐:云服务器特惠与网安学习资源的一站式聚合平台
运维·服务器·学习
heimeiyingwang2 小时前
【架构实战】BFF架构:Backend For Frontends
架构
时空自由民.2 小时前
Linux,ESP IDF,NuttX OS使用的项目编译管理构建体系Kconfig + Kbuild(或基于 Make/CMake 的构建系统)
linux·运维·服务器
上弦月-编程2 小时前
C语言位运算:从入门到精通
运维·c语言·开发语言·vscode·算法·leetcode·极限编程
云达闲人2 小时前
搭建DevOps企业级仿真实验环境:001Proxmox VE 8.x 系统介绍与安装准备
运维·devops·proxmox·idrac·实验环境搭建
码点滴2 小时前
上下文压缩不是“丢数据“:Context Compressor 的血缘追踪与 Prefix Cache 保护
人工智能·python·架构·prompt·ai编程
开开心心就好2 小时前
一款既是直播工具又是浏览器的软件
linux·运维·服务器·智能手机·逻辑回归·excel·最小二乘法
tangyal2 小时前
DNS(BIND) 正反向解析文件的部署实验
linux·运维·服务器·bind·dns正向解析·dns反向解析