MySQL MHA 完整配置与故障后原主库还原指南
本文基于 CentOS7.6 + MySQL5.7 环境,详细梳理 MHA(Master High Availability)的完整配置流程,以及故障转移后 “还原原主库” 的操作步骤,确保集群能稳定实现高可用与角色回滚。
目录
(3)安装 MHA Manager(仅 Manager 节点 50)
(1)配置 SSH 无密码认证(Manager 节点 50)
(3)配置 MHA 主配置文件(Manager 节点 50)
前言
本文基于 CentOS7.6 + MySQL5.7 环境,详细梳理 MHA(Master High Availability)的完整配置流程,以及故障转移后 “还原原主库” 的操作步骤,确保集群能稳定实现高可用与角色回滚。
一、MHA 核心概念与环境准备
1. 核心作用
MHA 用于解决 MySQL 单点故障问题,实现 0-30 秒自动故障切换,同时最大程度保障数据一致性,支持 “一主多从” 架构(最少 3 台服务器)。
2. 架构组成
节点类型 | 作用 | IP 示例 | 安装组件 |
---|---|---|---|
MHA Manager | 管理集群,定时探测主库,故障时自动切换 | 192.168.100.50 | mha4mysql-node + manager |
原主库(Master) | 初始主库,负责写入操作 | 192.168.100.47 | MySQL5.7 + mha4mysql-node |
新主库(Slave1) | 故障转移后的临时主库,故障前为从库 | 192.168.100.48 | MySQL5.7 + mha4mysql-node |
从库(Slave2) | 仅负责读取,故障转移后自动指向新主库 | 192.168.100.49 | MySQL5.7 + mha4mysql-node |
3. 环境初始化(所有节点执行)
# 1. 关闭防火墙与SELinux
systemctl stop firewalld && systemctl disable firewalld
setenforce 0 && sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
# 2. 配置主机名(按节点分别执行)
# 原主库(47):hostnamectl set-hostname master47
# 新主库(48):hostnamectl set-hostname slave48
# 从库(49):hostnamectl set-hostname slave49
# MHA Manager(50):hostnamectl set-hostname mha-manager
# 3. 配置hosts解析(所有节点)
echo "192.168.100.47 master47
192.168.100.48 slave48
192.168.100.49 slave49
192.168.100.50 mha-manager" >> /etc/hosts
二、MHA 完整配置流程
1. 配置 MySQL 一主两从(核心前提)
(1)修改 MySQL 配置文件(各节点)
-
原主库(47):/etc/my.cnf
[mysqld] server-id = 47 # 唯一ID,不可重复 log_bin = master-bin # 开启binlog,用于主从同步 log-slave-updates = true # 允许从库同步主库的binlog(故障转移后从库变主库需用)
-
新主库(48):/etc/my.cnf
[mysqld] server-id = 48 log_bin = master-bin relay-log = relay-log-bin # 开启中继日志 relay-log-index = slave-relay-bin.index read_only = 1 # 故障前设为只读(从库)
-
从库(49):/etc/my.cnf
[mysqld] server-id = 49 relay-log = relay-log-bin relay-log-index = slave-relay-bin.index read_only = 1
(2)重启 MySQL 并配置主从同步
# 所有节点重启MySQL
systemctl restart mysqld && systemctl enable mysqld
# 1. 原主库(47)创建同步账号
mysql -uroot -p
grant replication slave on *.* to 'myslave'@'192.168.100.%' identified by '123456';
grant all privileges on *.* to 'mha'@'192.168.100.%' identified by 'manager'; # MHA管理账号
flush privileges;
# 2. 查看原主库binlog信息(记录File和Position)
show master status;
# 示例输出:File=master-bin.000001,Position=154
# 3. 新主库(48)和从库(49)配置同步(替换File和Position)
mysql -uroot -p
change master to
master_host='192.168.100.47',
master_user='myslave',
master_password='123456',
master_log_file='master-bin.000001',
master_log_pos=154;
start slave; # 启动同步
# 4. 验证同步状态(IO和SQL线程需为Yes)
show slave status\G
2. 安装 MHA 组件(所有节点)
(1)安装依赖包
# 所有节点安装epel源和依赖
yum install epel-release --nogpgcheck -y
yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager
(2)安装 MHA Node(所有节点)
# 上传mha4mysql-node-0.57.tar.gz到/opt目录,解压安装
cd /opt
tar zxvf mha4mysql-node-0.57.tar.gz
cd mha4mysql-node-0.57
perl Makefile.PL && make && make install
(3)安装 MHA Manager(仅 Manager 节点 50)
# 上传mha4mysql-manager-0.57.tar.gz到/opt目录,解压安装
cd /opt
tar zxvf mha4mysql-manager-0.57.tar.gz
cd mha4mysql-manager-0.57
perl Makefile.PL && make && make install
3. 配置 MHA 关键脚本与文件
(1)配置 SSH 无密码认证(Manager 节点 50)
# Manager节点生成密钥,免密登录所有MySQL节点
ssh-keygen -t rsa # 一路回车
ssh-copy-id 192.168.100.47
ssh-copy-id 192.168.100.48
ssh-copy-id 192.168.100.49
# MySQL节点间互免密(避免故障切换时无法操作)
# 原主库(47):ssh-copy-id 192.168.100.48 && ssh-copy-id 192.168.100.49
# 新主库(48):ssh-copy-id 192.168.100.47 && ssh-copy-id 192.168.100.49
# 从库(49):ssh-copy-id 192.168.100.47 && ssh-copy-id 192.168.100.48
(2)配置 VIP 管理脚本(Manager 节点 50)
# 复制脚本到/usr/local/bin
cp /opt/mha4mysql-manager-0.57/samples/scripts/master_ip_failover /usr/local/bin/
# 修改脚本(指定VIP、网卡等信息)
vim /usr/local/bin/master_ip_failover
替换脚本内容为:
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
my ($command, $orig_master_ip, $new_master_ip);
my $vip = '192.168.100.200'; # 虚拟IP(业务访问用)
my $ifdev = 'ens33'; # 网卡名
my $key = '1'; # 虚拟网卡序号
GetOptions(
'command=s' => \$command,
'orig_master_ip=s' => \$orig_master_ip,
'new_master_ip=s' => \$new_master_ip,
);
if ($command eq "stop") {
# 原主库移除VIP
`ssh root\@$orig_master_ip "ifconfig $ifdev:$key down"`;
} elsif ($command eq "start") {
# 新主库绑定VIP
`ssh root\@$new_master_ip "ifconfig $ifdev:$key $vip"`;
}
exit 0;
(3)配置 MHA 主配置文件(Manager 节点 50)
# 创建配置目录
mkdir /etc/masterha
# 复制模板配置文件
cp /opt/mha4mysql-manager-0.57/samples/conf/app1.cnf /etc/masterha/
# 修改配置文件
vim /etc/masterha/app1.cnf
替换内容为:
[server default]
manager_log=/var/log/masterha/app1/manager.log # MHA日志路径
manager_workdir=/var/log/masterha/app1 # MHA工作目录
master_binlog_dir=/var/lib/mysql # MySQL binlog存储路径
master_ip_failover_script=/usr/local/bin/master_ip_failover # VIP脚本路径
password=manager # MHA管理账号密码
ping_interval=1 # 探测主库间隔(秒)
remote_workdir=/tmp # 远端临时目录
repl_password=123456 # 主从同步账号密码
repl_user=myslave # 主从同步账号
ssh_user=root # SSH登录用户
user=mha # MHA管理账号
# 原主库(47)
[server1]
hostname=192.168.100.47
port=3306
# 新主库(48)- 设为候选主库
[server2]
hostname=192.168.100.48
port=3306
candidate_master=1 # 故障时优先选为新主库
check_repl_delay=0 # 忽略同步延迟,强制选为新主库
# 从库(49)
[server3]
hostname=192.168.100.49
port=3306
4. 启动 MHA 并验证
# 1. 创建日志目录
mkdir -p /var/log/masterha/app1
# 2. 原主库(47)手动绑定VIP
ifconfig ens33:1 192.168.100.200/24
# 3. 测试SSH连通性(Manager节点50)
masterha_check_ssh --conf=/etc/masterha/app1.cnf
# 预期输出:All SSH connection tests passed successfully.
# 4. 测试主从复制健康度
masterha_check_repl --conf=/etc/masterha/app1.cnf
# 预期输出:MySQL Replication Health is OK.
# 5. 启动MHA Manager
nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/masterha/app1/manager.log 2>&1 &
# 6. 验证MHA状态(显示running且主库为47)
masterha_check_status --conf=/etc/masterha/app1.cnf
三、故障转移与原主库还原操作
1. 模拟故障转移(原主库 47 宕机)
(1)停止原主库(47)MySQL 服务
# 原主库(47)执行,模拟故障
systemctl stop mysqld
(2)观察 MHA 故障切换(Manager 节点 50)
# 查看日志,确认切换过程
tail -f /var/log/masterha/app1/manager.log
# 验证结果
masterha_check_status --conf=/etc/masterha/app1.cnf
# 预期输出:master:192.168.100.48(新主库已切换为48)
# 验证新主库(48)VIP绑定
ssh 192.168.100.48 "ifconfig" | grep 192.168.100.200
2. 还原原主库(47)为新主库
故障转移后,原主库 47 变为从库(同步 48 数据),若需还原 47 为主库,必须重新配置主从复制,步骤如下:
(1)恢复原主库(47)MySQL 服务
# 原主库(47)执行
systemctl restart mysqld
(2)停止新主库(48)写入,备份数据
# 新主库(48)执行,锁表防止写入
mysql -uroot -p
FLUSH TABLES WITH READ LOCK;
# 备份全量数据(新主库48执行,生成备份文件)
mysqldump -uroot -p --all-databases --master-data=2 > /opt/mysql_backup.sql
# --master-data=2:记录当前binlog位置,供从库同步用
(3)原主库(47)导入备份数据
# 1. 复制备份文件到原主库(47)
scp 192.168.100.48:/opt/mysql_backup.sql /opt/
# 2. 原主库(47)导入数据
mysql -uroot -p < /opt/mysql_backup.sql
(4)新主库(48)和从库(49)配置同步原主库(47)
# 1. 原主库(47)查看binlog信息(记录File和Position)
mysql -uroot -p
show master status;
# 示例输出:File=master-bin.000002,Position=154
# 2. 新主库(48)解除锁表,配置为从库(同步47)
mysql -uroot -p
UNLOCK TABLES; # 解锁
stop slave; # 停止原同步(同步48→47)
reset slave all; # 清除原从库配置
# 配置同步原主库(47)
change master to
master_host='192.168.100.47',
master_user='myslave',
master_password='123456',
master_log_file='master-bin.000002', # 替换为47的File
master_log_pos=154; # 替换为47的Position
start slave; # 启动同步
# 3. 从库(49)重新配置同步(同步47)
mysql -uroot -p
stop slave;
reset slave all;
change master to
master_host='192.168.100.47',
master_user='myslave',
master_password='123456',
master_log_file='master-bin.000002',
master_log_pos=154;
start slave;
(5)更新 MHA 配置并重启
# Manager节点50修改配置文件,确保主库指向47
vim /etc/masterha/app1.cnf
# 确认[server1](47)无额外限制,[server2](48)候选主库配置可保留
# 重启MHA Manager
masterha_stop --conf=/etc/masterha/app1.cnf
nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/masterha/app1/manager.log 2>&1 &
# 验证结果(主库已还原为47)
masterha_check_status --conf=/etc/masterha/app1.cnf
四、常见问题排查
- MHA 启动报错 “2 non-slave servers”:检查所有节点
show slave status\G
,确保只有 1 个主库(非从库),其他均为从库(IO/SQL 线程 Yes)。 - 手动切换报错 “advisory lock failed”:先执行
masterha_stop --conf=/etc/masterha/app1.cnf
停止 MHA,再重新切换。 - VIP 未自动迁移:检查
master_ip_failover
脚本路径和权限,确保chmod +x /usr/local/bin/master_ip_failover
。
MySQL MHA 配置与还原操作 Checklist
本清单按 “环境初始化→MHA 配置→故障模拟→原主库还原” 流程设计,明确每步操作节点、命令及预期结果,可直接对照执行。
一、环境初始化(所有节点执行)
步骤 | 操作节点 | 具体命令 | 预期结果 |
---|---|---|---|
1 | 所有节点 | systemctl stop firewalld && systemctl disable firewalld |
防火墙停止且开机不启动,无报错 |
2 | 所有节点 | setenforce 0 && sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config |
getenforce 输出 Permissive ,配置文件修改生效 |
3 | 各节点分别执行 | 原主库(47):hostnamectl set-hostname master47 新主库(48): hostnamectl set-hostname slave48 从库(49): hostnamectl set-hostname slave49 MHA Manager(50): hostnamectl set-hostname mha-manager |
hostname 命令输出对应节点名(如 master47) |
4 | 所有节点 | echo "192.168.100.47 master47<br>192.168.100.48 slave48<br>192.168.100.49 slave49<br>192.168.100.50 mha-manager" >> /etc/hosts |
ping master47 能通,无丢包 |
二、MHA 配置(分节点执行)
2.1 配置 MySQL 一主两从
步骤 | 操作节点 | 具体命令 | 预期结果 |
---|---|---|---|
1 | 原主库(47) | 修改 /etc/my.cnf ,添加:server-id = 47 log_bin = master-bin log-slave-updates = true |
保存后无语法错误 |
2 | 新主库(48) | 修改 /etc/my.cnf ,添加:server-id = 48 log_bin = master-bin relay-log = relay-log-bin relay-log-index = slave-relay-bin.index read_only = 1 |
保存后无语法错误 |
3 | 从库(49) | 修改 /etc/my.cnf ,添加:server-id = 49 relay-log = relay-log-bin relay-log-index = slave-relay-bin.index read_only = 1 |
保存后无语法错误 |
4 | 所有节点 | systemctl restart mysqld && systemctl enable mysqld |
systemctl status mysqld 显示 active (running) |
5 | 原主库(47) | 登录 MySQL:mysql -uroot -p 执行: grant replication slave on *.* to 'myslave'@'192.168.100.%' identified by '123456'; grant all privileges on *.* to 'mha'@'192.168.100.%' identified by 'manager'; flush privileges; |
无报错,权限添加成功 |
6 | 原主库(47) | 执行 show master status; |
输出 File (如 master-bin.000001)和 Position (如 154),记录备用 |
7 | 新主库(48)、从库(49) | 登录 MySQL:mysql -uroot -p 执行(替换 File 和 Position): change master to master_host='192.168.100.47',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=154; start slave; |
无报错,同步启动 |
8 | 新主库(48)、从库(49) | 执行 show slave status\G |
Slave_IO_Running 和 Slave_SQL_Running 均为 Yes |
2.2 安装 MHA 组件
步骤 | 操作节点 | 具体命令 | 预期结果 |
---|---|---|---|
1 | 所有节点 | yum install epel-release --nogpgcheck -y && yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager |
依赖包安装完成,无报错 |
2 | 所有节点 | 上传 mha4mysql-node-0.57.tar.gz 到 /opt ,执行:cd /opt && tar zxvf mha4mysql-node-0.57.tar.gz && cd mha4mysql-node-0.57 && perl Makefile.PL && make && make install |
安装完成,无 error 提示 |
3 | MHA Manager(50) | 上传 mha4mysql-manager-0.57.tar.gz 到 /opt ,执行:cd /opt && tar zxvf mha4mysql-manager-0.57.tar.gz && cd mha4mysql-manager-0.57 && perl Makefile.PL && make && make install |
安装完成,无 error 提示 |
2.3 配置 MHA 关键脚本与文件
步骤 | 操作节点 | 具体命令 | 预期结果 |
---|---|---|---|
1 | MHA Manager(50) | ssh-keygen -t rsa (一路回车)ssh-copy-id 192.168.100.47 && ssh-copy-id 192.168.100.48 && ssh-copy-id 192.168.100.49 |
输入目标节点密码后,ssh 192.168.100.47 无需输密码 |
2 | 所有 MySQL 节点 | 互传 SSH 密钥(如 master47 执行 ssh-copy-id 192.168.100.48 ) |
节点间 ssh 登录无需输密码 |
3 | MHA Manager(50) | cp /opt/mha4mysql-manager-0.57/samples/scripts/master_ip_failover /usr/local/bin/ |
ls /usr/local/bin/master_ip_failover 显示文件存在 |
4 | MHA Manager(50) | 修改 master_ip_failover 脚本,指定 vip='192.168.100.200' 、ifdev='ens33' |
脚本内容正确,无语法错误 |
5 | MHA Manager(50) | chmod +x /usr/local/bin/master_ip_failover |
ls -l /usr/local/bin/master_ip_failover 显示 x 权限 |
6 | MHA Manager(50) | mkdir /etc/masterha && cp /opt/mha4mysql-manager-0.57/samples/conf/app1.cnf /etc/masterha/ |
ls /etc/masterha/app1.cnf 显示文件存在 |
7 | MHA Manager(50) | 修改 app1.cnf ,配置节点信息、账号密码、脚本路径 |
配置内容与实际环境一致 |
2.4 启动 MHA 并验证
步骤 | 操作节点 | 具体命令 | 预期结果 | |
---|---|---|---|---|
1 | MHA Manager(50) | mkdir -p /var/log/masterha/app1 |
目录创建成功,无报错 | |
2 | 原主库(47) | ifconfig ens33:1 192.168.100.200/24 |
ifconfig 显示 ens33:1 网卡,IP 为 192.168.100.200 |
|
3 | MHA Manager(50) | masterha_check_ssh --conf=/etc/masterha/app1.cnf |
输出 All SSH connection tests passed successfully. |
|
4 | MHA Manager(50) | masterha_check_repl --conf=/etc/masterha/app1.cnf |
输出 MySQL Replication Health is OK. |
|
5 | MHA Manager(50) | nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/masterha/app1/manager.log 2>&1 & |
进程启动,`ps -ef | grep masterha` 能看到进程 |
6 | MHA Manager(50) | masterha_check_status --conf=/etc/masterha/app1.cnf |
输出 app1 (pid: xxx) is running(0:PING_OK), master:192.168.100.47 |
三、故障模拟(分节点执行)
步骤 | 操作节点 | 具体命令 | 预期结果 |
---|---|---|---|
1 | 原主库(47) | systemctl stop mysqld |
systemctl status mysqld 显示 inactive (dead) |
2 | MHA Manager(50) | tail -f /var/log/masterha/app1/manager.log |
日志显示 “Master is down”“Promoting 192.168.100.48 to new master” |
3 | MHA Manager(50) | masterha_check_status --conf=/etc/masterha/app1.cnf |
输出 master:192.168.100.48 ,切换完成 |
4 | 新主库(48) | ifconfig |
显示 ens33:1 网卡,IP 为 192.168.100.200(VIP 迁移成功) |
四、原主库还原(分节点执行)
步骤 | 操作节点 | 具体命令 | 预期结果 |
---|---|---|---|
1 | 原主库(47) | systemctl restart mysqld |
systemctl status mysqld 显示 active (running) |
2 | 新主库(48) | 登录 MySQL:mysql -uroot -p 执行 FLUSH TABLES WITH READ LOCK; |
无报错,表锁定成功 |
3 | 新主库(48) | mysqldump -uroot -p --all-databases --master-data=2 > /opt/mysql_backup.sql |
/opt 目录下生成 mysql_backup.sql 文件 |
4 | 原主库(47) | scp 192.168.100.48:/opt/mysql_backup.sql /opt/ |
备份文件复制到原主库 /opt 目录 |
5 | 原主库(47) | mysql -uroot -p < /opt/mysql_backup.sql |
数据导入完成,无报错 |
6 | 原主库(47) | 登录 MySQL,执行 show master status; |
输出新的 File 和 Position ,记录备用 |
7 | 新主库(48) | 登录 MySQL,执行:UNLOCK TABLES; stop slave; reset slave all; change master to master_host='192.168.100.47',master_user='myslave',master_password='123456',master_log_file='xxx',master_log_pos=xxx; start slave; |
show slave status\G 显示 Slave_IO_Running 和 Slave_SQL_Running 为 Yes |
8 | 从库(49) | 登录 MySQL,执行:stop slave; reset slave all; change master to master_host='192.168.100.47',master_user='myslave',master_password='123456',master_log_file='xxx',master_log_pos=xxx; start slave; |
show slave status\G 显示 Slave_IO_Running 和 Slave_SQL_Running 为 Yes |
9 | MHA Manager(50) | masterha_stop --conf=/etc/masterha/app1.cnf |
输出 Stopped app1 successfully. |
10 | MHA Manager(50) | nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/masterha/app1/manager.log 2>&1 & |
进程重启成功 |
11 | MHA Manager(50) | masterha_check_status --conf=/etc/masterha/app1.cnf |
输出 master:192.168.100.47 ,原主库还原成功 |
MySQL MHA 自动化执行脚本(分模块)
以下脚本按 “环境初始化→MHA 配置启动→故障模拟” 拆分,每个脚本开头预留核心参数,修改后即可一键执行,适配 CentOS7 系统。
一、环境初始化脚本(env_init.sh)
功能
关闭防火墙 / SELinux、配置主机名、hosts 解析(所有节点需分别执行,或通过批量工具分发执行)。
#!/bin/bash
# ======================== 可修改参数 ========================
# 当前节点角色(master47/slave48/slave49/mha-manager)
NODE_ROLE="master47"
# 当前节点IP(对应角色)
NODE_IP="192.168.100.47"
# 其他节点IP(按角色填写)
MASTER_IP="192.168.100.47"
SLAVE1_IP="192.168.100.48"
SLAVE2_IP="192.168.100.49"
MHA_MANAGER_IP="192.168.100.50"
# ============================================================
# 1. 关闭防火墙并禁用开机启动
echo "=== 关闭防火墙 ==="
systemctl stop firewalld
systemctl disable firewalld
if [ $? -eq 0 ]; then
echo "防火墙关闭成功"
else
echo "防火墙关闭失败,退出脚本"
exit 1
fi
# 2. 关闭SELinux并永久禁用
echo -e "\n=== 关闭SELinux ==="
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
if [ $(getenforce) = "Permissive" ]; then
echo "SELinux关闭成功"
else
echo "SELinux关闭失败,退出脚本"
exit 1
fi
# 3. 配置主机名(按角色匹配)
echo -e "\n=== 配置主机名 ==="
case $NODE_ROLE in
"master47")
hostnamectl set-hostname master47
;;
"slave48")
hostnamectl set-hostname slave48
;;
"slave49")
hostnamectl set-hostname slave49
;;
"mha-manager")
hostnamectl set-hostname mha-manager
;;
*)
echo "节点角色错误,仅支持master47/slave48/slave49/mha-manager"
exit 1
;;
esac
if [ $(hostname) = $NODE_ROLE ]; then
echo "主机名配置成功(当前主机名:$(hostname))"
else
echo "主机名配置失败,退出脚本"
exit 1
fi
# 4. 配置hosts解析
echo -e "\n=== 配置hosts解析 ==="
cat >> /etc/hosts << EOF
$MASTER_IP master47
$SLAVE1_IP slave48
$SLAVE2_IP slave49
$MHA_MANAGER_IP mha-manager
EOF
# 验证hosts生效
if ping -c 1 master47 > /dev/null 2>&1; then
echo "hosts配置成功"
else
echo "hosts配置失败,退出脚本"
exit 1
fi
echo -e "\n=== 环境初始化完成 ==="
二、MHA 配置与启动脚本(mha_start.sh)
功能
安装 MHA 组件、配置 MySQL 主从、SSH 免密、MHA 核心配置,最终启动 MHA(仅在 MHA Manager 节点执行)。
#!/bin/bash
# ======================== 可修改参数 ========================
# MySQL相关
MYSQL_ROOT_PWD="123456" # MySQL root密码
REPL_USER="myslave" # 主从同步账号
REPL_PWD="123456" # 主从同步密码
MHA_USER="mha" # MHA管理账号
MHA_PWD="manager" # MHA管理密码
# 节点IP
MASTER_IP="192.168.100.47" # 原主库IP
SLAVE1_IP="192.168.100.48" # 新主库(候选)IP
SLAVE2_IP="192.168.100.49" # 从库IP
MHA_MANAGER_IP="192.168.100.50" # MHA Manager IP
# VIP配置
VIP="192.168.100.200" # 虚拟IP
ETH_NAME="ens33" # 网卡名(如ens33)
# MHA路径
MHA_CONF="/etc/masterha/app1.cnf"# MHA配置文件路径
MHA_LOG_DIR="/var/log/masterha/app1" # MHA日志目录
# MHA安装包路径(需提前上传到/opt)
NODE_TAR="mha4mysql-node-0.57.tar.gz"
MANAGER_TAR="mha4mysql-manager-0.57.tar.gz"
# ============================================================
# 1. 所有节点安装依赖(通过SSH批量执行)
echo "=== 所有节点安装依赖包 ==="
for IP in $MASTER_IP $SLAVE1_IP $SLAVE2_IP $MHA_MANAGER_IP; do
echo "=== 正在处理节点:$IP ==="
ssh root@$IP "yum install epel-release --nogpgcheck -y && yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager"
if [ $? -eq 0 ]; then
echo "$IP 依赖安装成功"
else
echo "$IP 依赖安装失败,退出脚本"
exit 1
fi
done
# 2. 所有节点安装MHA Node
echo -e "\n=== 所有节点安装MHA Node ==="
for IP in $MASTER_IP $SLAVE1_IP $SLAVE2_IP $MHA_MANAGER_IP; do
echo "=== 正在处理节点:$IP ==="
# 复制安装包到目标节点
scp /opt/$NODE_TAR root@$IP:/opt/
# 远程执行安装
ssh root@$IP "cd /opt && tar zxvf $NODE_TAR && cd ${NODE_TAR%.tar.gz} && perl Makefile.PL && make && make install"
if [ $? -eq 0 ]; then
echo "$IP MHA Node安装成功"
else
echo "$IP MHA Node安装失败,退出脚本"
exit 1
fi
done
# 3. MHA Manager节点安装MHA Manager
echo -e "\n=== MHA Manager节点安装Manager ==="
cd /opt && tar zxvf $MANAGER_TAR && cd ${MANAGER_TAR%.tar.gz} && perl Makefile.PL && make && make install
if [ $? -eq 0 ]; then
echo "MHA Manager安装成功"
else
echo "MHA Manager安装失败,退出脚本"
exit 1
fi
# 4. 配置SSH免密(MHA Manager免密登录所有节点)
echo -e "\n=== 配置MHA Manager免密登录所有节点 ==="
ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
for IP in $MASTER_IP $SLAVE1_IP $SLAVE2_IP; do
ssh-copy-id -i ~/.ssh/id_rsa.pub root@$IP
if [ $? -eq 0 ]; then
echo "MHA Manager免密登录$IP 成功"
else
echo "MHA Manager免密登录$IP 失败,退出脚本"
exit 1
fi
done
# 5. 配置MySQL主从(原主库创建账号+从库配置同步)
echo -e "\n=== 配置MySQL主从 ==="
# 5.1 原主库创建账号
echo "=== 原主库创建同步账号 ==="
ssh root@$MASTER_IP "mysql -uroot -p$MYSQL_ROOT_PWD -e \"grant replication slave on *.* to '$REPL_USER'@'192.168.100.%' identified by '$REPL_PWD'; grant all privileges on *.* to '$MHA_USER'@'192.168.100.%' identified by '$MHA_PWD'; flush privileges;\""
if [ $? -eq 0 ]; then
echo "原主库账号创建成功"
else
echo "原主库账号创建失败,退出脚本"
exit 1
fi
# 5.2 获取原主库binlog信息
echo "=== 获取原主库binlog信息 ==="
BINLOG_INFO=$(ssh root@$MASTER_IP "mysql -uroot -p$MYSQL_ROOT_PWD -e 'show master status\G' | grep -E 'File|Position'")
BINLOG_FILE=$(echo $BINLOG_INFO | awk '{print $2}')
BINLOG_POS=$(echo $BINLOG_INFO | awk '{print $4}')
echo "原主库binlog文件:$BINLOG_FILE,位置:$BINLOG_POS"
# 5.3 从库配置同步
for SLAVE_IP in $SLAVE1_IP $SLAVE2_IP; do
echo "=== 配置从库:$SLAVE_IP ==="
ssh root@$SLAVE_IP "mysql -uroot -p$MYSQL_ROOT_PWD -e \"change master to master_host='$MASTER_IP',master_user='$REPL_USER',master_password='$REPL_PWD',master_log_file='$BINLOG_FILE',master_log_pos=$BINLOG_POS; start slave;\""
# 验证同步状态
SYNC_STATUS=$(ssh root@$SLAVE_IP "mysql -uroot -p$MYSQL_ROOT_PWD -e 'show slave status\G' | grep -E 'Slave_IO_Running|Slave_SQL_Running'")
if echo $SYNC_STATUS | grep -q "Yes Yes"; then
echo "$SLAVE_IP 主从同步配置成功"
else
echo "$SLAVE_IP 主从同步配置失败,退出脚本"
exit 1
fi
done
# 6. 配置MHA VIP脚本
echo -e "\n=== 配置MHA VIP脚本 ==="
# 复制脚本模板
cp /opt/${MANAGER_TAR%.tar.gz}/samples/scripts/master_ip_failover /usr/local/bin/
# 修改脚本内容(替换VIP、网卡名)
sed -i "s/my \$vip = '192.168.0.100'/my \$vip = '$VIP'/" /usr/local/bin/master_ip_failover
sed -i "s/my \$ifdev = 'eth0'/my \$ifdev = '$ETH_NAME'/" /usr/local/bin/master_ip_failover
chmod +x /usr/local/bin/master_ip_failover
if [ -x /usr/local/bin/master_ip_failover ]; then
echo "VIP脚本配置成功"
else
echo "VIP脚本配置失败,退出脚本"
exit 1
fi
# 7. 配置MHA主配置文件
echo -e "\n=== 配置MHA主配置文件 ==="
mkdir -p $(dirname $MHA_CONF) $MHA_LOG_DIR
cat > $MHA_CONF << EOF
[server default]
manager_log=$MHA_LOG_DIR/manager.log
manager_workdir=$MHA_LOG_DIR
master_binlog_dir=/var/lib/mysql
master_ip_failover_script=/usr/local/bin/master_ip_failover
password=$MHA_PWD
ping_interval=1
remote_workdir=/tmp
repl_password=$REPL_PWD
repl_user=$REPL_USER
ssh_user=root
user=$MHA_USER
[server1]
hostname=$MASTER_IP
port=3306
[server2]
hostname=$SLAVE1_IP
port=3306
candidate_master=1
check_repl_delay=0
[server3]
hostname=$SLAVE2_IP
port=3306
EOF
if [ -f $MHA_CONF ]; then
echo "MHA配置文件创建成功"
else
echo "MHA配置文件创建失败,退出脚本"
exit 1
fi
# 8. 原主库绑定VIP
echo -e "\n=== 原主库绑定VIP ==="
ssh root@$MASTER_IP "ifconfig $ETH_NAME:1 $VIP/24"
if ssh root@$MASTER_IP "ifconfig | grep $VIP"; then
echo "原主库VIP绑定成功"
else
echo "原主库VIP绑定失败,退出脚本"
exit 1
fi
# 9. 启动MHA并验证
echo -e "\n=== 启动MHA Manager ==="
nohup masterha_manager --conf=$MHA_CONF --remove_dead_master_conf --ignore_last_failover < /dev/null > $MHA_LOG_DIR/manager.log 2>&1 &
sleep 5
# 验证状态
MHA_STATUS=$(masterha_check_status --conf=$MHA_CONF)
if echo $MHA_STATUS | grep -q "running"; then
echo "MHA启动成功,状态:$MHA_STATUS"
else
echo "MHA启动失败,状态:$MHA_STATUS,退出脚本"
exit 1
fi
echo -e "\n=== MHA配置与启动完成 ==="
三、故障模拟脚本(fault_simulate.sh)
功能
停止原主库 MySQL 服务,模拟故障,自动验证 MHA 故障转移结果。
#!/bin/bash
# ======================== 可修改参数 ========================
MASTER_IP="192.168.100.47" # 原主库IP(故障节点)
SLAVE1_IP="192.168.100.48" # 新主库(候选)IP
MHA_CONF="/etc/masterha/app1.cnf"# MHA配置文件路径
VIP="192.168.100.200" # 虚拟IP
ETH_NAME="ens33" # 网卡名
# ============================================================
# 1. 停止原主库MySQL服务
echo "=== 停止原主库($MASTER_IP)MySQL服务 ==="
ssh root@$MASTER_IP "systemctl stop mysqld"
if ssh root@$MASTER_IP "systemctl status mysqld | grep 'inactive (dead)'"; then
echo "原主库MySQL已停止,故障模拟成功"
else
echo "原主库MySQL停止失败,退出脚本"
exit 1
fi
# 2. 等待MHA故障转移(默认等待10秒,可根据集群规模调整)
echo -e "\n=== 等待MHA故障转移(10秒) ==="
sleep 10
# 3. 验证故障转移结果
echo -e "\n=== 验证故障转移结果 ==="
# 3.1 验证MHA状态(主库是否切换为SLAVE1_IP)
echo "=== 验证MHA主库切换 ==="
MHA_STATUS=$(masterha_check_status --conf=$MHA_CONF)
if echo $MHA_STATUS | grep -q $SLAVE1_IP; then
echo "MHA主库切换成功,当前主库:$SLAVE1_IP"
else
echo "MHA主库切换失败,当前状态:$MHA_STATUS,退出脚本"
exit 1
fi
# 3.2 验证VIP是否迁移到新主库
echo -e "\n=== 验证VIP($VIP)迁移 ==="
if ssh root@$SLAVE1_IP "ifconfig | grep $VIP"; then
echo "VIP已迁移到新主库($SLAVE1_IP),故障转移完成"
else
echo "VIP未迁移,故障转移失败,退出脚本"
exit 1
fi
echo -e "\n=== 故障模拟与转移验证完成 ==="
脚本使用说明
1. 准备工作
- 将 MHA 安装包(
mha4mysql-node-0.57.tar.gz
、mha4mysql-manager-0.57.tar.gz
)上传到 MHA Manager 节点的/opt
目录。 - 给所有脚本添加执行权限:
chmod +x env_init.sh mha_start.sh fault_simulate.sh
。 - 根据实际环境修改每个脚本开头的 “可修改参数”(如 IP、密码、网卡名)。
2. 执行顺序
- 环境初始化:在每个节点分别执行
./env_init.sh
(或通过 Ansible 批量执行)。 - MHA 配置启动:在 MHA Manager 节点执行
./mha_start.sh
(一键完成组件安装、主从配置、MHA 启动)。 - 故障模拟:在 MHA Manager 节点执行
./fault_simulate.sh
(模拟原主库故障,验证转移结果)。
更多推荐
所有评论(0)