文章目录

MySQL MHA 完整指南(适配 /usr/local/mysql

1. MHA 概述

1.1 什么是 MHA

MHA(Master High Availability)是一套专为 MySQL 设计的高可用解决方案,核心功能是实现主库故障自动切换与主从复制管理,旨在解决 MySQL 单点故障问题,保障业务连续性。

其核心优势:

  • 快速故障切换:主库宕机后,0-30秒内完成自动切换,降低业务中断时间。
  • 数据一致性优先:故障切换过程中最大程度保留主库二进制日志(binlog),避免数据丢失。
  • 透明化操作:切换过程对应用层完全透明,无需手动修改数据库连接地址。

2. MHA 组成架构

MHA 架构由MySQL 基础架构MHA 组件两部分组成,需先搭建 MySQL 主从复制,再部署 MHA 组件。

2.1 MySQL 基础架构(MHA 依赖)

MHA 基于 MySQL 主从复制实现,支持以下常见架构(推荐 一主两从,最少3台服务器):

架构类型 适用场景 特点
一主一从 小型业务、读写分离需求低 结构简单,但从库故障无备用
一主两从 中大型业务、高可用需求高 MHA 推荐架构,有备用从库切换
主主复制(互为主从) 读写分离+主库备用 需配合 Keepalived 管理 VIP
级联复制(M-S-S-S) 从库数量多、减轻主库压力 主库仅同步到一级从库,再级联

2.2 MHA 核心组件

MHA 由 Node 节点Manager 节点组成,二者需配合工作:

组件 部署位置 核心作用
MHA Node 所有 MySQL 服务器(主/从) 1. 执行 binlog 保存、中继日志(relay log)应用等操作;
2. 接收 Manager 节点的指令,完成故障切换相关操作。
MHA Manager 独立服务器/某台从库 1. 定时探测主库状态(默认每秒 ping 一次);
2. 主库宕机时,自动选择最优从库提升为主库;
3. 管理所有从库重新指向新主库;
4. 支持管理多组 MySQL 主从集群。

3. MHA 核心特点

  1. 数据丢失最小化:主库宕机后,MHA 会尝试从宕机主库读取未同步的 binlog,复制到从库后再切换,避免数据丢失。
  2. 半同步复制兼容:若 MySQL 开启半同步复制,MHA 会优先选择已接收最新 binlog 的从库作为新主库,进一步降低数据丢失风险。
  3. 多集群管理:单个 MHA Manager 可管理多组 MySQL 主从集群,降低运维成本。
  4. 灵活的候选主库策略:支持通过配置指定候选主库,或按数据同步进度自动选择最优从库。

4. MHA 工作原理(故障切换流程)

主库宕机后,MHA 按以下步骤完成自动切换:

  1. 保存主库 binlog:MHA Node 尝试从宕机主库读取未同步的 binlog(若主库可访问),保存到本地。
  2. 筛选最优从库:对比所有从库的中继日志(relay log),选择数据最新的从库作为候选主库(可通过配置强制指定候选主库)。
  3. 同步从库数据:将候选主库的差异中继日志应用到其他从库,确保所有从库数据一致。
  4. 应用主库残留 binlog:将步骤1中保存的主库残留 binlog 应用到所有从库,彻底消除数据差异。
  5. 提升新主库:将候选主库提升为新主库,关闭其只读模式(read_only=0)。
  6. 重新指向主库:让所有其他从库停止同步旧主库,改为同步新主库,完成切换。

5. MySQL MHA 搭建实战

5.1 实验思路

  1. 搭建 MySQL 一主两从架构(主库:192.168.100.129,从库1:192.168.100.140,从库2:192.168.100.150),MySQL 安装路径统一为 /usr/local/mysql
  2. 部署 MHA 组件(所有 MySQL 节点装 Node,独立节点装 Manager+Node)。
  3. 配置 MHA 监控与故障切换脚本,测试主从同步与 SSH 无密码认证。
  4. 模拟主库故障,验证自动切换效果;修复故障主库,重新加入集群。

5.2 实验环境

节点角色 操作系统 IP 地址 安装组件 MySQL 版本 MySQL 安装路径
MHA Manager CentOS 7.9 64位 192.168.100.200 MHA Node + MHA Manager - -
MySQL Master CentOS 7.9 64位 192.168.100.129 MySQL 5.7 + MHA Node 5.7 /usr/local/mysql
MySQL Slave1 CentOS 7.9 64位 192.168.100.140 MySQL 5.7 + MHA Node(候选主库) 5.7 /usr/local/mysql
MySQL Slave2 CentOS 7.9 64位 192.168.100.150 MySQL 5.7 + MHA Node 5.7 /usr/local/mysql

注意:MHA 0.57 版本仅支持 MySQL 5.6/5.7,不支持 MySQL 8.0;所有节点需关闭防火墙与 SELinux。

5.3 准备工作(所有节点执行)

  1. 关闭防火墙与 SELinux

    systemctl stop firewalld && systemctl disable firewalld
    setenforce 0 && sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
    
  2. 修改主机名与 hosts 解析(避免主机名连接失败)

    # Master 节点
    hostnamectl set-hostname master 
    # Slave1 节点
    hostnamectl set-hostname slave1 
    # Slave2 节点
    hostnamectl set-hostname slave2 
    # manager 节点
    hostnamectl set-hostname manager
    # 所有 节点
    echo -e "192.168.100.129 master\n192.168.100.140 slave1\n192.168.100.150 slave2\n192.168.100.200 manager" >> /etc/hosts
    

5.4 步骤1:搭建 MySQL 一主两从(基于已安装的 MySQL)

5.4.1 验证 MySQL 配置(所有 MySQL 节点)

先确认当前 MySQL 配置:

# 验证配置文件路径与内容
cat /etc/my.cnf
# 验证 MySQL 服务状态
systemctl status mysqld  # 确保状态为 active (running)
# 验证关键路径权限(避免读写权限问题)
chown -R mysql:mysql /usr/local/mysql/
chmod -R 755 /usr/local/mysql/data/

若您需要修改 MySQL 密码(如忘记密码),可参考:在 /etc/my.cnf 中添加 skip-grant-tables,重启后无密码登录,执行 ALTER USER 'root'@'localhost' IDENTIFIED BY '您的新密码';,再删除 skip-grant-tables 重启。

5.4.2 配置 MySQL 主从复制(路径:/usr/local/mysql
(1)Master 节点配置(/etc/my.cnf,适配 /usr/local/mysql
vim /etc/my.cnf
[client]
port = 3306
socket = /usr/local/mysql/mysql.sock  # 与 MySQL 安装路径一致
#default-character-set=utf8    #注释这一行。

[mysqld]
user = mysql
basedir = /usr/local/mysql  # MySQL 安装根目录
datadir = /usr/local/mysql/data  # 数据目录(需归属 mysql 用户)
port = 3306
character-set-server = utf8
pid-file = /usr/local/mysql/mysqld.pid  # PID 文件路径
socket = /usr/local/mysql/mysql.sock  # 与 client 段保持一致
bind-address = 0.0.0.0  # 允许所有 IP 连接(生产环境建议指定具体 IP)
skip-name-resolve  # 跳过域名解析,加速连接

# 性能与基础配置
max_connections = 2048
default-storage-engine = INNODB
max_allowed_packet = 16M

# 主从复制核心配置(Master 节点必须)
server-id = 1  # 唯一标识(Slave 节点需修改为 2、3 等)
log_bin = master-bin  # binlog 日志路径(基于 datadir)
log-slave-updates = true  # 允许从库同步此 Master 的 binlog(级联复制需开启)

# SQL 模式(增强数据校验,与用户原配置一致)
sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,PIPES_AS_CONCAT,ANSI_QUOTES

[mysql]
port = 3306
default-character-set = utf8
socket = /usr/local/mysql/mysql.sock
auto-rehash

# 重启 MySQL 生效
systemctl restart mysqld
(2)Slave1/Slave2 节点配置(/etc/my.cnf,适配 /usr/local/mysql
  • Slave1(候选主库,需开启 binlog)

    vim /etc/my.cnf
    [client]
    port = 3306
    socket = /usr/local/mysql/mysql.sock
    #default-character-set=utf8
    
    [mysqld]
    user = mysql
    basedir = /usr/local/mysql
    datadir = /usr/local/mysql/data
    port = 3306
    character-set-server = utf8
    pid-file = /usr/local/mysql/mysqld.pid
    socket = /usr/local/mysql/mysql.sock
    bind-address = 0.0.0.0
    skip-name-resolve
    
    max_connections = 2048
    default-storage-engine = INNODB
    max_allowed_packet = 16M
    
    # 从库核心配置(候选主库需开启 binlog)
    server-id = 2  # 唯一标识(≠1/3)
    log_bin = master-bin  # 开启 binlog(提升为主库后可用)
    relay-log = relay-log-bin  # 中继日志路径(基于 datadir)
    relay-log-index = slave-relay-bin.index
    sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,PIPES_AS_CONCAT,ANSI_QUOTES
    
    [mysql]
    port = 3306
    default-character-set = utf8
    socket = /usr/local/mysql/mysql.sock
    auto-rehash
    
    # 重启 MySQL 生效
    systemctl restart mysqld
    
  • Slave2(普通从库,可选开启 binlog)

    vim /etc/my.cnf
    [client]
    port = 3306
    socket = /usr/local/mysql/mysql.sock
    #default-character-set=utf8
    
    [mysqld]
    user = mysql
    basedir = /usr/local/mysql
    datadir = /usr/local/mysql/data
    port = 3306
    character-set-server = utf8
    pid-file = /usr/local/mysql/mysqld.pid
    socket = /usr/local/mysql/mysql.sock
    bind-address = 0.0.0.0
    skip-name-resolve
    
    max_connections = 2048
    default-storage-engine = INNODB
    max_allowed_packet = 16M
    
    # 从库核心配置(普通从库无需开启 binlog)
    server-id = 3  # 唯一标识(≠1/2)
    relay-log = relay-log-bin
    relay-log-index = slave-relay-bin.index
    sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,PIPES_AS_CONCAT,ANSI_QUOTES
    
    [mysql]
    port = 3306
    default-character-set = utf8
    socket = /usr/local/mysql/mysql.sock
    auto-rehash
    
    # 重启 MySQL 生效
    systemctl restart mysqld
    
    在 Master、Slave1、Slave2 节点上都创建两个软链接
    ln -s /usr/local/mysql/bin/mysql /usr/sbin/
    ln -s /usr/local/mysql/bin/mysqlbinlog /usr/sbin/
    
(3)授权主从复制与 MHA 监控用户

Master 节点登录 MySQL,执行授权(三台MySQL都需要做):

mysql -uroot -p123  # 登录 Master 节点的 MySQL(使用您的 root 密码)
# 1. 授权从库同步用户(myslave):允许 192.168.100.0/24 网段的从库同步
grant replication slave on *.* to 'myslave'@'192.168.100.%' identified by '123';
# 2. 授权 MHA 管理用户(mha):拥有所有权限,用于监控和切换
grant all privileges on *.* to 'mha'@'192.168.100.%' identified by 'manager';
# 3. 授权 MHA 通过主机名连接(避免 DNS 解析问题,需与 hosts 解析对应)
grant all privileges on *.* to 'mha'@'master' identified by 'manager';
grant all privileges on *.* to 'mha'@'slave1' identified by 'manager';
grant all privileges on *.* to 'mha'@'slave2' identified by 'manager';

flush privileges;
(4)启动主从同步
  1. 在 Master 节点查看 binlog 信息(记录 File 和 Position,用于从库同步)

    mysql -uroot -p123
    show master status;
    # 示例输出(需替换为实际值,binlog 路径已适配 /usr/local/mysql/data)
    # +-------------------+----------+--------------+------------------+-------------------+
    # | File              | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    # +-------------------+----------+--------------+------------------+-------------------+
    # | master-bin.000001 |      1747 |              |                  |                   |
    # +-------------------+----------+--------------+------------------+-------------------+
    exit
    
  2. 在 Slave1/Slave2 节点执行同步命令(替换 File 和 Position 为 Master 实际值)

    mysql -uroot -p123
    # 停止现有同步(首次配置可跳过)
    stop slave;
    # 配置主库信息(主库 IP、同步用户、binlog 路径)
    change master to 
    master_host='192.168.100.129',  # Master 节点 IP
    master_user='myslave',          # 从库同步用户
    master_password='123',    # 同步用户密码
    master_log_file='master-bin.000001',  # 替换为 Master 的 File(binlog 文件名)
    master_log_pos=1747;                   # 替换为 Master 的 Position(binlog 偏移量)
    
    # 启动同步并验证
    start slave;
    show slave status\G
    # 关键验证:确保以下两项为 Yes(代表同步正常)
    # Slave_IO_Running: Yes
    # Slave_SQL_Running: Yes
    # 两个从库必须设置为只读模式:
    set global read_only=1;
    exit
    
  3. 测试主从同步(在 Master 节点插入数据,从库验证)

    # Master 节点:创建测试数据
    mysql -uroot -p123
    create database ceshi;
    use ceshi;
    create table test(id int);
    insert into test(id) values(1);
    exit
    
    # Slave1/Slave2 节点:验证数据同步(应显示 id=1)
    mysql -uroot -p123
    use ceshi;
    select * from test;
    exit
    

5.5 步骤2:部署 MHA 组件

5.5.1 安装 MHA 依赖(所有节点)

MHA 基于 Perl 开发,需先安装依赖包:

# 安装 EPEL 源(提供 Perl 依赖,CentOS 7 需开启)
yum install -y epel-release --nogpgcheck
# 安装 MHA 必需的 Perl 模块
yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch \
perl-Parallel-ForkManager perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker perl-CPAN
5.5.2 安装 MHA Node 组件(所有节点)

所有 MySQL 节点和 MHA Manager 节点都需先安装 Node 组件(Manager 依赖 Node):

# 下载 MHA Node 包(0.57 版本,适配 CentOS 7,若链接失效可替换为国内源)
cd /opt
wget https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.57/mha4mysql-node-0.57.tar.gz
# 解压并安装(Perl 模块安装,路径默认)
tar zxvf mha4mysql-node-0.57.tar.gz       #建议使用自己准备的本地包。
cd mha4mysql-node-0.57
perl Makefile.PL
make && make install
5.5.3 安装 MHA Manager 组件(仅 MHA Manager 节点)

仅在 192.168.100.200 节点安装 Manager 组件:

cd /opt
# 下载 MHA Manager 包
wget https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.57/mha4mysql-manager-0.57.tar.gz
# 解压并安装
tar zxvf mha4mysql-manager-0.57.tar.gz       #建议安装自己准备的本地包。
cd mha4mysql-manager-0.57
perl Makefile.PL
make && make install
5.5.4 配置 SSH 无密码认证(关键!)

MHA 依赖 SSH 无密码登录在节点间传输 binlog 和执行切换命令,需配置所有节点互信:

  1. MHA Manager 节点 → 所有 MySQL 节点 无密码登录

    # 在 MHA Manager 节点生成 SSH 密钥(一路回车,不设置密码)
    ssh-keygen -t rsa
    # 分发公钥到 Master、Slave1、Slave2(首次需输入目标节点 root 密码)
    ssh-copy-id 192.168.100.129
    ssh-copy-id 192.168.100.140
    ssh-copy-id 192.168.100.150
    
  2. MySQL 节点间 互相同步公钥(主库宕机时,从库需复制主库 binlog)

    # 在 Master 节点执行
    ssh-keygen -t rsa 
    ssh-copy-id 192.168.100.140  
    ssh-copy-id 192.168.100.150
    # 在 Slave1 节点执行
    ssh-keygen -t rsa  
    ssh-copy-id 192.168.100.129  
    ssh-copy-id 192.168.100.150
    # 在 Slave2 节点执行
    ssh-keygen -t rsa  
    ssh-copy-id 192.168.100.129  
    ssh-copy-id 192.168.100.140
    
  3. 验证 SSH 无密码登录(示例:MHA Manager 节点登录 Master)

    ssh root@192.168.100.129  # 无需输入密码即可登录,验证成功后 exit 退出
    

5.6 步骤3:配置 MHA 故障切换(适配 /usr/local/mysql

5.6.1 配置 VIP 管理脚本(仅 MHA Manager 节点)

MHA 通过 master_ip_failover 脚本管理虚拟 IP(VIP),切换时自动将 VIP 从旧主库迁移到新主库,脚本无需修改路径(仅管理网络,与 MySQL 路径无关):

  1. 复制脚本并修改

    # 在 manager 节点上复制相关脚本到/usr/local/bin 目录
    cp -rp /opt/mha4mysql-manager-0.57/samples/scripts /usr/local/bin
    //拷贝后会有四个执行文件。
    ll /usr/local/bin/scripts/
    ----------------------------------------------------------------------------------------------------------
     master_ip_failover  		#自动切换时 VIP 管理的脚本
     master_ip_online_change 	#在线切换时 vip 的管理
     power_manager 				#故障发生后关闭主机的脚本
     send_report 				#因故障切换后发送报警的脚本
     ----------------------------------------------------------------------------------------------------------
    cp /usr/local/bin/scripts/master_ip_failover /usr/local/bin
    # 修改脚本内容(替换 VIP、网卡等参数,与网络环境匹配)
    vim /usr/local/bin/master_ip_failover
    
  2. 脚本完整内容(删除原有内容,直接复制以下代码)

    #!/usr/bin/env perl
    use strict;
    use warnings FATAL => 'all';
    
    use Getopt::Long;
    
    my (
    $command, $ssh_user, $orig_master_host, $orig_master_ip,
    $orig_master_port, $new_master_host, $new_master_ip, $new_master_port
    );
    #############################添加内容部分#########################################
    my $vip = '192.168.100.180';									#指定vip的地址
    my $brdc = '192.168.100.255';								#指定vip的广播地址
    my $ifdev = 'ens33';										#指定vip绑定的网卡
    my $key = '1';												#指定vip绑定的虚拟网卡序列号
    my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip";		#代表此变量值为ifconfig ens33:1 192.168.100.180
    my $ssh_stop_vip = "/sbin/ifconfig ens33:$key down";		#代表此变量值为ifconfig ens33:1 192.168.100.180 down
    my $exit_code = 0;											#指定退出状态码为0
    #my $ssh_start_vip = "/usr/sbin/ip addr add $vip/24 brd $brdc dev $ifdev label $ifdev:$key;/usr/sbin/arping -q -A -c 1 -I $ifdev $vip;iptables -F;";
    #my $ssh_stop_vip = "/usr/sbin/ip addr del $vip/24 dev $ifdev label $ifdev:$key";
    ##################################################################################
    GetOptions(
    'command=s' => \$command,
    'ssh_user=s' => \$ssh_user,
    'orig_master_host=s' => \$orig_master_host,
    'orig_master_ip=s' => \$orig_master_ip,
    'orig_master_port=i' => \$orig_master_port,
    'new_master_host=s' => \$new_master_host,
    'new_master_ip=s' => \$new_master_ip,
    'new_master_port=i' => \$new_master_port,
    );
    
    exit &main();
    
    sub main {
    
    print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";
    
    if ( $command eq "stop" || $command eq "stopssh" ) {
    
    my $exit_code = 1;
    eval {
    print "Disabling the VIP on old master: $orig_master_host \n";
    &stop_vip();
    $exit_code = 0;
    };
    if ($@) {
    warn "Got Error: $@\n";
    exit $exit_code;
    }
    exit $exit_code;
    }
    elsif ( $command eq "start" ) {
    
    my $exit_code = 10;
    eval {
    print "Enabling the VIP - $vip on the new master - $new_master_host \n";
    &start_vip();
    $exit_code = 0;
    };
    if ($@) {
    warn $@;
    exit $exit_code;
    }
    exit $exit_code;
    }
    elsif ( $command eq "status" ) {
    print "Checking the Status of the script.. OK \n";
    exit 0;
    }
    else {
    &usage();
    exit 1;
    }
    }
    sub start_vip() {
    `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
    }
    ## A simple system call that disable the VIP on the old_master
    sub stop_vip() {
    `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
    }
    
    sub usage {
    print
    "Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
    }
    
    
  3. 添加脚本执行权限并修复编码(待定)

    # 添加执行权限
    chmod +x /usr/local/bin/master_ip_failover
    # 解决中英文编码问题(避免脚本执行时报语法错误)
    yum install -y dos2unix
    dos2unix /usr/local/bin/master_ip_failover
    
5.6.2 配置 MHA 集群文件(仅 MHA Manager 节点,适配 /usr/local/mysql

创建 MHA 软件目录并拷贝配置文件,这里使用app1.cnf配置文件来管理 mysql 节点服务器:

  1. 创建配置目录与文件

    mkdir -p /etc/masterha   # 配置目录
    cp /opt/mha4mysql-manager-0.57/samples/conf/app1.cnf /etc/masterha/
    vim /etc/masterha/app1.cnf  # 修改配置
    
  2. 配置文件完整内容(删除原有内容,替换为以下配置)

    [server default]
    manager_log=/var/log/masterha/app1/manager.log
    manager_workdir=/var/log/masterha/app1
    master_binlog_dir=/usr/local/mysql/data
    master_ip_failover_script=/usr/local/bin/master_ip_failover
    master_ip_online_change_script=/usr/local/bin/master_ip_online_change
    password=manager
    ping_interval=1
    remote_workdir=/tmp
    repl_password=123
    repl_user=myslave
    secondary_check_script=/usr/local/bin/masterha_secondary_check -s 192.168.100.140 -s 192.168.100.150
    shutdown_script=""
    ssh_user=root
    user=mha
    
    [server1]
    hostname=192.168.100.129
    port=3306
    
    [server2]
    candidate_master=1
    check_repl_delay=0
    hostname=192.168.100.140
    port=3306
    
    [server3]
    hostname=192.168.100.150
    port=3306
    
    

5.7 步骤4:测试与启动 MHA

5.7.1 手动配置初始 VIP(Master 节点)

首次启动 MHA 前,需在 Master 节点手动绑定 VIP(后续切换由 MHA 自动管理):

# 绑定 VIP(与脚本中配置的参数一致:ens33:1、192.168.100.180)
/sbin/ifconfig ens33:1 192.168.100.180/24
# 验证 VIP(应显示 ens33:1 网卡,IP 为 192.168.100.180)
ifconfig      # ip a
5.7.2 测试 SSH 连接(MHA Manager 节点)

验证 MHA 能否通过 SSH 无密码访问所有节点,输出 All SSH connection tests passed successfully 为正常:

masterha_check_ssh -conf=/etc/masterha/app1.cnf
5.7.3 测试主从复制(MHA Manager 节点)

验证 MySQL 主从复制健康状态,输出 MySQL Replication Health is OK 为正常(若报错,优先检查主从同步与 MHA 用户授权):

masterha_check_repl -conf=/etc/masterha/app1.cnf
5.7.4 启动 MHA Manager(MHA Manager 节点)

使用后台进程启动 MHA,避免终端关闭后进程退出:

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 &

#生产中java 服务启动的方式,此条代码无需输入,仅作为课外拓展。
nohup  java -jar  微服务名称-( war jar)   &   

----------------------------------------------------------------------------------------------------------
--remove_dead_master_conf:该参数代表当发生主从切换后,老的主库的 ip 将会从配置文件中移除。
--manger_log:日志存放位置。
--ignore_last_failover:在缺省情况下,如果 MHA 检测到连续发生宕机,且两次宕机间隔不足 8 小时的话,则不会进行 Failover, 之所以这样限制是为了避免 ping-pong 效应。该参数代表忽略上次 MHA 触发切换产生的文件,默认情况下,MHA 发生切换后会在日志记录,也就是上面设置的日志app1.failover.complete文件,下次再次切换的时候如果发现该目录下存在该文件将不允许触发切换,除非在第一次切换后收到删除该文件,为了方便,这里设置为--ignore_last_failover。
----------------------------------------------------------------------------------------------------------
5.7.5 验证 MHA 状态(MHA Manager 节点)
  1. 查看 MHA 运行状态(输出 app1 (pid: xxxx) is running(MASTER is 192.168.100.129) 为正常)

    masterha_check_status --conf=/etc/masterha/app1.cnf
    
  2. 查看 MHA 日志(确认当前主库为 Master 节点,binlog 路径正确)

    grep "current master" /var/log/masterha/app1/manager.log
    # 示例输出:[info] Current master is 192.168.100.129(192.168.100.129:3306)
    grep "master_binlog_dir" /var/log/masterha/app1/manager.log
    # 示例输出:[info] master_binlog_dir set to /usr/local/mysql/data (server1)
    
5.7.6 若要关闭 manager 服务
//若要关闭 manager 服务,可以使用如下命令。

masterha_stop --conf=/etc/masterha/app1.cnf

或者可以直接采用 kill 进程 ID 的方式关闭。
5.7.7 查看master VIP
#查看master 的 VIP 地址 192.168.100.180 是否存在,这个 VIP 地址不会因为 manager 节点停止 MHA 服务而消失。
ip a

6. 故障模拟与恢复

6.1 模拟主库故障(Master 节点)

在 Master 节点停止 MySQL 服务,模拟主库宕机(生产环境可能因硬件故障、网络中断触发):

# 停止 MySQL 服务(模拟正常宕机)
systemctl stop mysqld
# 或强制杀死 MySQL 进程(模拟异常宕机)
pkill -9 mysql

6.2 观察故障切换(MHA Manager 节点)

实时查看 MHA 日志,观察切换过程(关键日志已标注):

tail -f /var/log/masterha/app1/manager.log

切换成功的关键日志:

  1. 检测到主库宕机:[warning] Master is down (slave is not responding)
  2. 选择新主库:[info] Selected new master is 192.168.100.140 (candidate master)
  3. 迁移 VIP:Enabling VIP 192.168.100.180 on new master: 192.168.100.140
  4. 同步从库数据:[info] Applying differential relay logs to 192.168.100.150
  5. 切换完成:[info] Failover completed successfully. New master is 192.168.100.140

6.3 验证切换结果

  1. 验证 VIP 迁移(Slave1 节点,原候选主库):VIP 已从 Master 迁移到 Slave1

    ip a  # 应显示 ens33:1 网卡,IP 为 192.168.100.180
    
  2. 验证新主库状态(Slave1 节点):Slave1 已关闭只读模式,成为新主库

    mysql -uroot -p123
    show variables like 'read_only';  # 输出 OFF(主库可读可写)
    exit
    
  3. 验证从库同步(Slave2 节点):Slave2 已同步新主库(Slave1)

    mysql -uroot -p123
    show slave status\G
    # 关键验证:
    # Master_Host: 192.168.100.140(新主库 IP,原 Slave1)
    # Slave_IO_Running: Yes
    # Slave_SQL_Running: Yes
    exit
    

6.4 故障主库恢复(原 Master 节点,路径:/usr/local/mysql

修复原主库(如重启服务、修复硬件)后,需将其重新加入集群作为从库:

  1. 重启 MySQL 服务(原 Master 节点)

    systemctl restart mysqld
    # 验证 MySQL 状态(确保启动成功)
    systemctl status mysqld
    
  2. 查看新主库(Slave1)的 binlog 信息(Slave1 节点,用于原主库同步)

    mysql -uroot -p123
    show master status;
    # 示例输出(记录 File 和 Position,原主库需同步此 binlog)
    # +-------------------+----------+--------------+------------------+-------------------+
    # | File              | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    # +-------------------+----------+--------------+------------------+-------------------+
    # | master-bin.000001 |      154 |              |                  |                   |
    # +-------------------+----------+--------------+------------------+-------------------+
    exit
    
  3. 原 Master 节点同步新主库(Slave1)(原 Master 节点,从库身份)
    修改原主库(master)的 my.cnf,添加中继日志参数

    vim /etc/my.cnf
    [mysqld]
    # 保留原有的基础配置(user、basedir、datadir、socket 等)
    server-id = 1                  # 注意:server-id 保持不变(必须唯一,不能与新主库/其他从库重复)
    log_bin = master-bin  # 可选:若后续可能再次作为候选主库,保留 log_bin;若仅作为普通从库,可注释(但建议保留,灵活)
    # 新增中继日志配置(核心)
    relay-log = relay-log-bin  # 中继日志文件名,路径与 datadir 一致
    relay-log-index = slave-relay-bin.index  # 中继日志索引文件(记录所有中继日志列表)
    read_only = 1                  # 从库默认只读(避免误写数据,提升为主库时会自动关闭)
    
    # 重启前确保原主库无业务写入(已转为从库,只读配置会限制写入)
    systemctl restart mysqld
    mysql -uroot -p123
    # 停止旧同步(原主库无 slave 进程,可跳过)
    stop slave;
    # 配置同步新主库(Slave1),binlog 路径适配 /usr/local/mysql/data
    change master to 
       master_host='192.168.100.140',  # 新主库 IP(原 Slave1)
       master_user='myslave',          # 从库同步用户
       master_password='123',    # 同步用户密码
       master_log_file='master-bin.000001',  # 替换为 Slave1 的 File
       master_log_pos=154;                   # 替换为 Slave1 的 Position
    
    # 启动同步并验证
    start slave;
    show slave status\G
    # 验证:Slave_IO_Running=Yes、Slave_SQL_Running=Yes(同步正常)
    exit
    
  4. 更新 MHA 配置文件(MHA Manager 节点):重新加入原主库

    vim /etc/masterha/app1.cnf
    # 添加原主库配置(注意 server 编号唯一)
    [server1]
    hostname=192.168.100.129  # 原 Master 节点 IP
    port=3306
    
    #修改
    vim /etc/my.cnf
    在[mysqld]区域加入
    relay-log = relay-log-bin
    relay-log-index = slave-relay-bin.index
    read_only = 1
    
    删除原slave1
    read_only = 1
    
    
    
  5. 重启 MHA Manager(MHA Manager 节点)

    # 停止现有 MHA 进程
    masterha_stop --conf=/etc/masterha/app1.cnf
    # 重新启动 MHA(参数与首次启动一致)
    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 &
    
    # 验证 MHA 状态(应包含 4 个节点,当前主库为 192.168.100.140)
    masterha_check_status --conf=/etc/masterha/app1.cnf
    #验证四台机器的连接情况。
    masterha_check_repl -conf=/etc/masterha/app1.cnf
    

7. MHA 常用工具说明

工具名称 组件归属 核心作用
masterha_check_ssh Manager 检查 MHA 集群所有节点的 SSH 无密码认证状态
masterha_check_repl Manager 检查 MySQL 主从复制健康状态(含 binlog 路径、同步用户授权等)
masterha_manager Manager 启动 MHA Manager 进程(核心工具,负责监控与切换)
masterha_check_status Manager 查看 MHA 运行状态及当前主库 IP
masterha_master_switch Manager 手动触发主库切换(用于在线升级主库,非故障场景)
masterha_stop Manager 停止 MHA Manager 进程(需指定配置文件)
save_binary_logs Node 保存宕机主库的残留 binlog(MHA 自动调用,无需手动执行)
apply_diff_relay_logs Node 应用差异中继日志到从库,确保所有从库数据一致(MHA 自动调用)
purge_relay_logs Node 安全清除从库的中继日志(不阻塞 SQL 线程,避免磁盘空间占用)

8. 注意事项(适配 /usr/local/mysql 路径)

  1. 路径一致性:所有涉及 MySQL 路径的配置(my.cnfapp1.cnf、软链接)必须统一为 /usr/local/mysql,避免因路径不匹配导致 MHA 无法读取 binlog 或执行命令。
  2. 目录权限:确保 /usr/local/mysql 及子目录(尤其是 data)的所有者为 mysql 用户,否则 MySQL 无法写入 binlog 或中继日志,主从同步会失败。
    # 定期检查权限(若异常,执行以下命令修复)
    chown -R mysql:mysql /usr/local/mysql/
    
  3. 版本兼容性:MHA 0.57 仅支持 MySQL 5.6/5.7,若使用 MySQL 8.0,需升级 MHA 到 0.58+ 版本(需手动编译,不推荐新手使用)。
  4. 日志监控:定期查看 MHA 日志(/var/log/masterha/app1/manager.log)和 MySQL 错误日志(/usr/local/mysql/data/主机名.err),及时发现路径错误、权限问题等。
  5. VIP 可靠性:若使用云服务器(如阿里云、腾讯云),需先在控制台配置“虚拟 IP”或“弹性公网 IP”,确保 VIP 支持跨节点迁移(部分云厂商需额外配置路由)。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐