MySQL高可用集群实战:MHA搭建全攻略

Mysql-MHA高可用集群

搭建一主两从架构

目标:配置 1 个主库(10)和 2 个从库(20、30),开启 GTID 和半同步复制

复制代码
# ========== Master 节点(172.25.254.10)配置 ==========

# 停止 MySQL 服务
[root@mysql-node10 ~]# /etc/init.d/mysqld stop

# 清空数据目录(全新初始化,删除旧数据)
[root@mysql-node10 ~]# rm -fr /data/mysql/*

# 编辑 MySQL 配置文件
[root@mysql-node10 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql                      # 数据目录
socket=/data/mysql/mysql.sock            # socket 文件位置
server-id=1                              # 服务器 ID,主库必须唯一
log-bin=mysql-bin                        # 启用二进制日志
gtid_mode=ON                             # 开启 GTID 全局事务标识
log_slave_updates=ON                     # 从库记录中继日志到自己的 binlog
enforce-gtid-consistency=ON              # 强制 GTID 一致性
symbolic-links=0                         # 禁用符号链接

# 初始化数据库(生成初始数据,会输出临时密码)
[root@mysql-node10 ~]# mysqld --user mysql --initialize

# 启动 MySQL
[root@mysql-node10 ~]# /etc/init.d/mysqld start

# 运行安全配置脚本(设置 root 密码、删除匿名用户等)
[root@mysql-node10 ~]# mysql_secure_installation

# 登录 MySQL
[root@mysql-node10 ~]# mysql -p

# 创建复制用户 swp,用于主从同步
mysql> create user swp@'%' identified with mysql_native_password by 'swp';
Query OK, 0 rows affected (0.00 sec)

# 授予复制权限
mysql> GRANT REPLICATION SLAVE ON *.* TO swp@'%';
Query OK, 0 rows affected (0.00 sec)

# 安装半同步复制主库插件
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
Query OK, 0 rows affected (0.02 sec)

# 启用半同步复制主库
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
Query OK, 0 rows affected (0.00 sec)


# ========== Slave 节点(172.25.254.20 和 172.25.254.30)配置 ==========

# 停止 MySQL 服务
[root@mysql-node20 & 30 ~]# /etc/init.d/mysqld stop

# 清空数据目录
[root@mysql-node20 & 30 ~]# rm -fr /data/mysql/*

# 编辑配置文件(注意 server-id 不同:20 用 2,30 用 3)
[root@mysql-node20 & 30 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=1                    # ⚠️ 实际配置时 20 用 2,30 用 3
log-bin=mysql-bin
gtid_mode=ON
log_slave_updates=ON
enforce-gtid-consistency=ON
symbolic-links=0

# 初始化数据库
[root@mysql-node20 & 30 ~]# mysqld --user mysql --initialize

# 启动 MySQL
[root@mysql-node20 & 300 ~]# /etc/init.d/mysqld start

# 安全配置
[root@mysql-node20 & 30 ~]# mysql_secure_installation

# 登录 MySQL
[root@mysql-node20 & 30 ~]# mysql -p

# 配置主从复制(使用 GTID 自动定位)
mysql> CHANGE MASTER TO 
    MASTER_HOST='172.25.254.10',      # 主库 IP
    MASTER_USER='swp',                 # 复制用户
    MASTER_PASSWORD='swp',             # 复制密码
    MASTER_AUTO_POSITION=1;            # 使用 GTID 自动获取位置
Query OK, 0 rows affected, 2 warnings (0.00 sec)

# 启动从库复制线程
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

# 安装半同步复制从库插件
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected (0.01 sec)

# 启用半同步复制从库
mysql> SET GLOBAL rpl_semi_sync_slave_enabled =1;
Query OK, 0 rows affected (0.00 sec)

# 重启 IO 线程使半同步生效
mysql> STOP SLAVE IO_THREAD;
Query OK, 0 rows affected (0.00 sec)

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

# 验证半同步是否开启成功
mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |      # 值为 ON 表示成功
+----------------------------+-------+
1 row in set (0.01 sec)

1. 配置 MHA Manager

MHA Manager 是控制中心,负责监控主库状态并自动切换

复制代码
# 解压 MHA 安装包

[root@mha ~]# unzip MHA-7.zip
[root@mha ~]# cd MHA-7/

# 安装 Perl 依赖(MHA 基于 Perl 开发)

[root@mha MHA-7]# dnf install perl perl-DBD-MySQL perl-CPAN -y
复制代码
# 进入 CPAN 交互式安装 Perl 模块

[root@mha MHA-7]# cpan

# 自动配置 CPAN(一路 yes)

Loading internal logger. Log::Log4perl recommended for better logging

CPAN.pm requires configuration, but most of it can be done automatically.
Would you like to configure as much as possible automatically? [yes] yes

# 安装 MHA 必需的 Perl 模块

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

# 安装 MHA 软件包(--nodeps 忽略依赖,因为已手动安装 Perl 模块)

[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

在所有 MySQL 节点安装 MHA Node 软件

MHA Node 安装在每个数据库节点上,负责执行切换操作

复制代码
# 循环将 node 包复制到 10、20、30 并安装
[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      ########################################
# ... 20、30 类似输出 ...

修改 MHA Manager 中的检测代码(兼容 MySQL 8.0)

原因:MHA 0.58 版本解析 MySQL 8.0 版本号时存在兼容性问题,需要修复

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

# 修改后的代码(兼容 MySQL 8.x)
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);  # 格式化为 6 位数字
  return $result;
}

为 MHA 建立远程登录用户

目的:MHA Manager 需要通过 MySQL 用户连接各节点进行管理

复制代码
# 在主库(10)上执行
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 的配置文件模板

复制代码
# 创建配置目录
[root@mha mha4mysql-manager-0.58]# mkdir /etc/masterha/ -p

# 解压源码包(获取示例配置)
[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

修改配置文件

配置文件说明:定义集群节点、用户、路径等关键信息

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

# ========== 全局默认配置 ==========
[server default]
user=root                              # MHA 管理用户
password=root                          # 管理用户密码(⚠️ 注意:实际是 lee)
ssh_user=root                          # SSH 登录用户
repl_user=swp                          # 主从复制用户
repl_password=swp                      # 复制密码
master_binlog_dir=/data/mysql          # 主库 binlog 目录
remote_workdir=/tmp                    # 远程工作目录
secondary_check_script= masterha_secondary_check -s 172.25.254.10 -s 172.25.254.2
ping_interval=3                        # 健康检查间隔(秒)

# 以下脚本暂未配置(后续配置 VIP 时需要)
# 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

# ========== Manager 自身配置 ==========
[server default]
manager_workdir=/etc/masterha          # Manager 工作目录
manager_log=/etc/masterha/mha.log       # Manager 日志文件

# ========== 节点定义 ==========
[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                            # 禁止成为主库(只读从库)

检测环境

检测 SSH 互信

目的:确保 MHA Manager 能免密登录所有数据库节点

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

Fri Feb 27 16:23:20 2026 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Fri Feb 27 16:23:20 2026 - [info] Reading application default configuration from /etc/masterha/app1.cnf..
Fri Feb 27 16:23:20 2026 - [info] Reading server configuration from /etc/masterha/app1.cnf..
Fri Feb 27 16:23:20 2026 - [info] Starting SSH connection tests..
# ... 各节点间双向 SSH 测试 ...
Fri Feb 27 16:23:22 2026 - [info] All SSH connection tests passed successfully.   # ✅ 成功
Use of uninitialized value in exit at /usr/bin/masterha_check_ssh line 44.

检测复制健康状态

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

Fri Feb 27 16:23:50 2026 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Fri Feb 27 16:23:50 2026 - [info] Reading application default configuration from /etc/masterha/app1.cnf..
Fri Feb 27 16:23:50 2026 - [info] Reading server configuration from /etc/masterha/app1.cnf..
Fri Feb 27 16:23:50 2026 - [info] MHA::MasterMonitor version 0.58.
Fri Feb 27 16:23:51 2026 - [info] GTID failover mode = 1                     # ✅ GTID 切换模式已启用
Fri Feb 27 16:23:51 2026 - [info] Dead Servers:
Fri Feb 27 16:23:51 2026 - [info] Alive Servers:
Fri Feb 27 16:23:51 2026 - [info]   172.25.254.10(172.25.254.10:3306)
Fri Feb 27 16:23:51 2026 - [info]   172.25.254.20(172.25.254.20:3306)
Fri Feb 27 16:23:51 2026 - [info]   172.25.254.30(172.25.254.30:3306)
Fri Feb 27 16:23:51 2026 - [info] Alive Slaves:
Fri Feb 27 16:23:51 2026 - [info]   172.25.254.20(172.25.254.20:3306)  Version=8.3.0
Fri Feb 27 16:23:51 2026 - [info]     Replicating from 172.25.254.10       # 20 从 10 复制
Fri Feb 27 16:23:51 2026 - [info]   172.25.254.30(172.25.254.30:3306)  Version=8.3.0
Fri Feb 27 16:23:51 2026 - [info]     Replicating from 172.25.254.10       # 30 从 10 复制
Fri Feb 27 16:23:51 2026 - [info] Current Alive Master: 172.25.254.10      # 当前主库是 10
Fri Feb 27 16:23:51 2026 - [info] Checking slave configurations..
Fri Feb 27 16:23:51 2026 - [info]  read_only=1 is not set on slave 172.25.254.20  # ⚠️ 警告:从库未设置只读
Fri Feb 27 16:23:51 2026 - [info]  read_only=1 is not set on slave 172.25.254.30
# ... 省略部分输出 ...
Fri Feb 27 16:23:51 2026 - [info] MySQL Replication Health is OK.           # ✅ 复制健康

在 Slave 中安装 MHA Node 软件依赖

注意:这一步是在**每个数据库节点(10、20、30)**上执行,不是在 MHA Manager 上

复制代码
# 安装 Perl 依赖

[root@mysql-node1~3 ~]# dnf install perl perl-DBD-MySQL perl-CPAN -y

# 解压 CPAN 插件包(如果有离线包)

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

# 进入 CPAN 安装 Perl 模块(与 Manager 安装类似)

[root@mysql-node1~3 ~]# cpan

# ... 自动配置 ...

cpan[1]> install Config::Tiny
cpan[2]> install Log::Dispatch
cpan[3]> install Mail::Sender

# 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
```

集群无故障切换(手动在线切换)

场景:主库正常运行时,手动将主库切换到另一个节点

切换前查看从库状态

复制代码
[root@mysql2和mysql3 ~]# mysql -uroot -proot -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          # 当前主库是 10
                  Master_User: swp
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000004
          Read_Master_Log_Pos: 2085
               Relay_Log_File: mysql2-relay-bin.000008
                Relay_Log_Pos: 462
        Relay_Master_Log_File: mysql-bin.000004
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

执行在线切换(主库无故障)

目标:将主库从 10 切换到 20

复制代码
# 在 MHA Manager 上执行
[root@mysql-mha ~]# masterha_master_switch \
--conf=/etc/masterha/app1.cnf \              # 指定配置文件
--master_state=alive \                       # 主库状态为 alive(正常运行)
--new_master_host=172.25.254.20 \            # 新主库 IP
--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

Sun Apr 12 19:16:47 2026 - [info] MHA::MasterRotate version 0.58.
Sun Apr 12 19:16:47 2026 - [info] Starting online master switch..

# ========== 阶段1:配置检查 ==========
Sun Apr 12 19:16:47 2026 - [info] * Phase 1: Configuration Check Phase..
Sun Apr 12 19:16:48 2026 - [info] GTID failover mode = 1
Sun Apr 12 19:16:48 2026 - [info] Current Alive Master: 172.25.254.10(172.25.254.10:3306)
Sun Apr 12 19:16:48 2026 - [info] Alive Slaves:
Sun Apr 12 19:16:48 2026 - [info]   172.25.254.20(172.25.254.20:3306)  # 候选主库
Sun Apr 12 19:16:48 2026 - [info]   172.25.254.30(172.25.254.30:3306)  # 只读从库

# 询问是否在主库执行 FLUSH TABLES
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
Sun Apr 12 19:16:55 2026 - [info] Executing FLUSH NO_WRITE_TO_BINLOG TABLES. This may take long time..
Sun Apr 12 19:16:55 2026 - [info]  ok.

# 切换拓扑预览
From:
172.25.254.10(172.25.254.10:3306) (current master)
 +--172.25.254.20(172.25.254.20:3306)
 +--172.25.254.30(172.25.254.30:3306)

To:
172.25.254.20(172.25.254.20:3306) (new master)
 +--172.25.254.30(172.25.254.30:3306)
 +--172.25.254.10(172.25.254.10:3306)

# 确认执行切换
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

# ========== 阶段2:拒绝写入 ==========
Sun Apr 12 19:16:57 2026 - [info] * Phase 2: Rejecting updates Phase..
master_ip_online_change_script is not defined... Is it ok to proceed? (yes/NO): yes
Sun Apr 12 19:16:59 2026 - [info] Executing FLUSH TABLES WITH READ LOCK..  # 锁表

# ========== 阶段3:切换从库 ==========
Sun Apr 12 19:16:59 2026 - [info] * Switching slaves in parallel..
# 30 号从库切换到新主库 20
Sun Apr 12 19:17:01 2026 - [info] -- Slave switch on host 172.25.254.30 succeeded.
# 原主库 10 变成从库
Sun Apr 12 19:17:02 2026 - [info]  Resetting slave 172.25.254.10 and starting replication from the new master

# ========== 完成 ==========
Sun Apr 12 19:17:02 2026 - [info] Switching master to 172.25.254.20(172.25.254.20:3306) completed successfully.

切换后验证

复制代码
[root@MHA ~]# masterha_check_repl --conf=/etc/masterha/app1.cnf

Sun Apr 12 19:18:38 2026 - [info] Current Alive Master: 172.25.254.20(172.25.254.20:3306)   # ✅ 主库已变成 20
Sun Apr 12 19:18:38 2026 - [info]
172.25.254.20(172.25.254.20:3306) (current master)
 +--172.25.254.10(172.25.254.10:3306)      # 10 变成从库
 +--172.25.254.30(172.25.254.30:3306)

MySQL Replication Health is OK.

查看集群状态

验证:所有从库都指向新主库 20

复制代码
# 在 10 上查看
mysql -uroot -proot -e "show slave status\G;" | head -n 15
# Master_Host: 172.25.254.20

# 在 30 上查看
mysql -uroot -proot -e "show slave status\G;" | head -n 15
# Master_Host: 172.25.254.20

Master 故障手动切换

场景:主库宕机,手动执行故障切换

模拟主库故障

复制代码
# 在原来的主库(10)上停止 MySQL
[root@mysql-node2 mysql]# /etc/init.d/mysqld stop

执行故障切换

复制代码
# 在 MHA Manager 上执行
[root@mysql-mha masterha]# masterha_master_switch \
    --master_state=dead \                              # 主库已死
    --conf=/etc/masterha/app1.cnf \                    # 配置文件
    --dead_master_host=172.25.254.10 \                 # 故障主库 IP
    --dead_master_port=3306 \                          # 故障主库端口
    --new_master_host=172.25.254.20 \                  # 新主库 IP
    --new_master_port=3306 \                           # 新主库端口
    --ignore_last_failover                             # 忽略上次切换的锁文件

--ignore_last_failover 说明 :MHA 切换后会在 /etc/masterha/ 目录生成锁文件,防止重复切换。手动故障切换时需要忽略它。

切换详细过程

复制代码
[root@MHA ~]# masterha_master_switch --master_state=dead --conf=/etc/masterha/app1.cnf --dead_master_host=172.25.254.10 --dead_master_port=3306 --new_master_host=172.25.254.20 --new_master_port=3306 --ignore_last_failover

Sun Apr 12 19:30:41 2026 - [info] Starting master failover.
Sun Apr 12 19:30:42 2026 - [info] GTID failover mode = 1
Sun Apr 12 19:30:42 2026 - [info] Dead Servers:
Sun Apr 12 19:30:42 2026 - [info]   172.25.254.10(172.25.254.10:3306)    # 已宕机

Master 172.25.254.10(172.25.254.10:3306) is dead. Proceed? (yes/NO): yes

# 切换拓扑预览

From:
172.25.254.10(172.25.254.10:3306) (current master)
 +--172.25.254.20(172.25.254.20:3306)
 +--172.25.254.30(172.25.254.30:3306)

To:
172.25.254.20(172.25.254.20:3306) (new master)
 +--172.25.254.30(172.25.254.30:3306)

Starting master switch...? (yes/NO): yes

# ... 切换过程 ...

# ⚠️ 注意:切换过程中出现警告(但不影响整体成功)

Sun Apr 12 19:30:49 2026 - [error] gtid_wait(...) returned NULL on 172.25.254.30. Maybe SQL thread was aborted?
Sun Apr 12 19:30:49 2026 - [error] Master failover done, but recovery on slave partially failed.

----- Failover Report -----
Master 172.25.254.10(172.25.254.10:3306) is down!
Selected 172.25.254.20(172.25.254.20:3306) as a new master.
Master failover to 172.25.254.20 done, but recovery on slave partially failed.

查看切换后的状态

复制代码
# 在 30 上查看,已指向新主库 20
[root@mysql3 ~]# mysql -uroot -proot -e "show slave status\G;" | head -n 15
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 172.25.254.20          # ✅ 已指向 20
                  Master_User: swp
                  Master_Port: 3306
              Master_Log_File: mysql-bin.000002
          Read_Master_Log_Pos: 1063
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

恢复故障 MySQL 节点

场景:原来宕机的主库(10)修复后,需要重新加入集群作为从库

1. 删除 MHA 切换锁文件

bash

复制代码
# 查看锁文件(切换后自动生成)
[root@MHA ~]# ls /etc/masterha/
app1.cnf  app1.failover.complete    # ⚠️ 锁文件,阻止后续切换

# 删除锁文件
[root@MHA ~]# rm -fr /etc/masterha/app1.failover.complete

https://tuchuang1980.oss-cn-beijing.aliyuncs.com/tuchuang/image-20260412195332776.png

2. 在从库(20)上重置复制信息(可选)

复制代码
[root@mysql2 ~]# mysql -uroot -proot -e "reset slave;"

3. 启动故障节点

bash

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

4. 重新配置为从库

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

# 配置指向新主库 20(使用 GTID 自动定位)
mysql> CHANGE MASTER TO 
    MASTER_HOST='172.25.254.20', 
    MASTER_USER='swp', 
    MASTER_PASSWORD='swp', 
    MASTER_AUTO_POSITION=1;

# 启动复制
mysql> START SLAVE;

验证复制状态

复制代码
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 172.25.254.20          # ✅ 指向 20
                  Master_User: swp
                  Master_Port: 3306
              Master_Log_File: mysql-bin.000002
          Read_Master_Log_Pos: 1063
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

切回 Master 为 mysql1(10)

场景:希望将主库从 20 切换回 10

复制代码
[root@MHA ~]# masterha_master_switch \
    --conf=/etc/masterha/app1.cnf \
    --master_state=alive \
    --new_master_host=172.25.254.10 \
    --new_master_port=3306 \
    --orig_master_is_new_slave \
    --running_updates_limit=10000

自动故障切换

目标:MHA Manager 后台运行,自动监控主库状态,故障时自动切换

1. 清理环境

bash

复制代码
# 删除锁文件(如果存在)
[root@mysql-mha masterha]# rm -fr app1.failover.complete

# 清空日志文件便于观察
[root@MHA ~]# > /etc/masterha/*.log

# 开启日志监控(另开一个 shell)
[root@MHA ~]# watch -n 1 cat /etc/masterha/mha.log

2. 启动 MHA Manager 后台监控

bash

复制代码
# 启动自动切换(后台运行)
[root@MHA ~]# masterha_manager --conf=/etc/masterha/app1.cnf &

# 查看后台任务
[root@MHA ~]# jobs
[1]+  Running                 masterha_manager --conf=/etc/masterha/app1.cnf &

3. 监控日志输出

复制代码
[root@MHA ~]# watch -n 1 cat /etc/masterha/*.log #监控

4. 模拟主库故障

复制代码
# 在 10 上停止 MySQL
[root@mysql-node1 ~]# /etc/init.d/mysqld stop

5. 验证自动切换结果

bash

复制代码
# 在 30 上查看,应自动指向新主库 20
[root@mysql3 ~]# mysql -uroot -proot -e "show slave status\G;" | head -n 15

6. 故障节点恢复

复制代码
# 启动故障节点
[root@mysql-node1 ~]# /etc/init.d/mysqld start

# 重新配置为从库(指向新主库 20)
[root@mysql-node1 ~]# mysql -uroot -proot
mysql> CHANGE MASTER TO 
    MASTER_HOST='172.25.254.20', 
    MASTER_USER='swp', 
    MASTER_PASSWORD='swp', 
    MASTER_AUTO_POSITION=1;
mysql> START SLAVE;

7. 删除锁文件(重要)

注意:自动切换后 MHA Manager 会退出,同时生成锁文件。需要手动删除锁文件并重启 Manager,才能继续监控。

复制代码
[root@MHA ~]# rm -rf /etc/masterha/app1.failover.complete

为 MHA 添加 VIP 功能

目的:应用程序通过 VIP(虚拟 IP)访问数据库,主库切换时 VIP 自动漂移,实现应用无感知

1. 复制 VIP 切换脚本

复制代码
# 查看脚本文件
[root@MHA ~]# ll MHA-7/master_ip_*
-rw-r--r-- 1 root root 2156 Jan 14  2021 MHA-7/master_ip_failover      # 故障切换脚本
-rw-r--r-- 1 root root 2156 Apr 16 19:42 MHA-7/master_ip_online_change # 在线切换脚本

# 创建脚本目录并复制
[root@MHA ~]# cp MHA-7/master_ip_* /etc/masterha/scripts

2. 修改 MHA 配置文件,启用 VIP 脚本

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

3. 修改故障切换脚本中的 VIP 地址

复制代码
[root@MHA ~]# vim /etc/masterha/scripts/master_ip_failover

# 找到 vip 变量并修改
my $vip = '172.25.254.100/24';      # 设置 VIP 地址

4. 修改在线切换脚本中的 VIP 地址

bash

复制代码
[root@MHA ~]# vim MHA-7/master_ip_online_change

my $vip = '172.25.254.100/24';

5. 模拟故障并验证 VIP 漂移

6. 启动 MHA 监控

复制代码
# 检查状态
[root@MHA ~]# masterha_check_status --conf=/etc/masterha/app1.cnf &

# 启动 Manager
[root@MHA ~]# masterha_manager --conf=/etc/masterha/app1.cnf &

7. 手动绑定 VIP 到当前主库(10)

复制代码
# 在 1上添加 VIP
[root@mysql-node1 ~]# ip a a 172.25.254.100/24 dev eth0

# 查看 VIP 是否添加成功
[root@mysql-node1 ~]# ip a
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:05:9d:b4 brd ff:ff:ff:ff:ff:ff
    inet 172.25.254.10/24 brd 172.25.254.255 scope global noprefixroute eth0
    inet 172.25.254.100/24 scope global secondary eth0    # ✅ VIP 已添加

8. 停止主库触发切换

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

9. 验证 VIP 已漂移到新主库(20)

复制代码
# 在 2 上查看 VIP
[root@mysql-node2 ~]# ip a
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:cb:63:ce brd ff:ff:ff:ff:ff:ff
    inet 172.25.254.20/24 brd 172.25.254.255 scope global noprefixroute eth0
    inet 172.25.254.100/24 scope global secondary eth0    # ✅ VIP 已漂移到 2

00 qdisc mq state UP group default qlen 1000

link/ether 00:0c:29:05:9d:b4 brd ff:ff:ff:ff:ff:ff

inet 172.25.254.10/24 brd 172.25.254.255 scope global noprefixroute eth0

inet 172.25.254.100/24 scope global secondary eth0 # ✅ VIP 已添加

复制代码
[外链图片转存中...(img-oP9uRHMC-1776343362112)]

### 8. 停止主库触发切换

关闭主库 1

root@mysql-node1 \~\]# /etc/init.d/mysqld stop Shutting down MySQL... SUCCESS! ### 9. 验证 VIP 已漂移到新主库(20) ## 在 2 上查看 VIP \[root@mysql-node2 \~\]# ip a 2: eth0: \ mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:cb:63:ce brd ff:ff:ff:ff:ff:ff inet 172.25.254.20/24 brd 172.25.254.255 scope global noprefixroute eth0 inet 172.25.254.100/24 scope global secondary eth0 # ✅ VIP 已漂移到 2 [外链图片转存中...(img-gZthZZB7-1776343362112)] [外链图片转存中...(img-ul44dTbJ-1776343362112)]

相关推荐
00后程序员张2 小时前
iOS应用性能优化全解析:卡顿、耗电、启动与瘦身
android·ios·性能优化·小程序·uni-app·iphone·webview
毅炼2 小时前
MySQL 常见问题总结(3)
数据库·sql·mysql
杨云龙UP2 小时前
ODA-Oracle实践记录:通过Navicat导出导入表CSV文件并清理重复数据,处理OA待办延迟刷新问题_20260416
linux·运维·服务器·数据库·sql·mysql·oracle
程序员陆业聪2 小时前
跨端框架横评 2026:Flutter、React Native、KMP、小程序,谁是你下一个项目的正确答案?
android
aq55356002 小时前
Laravel3.x核心特性全解析
android
菜鸟国国2 小时前
Compose 点击/按压事件全解析:从基础到进阶,新手也能秒懂
android
xuhaoyu_cpp_java2 小时前
MySql学习(四)
数据库·经验分享·笔记·sql·学习·mysql
suliqiang2 小时前
MySQL数据库性能优化实战:系统性能提升100%的完整指南
数据库·mysql·性能优化
码点3 小时前
Android 设备重启如何拿日志
android