MySQL运维实战:备份恢复+主从复制+读写分离+MHA高可用(超详细手把手教程)

MySQL运维实战:备份恢复+主从复制+读写分离+MHA高可用(超详细手把手教程)

摘要:MySQL数据库高可用、数据备份、读写分离是后端运维核心技能,也是面试高频考点!本文从零手把手实操,涵盖MySQL数据备份与恢复、主从复制原理与搭建、Amoeba读写分离、MHA高可用集群,附带完整可运行代码、避坑要点,最后补充MHA原主库复用为备用节点的配置方案,零基础也能轻松落地!

环境说明:CentOS 7 + MySQL 5.7(源码安装)


一、MySQL数据备份与恢复(生产必备)

1.1 数据备份的重要性

生产环境中数据是核心资产,任何数据丢失都会造成严重业务损失,常见数据丢失原因:

  • 程序代码bug、运算错误

  • 人为误操作(删库、删表)

  • 磁盘硬件故障、服务器宕机

  • 自然灾害(火灾、地震)、服务器盗窃

1.2 数据库备份分类

1.2.1 物理备份

直接备份数据库物理文件(数据文件、日志文件),速度快、恢复简单,适合大数据量场景。分为三种:

  • 冷备份(脱机备份):关闭数据库后备份,数据一致性最高

  • 热备份(联机备份):数据库运行中备份,依赖binlog日志,不影响业务

  • 温备份:锁定数据表(可读不可写)状态下备份

1.2.2 逻辑备份

备份数据库逻辑对象(表、数据、库结构),生成SQL脚本,灵活性高,适合小数据量、跨环境迁移,核心工具:mysqldump。

1.2.3 常见备份方法

  • 物理冷备
    • 备份时数据库处于关闭状态,直接打包数据库文件
    • 备份速度快,恢复时也是最简单的
  • 专用备份工具mydump或mysqlhotcopy
    • mysqldump常用的逻辑备份工具
    • mysqlhotcopy仅拥有备份MylSAM和ARCHIVE表
  • 启用二进制日志进行增量备份
    • 进行增量备份,需要刷新二进制日志
  • 第三方工具备份
    • 免费的MySQL热备份软件Percona XtraBackup

1.3 常用备份方式实操

1.3.1 物理冷备份(生产推荐)

核心思路:停止数据库服务 → 打包物理数据文件 → 重启服务

bash 复制代码
# 【mysql01】MySQL物理冷备份完整流程

# 停止MySQL服务,保证数据文件一致性(冷备份核心要求)
[root@mysql01 ~]# systemctl stop mysqld

# 进入MySQL数据根目录
[root@mysql01 ~]# cd /usr/local/mysql/data

# 创建专属备份存储目录
[root@mysql01 data]# mkdir /mysql_bak

# 打包全部数据文件,携带时间戳,避免备份文件覆盖
[root@mysql01 data]# tar czf /mysql_bak/mysql-backup-$(date +%F).tar.gz *

# 重启MySQL服务,恢复业务运行
[root@mysql01 data]# systemctl start mysqld

数据恢复测试:

bash 复制代码
# 【mysql01】物理冷备份数据恢复实操(模拟故障恢复)
# 停止MySQL服务,防止数据文件被进程占用
[root@mysql01 ~]# systemctl stop mysqld

# 清空数据目录,模拟数据损坏/丢失场景(生产环境禁止随意执行)
[root@mysql01 ~]# rm -rf /usr/local/mysql/data/*

# 启动服务,验证数据库故障失效
[root@mysql01 ~]# systemctl start mysqld

# 再次停止服务,准备执行数据恢复
[root@mysql01 ~]# systemctl stop mysqld

# 解压对应时间戳备份包,还原全部数据文件
[root@mysql01 ~]# tar xzf /mysql_bak/mysql-backup-2025-10-15.tar.gz -C /usr/local/mysql/data/

# 修正数据目录权限,避免MySQL启动权限报错
[root@mysql01 ~]# chown -R mysql:mysql /usr/local/mysql/data

# 重启MySQL服务,完成数据恢复
[root@mysql01 ~]# systemctl start mysqld

1.3.2 逻辑备份(mysqldump)

支持单表、单库、多库、全库备份,是日常运维最常用的备份方式。

bash 复制代码
# 【mysql01】mysqldump逻辑备份常用命令合集(日常运维主流)

# 备份单个数据库(仅数据,不含建库语句,恢复数据需进入对应的库恢复数据)
[root@mysql01 ~]# mysqldump -u root -phuawei school > /mysql_bak/school.sql

# 备份多个数据库(包含建库语句,可直接恢复)
[root@mysql01 ~]# mysqldump -u root -phuawei --databases school mysql > /mysql_bak/school-mysql.sql

# 备份全库数据,适配整机数据迁移场景
[root@mysql01 ~]# mysqldump -u root -phuawei --opt --all-databases > /mysql_bak/all.sql

# 精准备份单表结构与数据,适配局部数据恢复
[root@mysql01 ~]# mysqldump -u root -phuawei school info > /mysql_bak/info.sql

--opt 包含 --lock-tables,对 InnoDB 会锁表,默认启用,可省略。

InnoDB 引擎生产环境,建议加上 --single-transaction,用快照代替锁表,不影响业务读写:

bash 复制代码
mysqldump -uroot -phuawei --opt --single-transaction --all-databases > /mysql_bak/all.sql
参数 作用
--add-drop-table 建表前自动加 DROP TABLE IF EXISTS,恢复时先删旧表,避免表已存在报错(你之前 school.sql 里就看到了)
--add-locks 导入数据前后加 LOCK / UNLOCK TABLES,加速写入
--create-options CREATE TABLE 带上引擎、自增等完整表属性
--disable-keys 导入数据前关闭索引,插完数据再重建索引,大幅加快导入速度
--extended-insert 多行合并成一条 INSERT,减少 SQL 语句数量,备份文件更小、恢复更快(不是一行一条 insert)
--lock-tables 备份时锁表,保证 MyISAM 数据一致性;InnoDB 不推荐,会锁库
--quick 边读数据边输出,不在内存缓存整张表,适合大表,防止内存溢出
--set-charset 备份文件开头写入字符集设置语句

逻辑数据恢复实操:

bash 复制代码
# 【mysql01】逻辑备份SQL脚本数据恢复实操
[root@mysql01 ~]# mysql -u root -phuawei

# 切换至目标业务数据库
mysql> use school;

# 模拟生产误操作:删除业务数据表
mysql> drop table info;

# 导入备份SQL脚本,恢复表结构与全部数据
mysql> source /mysql_bak/info.sql;

# 查看数据表,校验数据恢复结果
mysql> show tables;

1.3.3 增量备份(binlog日志)

全量备份耗时久,增量备份仅备份新增/修改数据,依托MySQL二进制日志(binlog)实现,生产主流组合:定期全量备份+实时增量备份。

步骤1:开启binlog日志

bash 复制代码
# 【mysql01】开启binlog二进制日志(增量备份核心依赖)
[root@mysql01 ~]# vim /etc/my.cnf

# 在[mysqld]模块配置binlog,记录所有增删改操作
log-bin=mysql-bin

# 重启MySQL服务,使日志配置生效
[root@mysql01 ~]# systemctl restart mysqld.service

步骤2:全量备份+日志刷新

bash 复制代码
# 执行全量备份,搭建增量恢复数据基线
[root@mysql01 ~]# mysqldump -u root -phuawei --all-databases > /opt/mysql-all.sql

# 刷新切割binlog日志,旧日志归档,新日志记录后续增量操作
[root@mysql01 ~]# mysqladmin -uroot -phuawei flush-logs

步骤3:模拟增量数据写入

bash 复制代码
# 【mysql01】模拟增量业务数据写入
[root@mysql01 ~]# mysql -uroot -phuawei

# 新增数据写入
mysql> use school; 
mysql> insert into info (name,score,address,hobby) values ('美猴王',75,'武汉',1);
mysql> insert into info (name,score,address,hobby) values ('超人',83,'上海',2);
mysql> exit

# 再次切割日志,固化增量操作日志,便于精准恢复
[root@mysql01 ~]# mysqladmin -uroot -p flush-logs

步骤4:模拟数据删除+增量恢复

bash 复制代码
# 模拟生产误删增量数据,制造数据故障
[root@mysql01 ~]# mysql -uroot -phuawei
mysql> use school;
mysql> delete from info where id=5; # 删除新增测试数据1
mysql> delete from info where id=6; # 删除新增测试数据2
mysql> exit

# 格式化解析binlog日志,定位误操作SQL语句
[root@mysql01 ~]# mysqlbinlog --no-defaults --base64-output=decode-rows -v /usr/local/mysql/data/mysql-bin.000002

# 回放binlog日志,执行增量数据恢复
[root@mysql01 ~]# mysqlbinlog --no-defaults /usr/local/mysql/data/mysql-bin.000002 | mysql -uroot -phuawei

# 进入数据库,校验数据恢复效果
[root@mysql01 ~]# mysql -uroot -phuawei
mysql> use school;
mysql> select * from info;

二、MySQL主从复制与读写分离(性能优化核心)

2.1 主从复制核心原理

2.1.1 三大核心组件

  • binlog二进制日志(主库):记录主库所有增删改操作

  • IO线程(从库):连接主库,拉取binlog日志到本地中继日志

  • SQL线程(从库):读取中继日志,重放SQL语句同步数据

2.1.2 完整复制流程

  1. 主库执行INSERT/UPDATE/DELETE等写操作
  2. 主库将操作记录到binlog二进制日志
  3. 从库IO线程请求主库binlog日志
  4. 主库dump线程推送binlog日志至从库
  5. 从库IO线程将日志写入本地relay中继日志
  6. 从库SQL线程重放中继日志,同步数据
  7. 正常状态:Slave_IO_Running=Yes、Slave_SQL_Running=Yes
  8. 从库数据和主库完全一致

使用目标:数据冗余和灾难恢复;提升并发能力、避免锁冲突。

2.1.3 MySQL读写分离原理

  • 只在主服务器上写,只在从服务器上读
  • 主数据库处理事务性查询,从数据库处理SELECT查询
  • 数据库复制用于将事务性查询的变更同步到集群中的从数据库
  • 读写分离方案
    • 基于程序代码内部实现
    • 基于中间代理层实现
      • MySQL-Proxy
      • Amoeba
      • mycat

环境拓扑

主机名 IP地址 角色作用
mysql-master 192.168.108.101 MySQL主库(写操作)
mysql-slave01 192.168.108.102 MySQL从库1(读操作)
mysql-slave02 192.168.108.103 MySQL从库2(读操作)
amoeba 192.168.108.110 读写分离中间件
mysql-client 192.168.108.111 测试客户端

2.3 环境初始化(所有节点执行)

bash 复制代码
# 集群所有节点统一环境初始化配置
# 同步公共时间服务器,保证集群时间一致
[root@all ~]# ntpdate ntp.aliyun.com 

# 校验时间同步结果
[root@all ~]# date -R 

# 关闭防火墙,以免影响实验
[root@all ~]# systemctl disable firewalld --now 
[root@all ~]# setenforce 0 

# 清理MySQL残留进程,解决连接占用、启动异常问题
[root@all ~]# pkill -9 mysql;systemctl restart mysqld

2.4 主从复制搭建实操

2.4.1 主库配置(mysql-master)

bash 复制代码
# 【mysql-master】主库主从复制核心配置
[root@mysql-master ~]# vim /etc/my.cnf
[mysqld]
server-id = 11             # 集群唯一节点ID,主从节点不可重复
log-bin = master-bin       # 开启二进制日志,主从复制核心依赖
log-slave-updates = true   # 允许从库同步日志,适配多级复制与MHA架构

# 重启服务,加载新配置
[root@mysql-master ~]# systemctl restart mysqld

# 创建从库同步专用账号,授权网段访问权限
[root@mysql-master ~]# mysql -u root -phuawei
mysql> GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.108.%' IDENTIFIED BY '123456';
mysql> FLUSH PRIVILEGES;
mysql> show master status;

2.4.2 从库配置(mysql-slave01/02)

两台从库操作一致,仅server-id不同

bash 复制代码
# 【mysql-slave01】从库初始化与主从复制配置
[root@mysql-slave01 ~]# systemctl stop mysqld # 停止服务,规避文件占用报错
[root@mysql-slave01 ~]# rm -f /usr/local/mysql/data/auto.cnf # 清除克隆机器重复UUID,解决同步报错
[root@mysql-slave01 ~]# systemctl start mysqld # 重启生成唯一UUID

# 修改从库配置文件
[root@mysql-slave01 ~]# vim /etc/my.cnf
[mysqld]
server-id = 22       
relay-log = relay-log-bin                 # 开启中继日志,缓存主库同步日志


# 重启服务加载配置
[root@mysql-slave01 ~]# systemctl restart mysqld

# 关联主库信息,建立主从复制链路
[root@mysql-slave01 ~]# mysql -u root -p
mysql> change master to master_host='192.168.108.101',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=604;
mysql> start slave;
mysql> show slave status\G;

2.4.3 主从同步验证

bash 复制代码
# 【mysql-master】创建测试库表并写入测试数据
mysql> create database school;
mysql> use school;
mysql> CREATE TABLE student (id int UNSIGNED AUTO_INCREMENT PRIMARY KEY,name VARCHAR(20) NOT NULL,age tinyint UNSIGNED,gender ENUM('M','F') default 'M')ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;
mysql> insert student (name,age)values('路飞',20);

# 【mysql-slave01/02】查询数据,验证主从同步生效
mysql> select * from school.student;

2.5 基于Amoeba的读写分离搭建

2.5.1 读写分离原理

  • 写操作(INSERT/UPDATE/DELETE):路由至主库,保证数据一致性
  • 读操作(SELECT):轮询路由至从库集群,分担查询压力
  • Amoeba:Java开发的轻量SQL代理中间件,零代码侵入、配置简单
bash 复制代码
应用程序
    ↓
读写中间件(或代码判断)
    ↓
------------------------------------------------------
写 → Master(主库)
读 → Slave 1
     Slave 2
     Slave 3
------------------------------------------------------
  1. 从库可以有 1 台、2 台、多台,共同分担查询压力

    主从复制保证数据一致

    读写分离保证性能扩容

Amoeba 是一款基于 Java 开发的 MySQL 数据库代理中间件 ,核心定位是SQL 路由 ,帮你在应用与 MySQL 之间实现读写分离、负载均衡、高可用,对应用透明、配置简单,是早期企业实现 MySQL 读写分离的主流方案。

  • 角色:应用 ↔ Amoeba ↔ MySQL 主从集群,Amoeba 是中间 "SQL 路由器"。
  • 核心能力 :自动识别 SQL 类型,写(INSERT/UPDATE/DELETE)走主库,读(SELECT)走从库,并对从库做负载均衡。
  • 依赖前提 :必须先搭好 MySQL 主从复制,Amoeba 只负责路由,不负责数据同步。
  • 优势 :零代码侵入、配置基于 XML(比 MySQL Proxy 的 Lua 简单)、轻量易运维。

工作流程(读写分离)

  1. 应用连接 Amoeba 代理(默认端口 8066),而非直接连 MySQL。

  2. Amoeba 解析 SQL:

    • 写操作 → 转发到配置的 主库池(writePool)。
    • 读操作 → 转发到配置的 从库池(readPool),并按轮询 / 权重做负载均衡。
  3. 主从复制保证从库数据与主库一致,应用无感知。

核心组件(配置文件)

Amoeba 核心配置在 $AMOEBA_HOME/conf/ 下,共 7 个,最关键 2 个:

配置文件 作用
amoeba.xml 代理核心配置:端口、认证、读写池、路由规则、线程池
dbServers.xml 定义后端 MySQL 节点(主 / 从)、连接信息、连接池

路由规则(读写分离核心)

在 amoeba.xml 中配置:

  • writePool:指定写操作转发的主库节点池。
  • readPool:指定读操作转发的从库节点池(多从库自动轮询)。
  • 规则优先级:readPools/writePools > defaultPools。

2.5.2 Amoeba环境部署

bash 复制代码
# 【amoeba】读写分离中间件环境部署初始化
[root@amoeba ~]# hostnamectl set-hostname amoeba
[root@amoeba ~]# systemctl stop firewalld.service
[root@amoeba ~]# setenforce 0

# 赋予JDK安装包执行权限并完成安装
[root@amoeba ~]# chmod +x jdk-6u14-linux-x64.bin
[root@amoeba ~]# ./jdk-6u14-linux-x64.bin

# 迁移JDK至固定目录,统一环境路径
[root@amoeba ~]# mv jdk1.6.0_14/ /usr/local/jdk1.6

# 配置系统全局环境变量
[root@amoeba ~]# vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$AMOEBA_HOME/bin

[root@amoeba ~]# source /etc/profile # 加载环境变量,即刻生效

# 创建Amoeba安装目录并解压部署包
[root@amoeba ~]# mkdir /usr/local/amoeba
[root@amoeba ~]# tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
[root@amoeba ~]# chmod -R 755 /usr/local/amoeba/ 
[root@amoeba ~]# /usr/local/amoeba/bin/amoeba

2.5.3 数据库授权Amoeba访问

bash 复制代码
# 【所有MySQL节点】授权Amoeba中间件远程访问权限
mysql> grant all on *.* to test@'192.168.108.%' identified by '123.com';
mysql> flush privileges;

2.5.4 Amoeba核心配置

  1. 配置代理账号密码与读写池
bash 复制代码
# 【amoeba】配置客户端连接信息与读写路由规则
[root@amoeba ~]# vim /usr/local/amoeba/conf/amoeba.xml

# 30行:配置客户端连接Amoeba的账号
<property name="user">amoeba</property>

# 32行:配置客户端连接Amoeba的密码
<property name="password">123456</property>

---117和120-去掉注释-
 115行 <property name="defaultPool">master</property> # 默认数据库池,一般写master,保证未知 SQL 在主库执行,防止数据写从库
 116
 117
 118行<property name="writePool">master</property>    # 指定写请求路由池(仅主库,保证数据一致性)
 119行<property name="readPool">slaves</property>     # 指定读请求路由池(从库集群,实现负载均衡)
 120
  1. 配置后端MySQL节点
bash 复制代码
# 【amoeba】配置后端MySQL集群节点信息
[root@amoeba ~]# vim /usr/local/amoeba/conf/dbServers.xml

---23--注意!!!(mysql5.7,默认没有test数据库所以需要修改为mysql数据库)-(mysql5.5直接忽略)--
<!-- mysql schema -->
<property name="schema">mysql</property>

--25行到30行,第30行-->移动到28行后面
 25                         <!-- mysql user -->
 26                         <property name="user">test</property>         # 对接MySQL的授权账号 
 27
 28                         <!--  mysql password -->
 29                         <property name="password">123.com</property>  # 对接MySQL的授权密码
 30

# 定义主库节点,承担全部写请求
45行<dbServer name="master"  parent="abstractServer">          # 修改为amoeba.xml定义的主库写请求路由池的名字
48行<property name="ipAddress">192.168.108.101</property>      # 主库IP地址

# 定义从库节点1,承担读请求负载
--52到57行从库配置
52行<dbServer name="slave1"  parent="abstractServer">
--55-从服务器地址-
55 <property name="ipAddress">192.168.108.102</property>      

# 定义从库节点2,承担读请求负载
 ---52到57行复制一份在58行后面
原52行<dbServer name="slave2"  parent="abstractServer">
--55-从服务器地址-
原55 <property name="ipAddress">192.168.108.103</property>         

# 配置从库负载均衡池,实现读请求轮询分发
<dbServer name="slaves" virtual="true">                            # 修改为amoeba.xml定义的从库读请求路由池的名字
<poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
<property name="poolNames">slave1,slave2</property>                # 修改为节点1和节点2的独立从池库的名字
</poolConfig>
</dbServer>

vim conf/dbServers.xml 结果如下

2.5.5 启动服务与读写分离验证

bash 复制代码
# 后台启动Amoeba读写分离代理服务
[root@amoeba ~]# /usr/local/amoeba/bin/amoeba start&

# 查看Java端口监听,验证服务启动成功(默认8066端口)
[root@amoeba ~]# netstat -anpt | grep java

# 【mysql-client】客户端连接测试
[root@mysql-client ~]# yum install -y mysql

# 通过Amoeba代理连接数据库,所有请求由代理自动分发
[root@mysql-client ~]# mysql -u amoeba -p123456 -h 192.168.108.110 -P8066

# 客户端创建数据库,3个库由于主从同步,都会有数据
mysql> insert into info (name,score,address,hobby) values ('卡卡西',90,'上海',1);

# 关闭从库同步功能
# mysql-slave01
mysql> stop slave;

# mysql-slave02
mysql> stop slave;

# 客户端再写入新的数据,数据不会同步,数据只会出现在主库,从库没有
#mysql-client
mysql> insert into info (name,score,address,hobby) values ('鸣人',80,'上海',2);

# mysql-slave01 手动写入数据,score不一致
mysql> insert into info (name,score,address,hobby) values ('鸣人',81,'上海',2);

# mysql-slave02 手动写入数据,score不一致
mysql> insert into info (name,score,address,hobby) values ('鸣人',83,'上海',2);

# 客户端测试,第一次会向从服务器1读取,第二次会向从2读取
#mysql-client
MySQL [(none)]> select * from school.info;

# 验证了在客户端写的数据是写字在主库,读是在从库读取。

三、MySQL MHA高可用集群(解决主库单点故障)

3.1 MHA核心介绍

MHA(Master High Availability)是MySQL专属开源高可用工具,解决主库单点故障,可在0-30秒完成自动故障切换,最大程度保证数据不丢失,是中小企业MySQL高可用主流方案。

核心组件:

  • MHA Manager:管理节点,监控集群状态、触发故障切换

  • MHA Node:所有MySQL数据节点,负责日志同步、故障修复

3.2 MHA实验环境

主机名 IP地址 角色
mysql-master 192.168.108.131 主库、安装node组件
mysql-slave01 192.168.108.132 从库1、备选主库、安装node组件
mysql-slave02 192.168.108.133 从库2、安装node组件
mha 192.168.108.130 管理节点、安装manager+node组件

3.3 环境初始化与主从配置

  1. 修复克隆主机UUID重复问题
bash 复制代码
# 【slave01、slave02】修复克隆机器UUID重复问题(MHA集群必备)
# 停止服务,释放数据文件占用
[root@mysql-slave01 ~]# systemctl stop mysqld 

# 删除重复UUID配置
[root@mysql-slave01 ~]# rm -f /usr/local/mysql/data/auto.cnf 

# 重启自动生成唯一UUID
[root@mysql-slave01 ~]# systemctl start mysqld

[root@mysql-slave02 ~]# systemctl stop mysqld
[root@mysql-slave02 ~]# rm -f /usr/local/mysql/data/auto.cnf
[root@mysql-slave02 ~]# systemctl start mysqld
  1. 安装依赖、配置软链接
bash 复制代码
# 集群所有MySQL节点安装MHA依赖组件
[root@all ~]# yum -y install perl-Module-Install

# 创建MySQL命令软链接,解决MHA工具识别命令失败问题
[root@all ~]# ln -s /usr/local/mysql/bin/mysqlbinlog /usr/bin/
[root@all ~]# ln -s /usr/local/mysql/bin/mysql /usr/bin/

# 重启服务,加载环境变量配置
[root@all ~]# systemctl restart mysqld
  1. 数据库配置文件修改(5.7专属避坑)

所有从库注释 /etc/my.cnf 中 [client] 下的 default-character-set=utf8

bash 复制代码
[root@mysql-master ~]# vim /etc/my.cnf
[mysqld]
server-id = 1                                   #三台服务器的 server-id 不能一样
log_bin = master-bin
log-slave-updates = true

[root@mysql-master ~]# systemctl restart mysqld

[root@mysql-slave01 ~]# vim /etc/my.cnf         
[client]
#default-character-set=utf8
[mysqld]
server-id = 2           
log_bin = master-bin                
relay-log = relay-log-bin

[root@mysql-slave01 ~]# systemctl restart mysqld

[root@mysql-slave02 ~]# vim /etc/my.cnf
[client]
#default-character-set=utf8

[mysqld]
server-id = 3                    
relay-log = relay-log-bin

[root@mysql-slave02 ~]# systemctl restart mysqld
  1. 授权同步与MHA管理账号
bash 复制代码
# 所有MySQL节点创建集群专属授权账号
mysql> grant replication slave on *.* to 'myslave'@'192.168.108.%' identified by '123';  # 主从同步专用账号
mysql> grant all privileges on *.* to 'mha'@'192.168.108.%' identified by 'manager';     # MHA集群管理账号

# 补充基于主机名(hostname)的授权,规避MHA权限检测报错
# MHA内部会同时使用IP和主机名去连接数据库,只授权IP会导致MHA校验权限失败
mysql> grant all privileges on *.* to 'mha'@'mysql-master' identified by 'manager';
mysql> grant all privileges on *.* to 'mha'@'mysql-slave01' identified by 'manager';
mysql> grant all privileges on *.* to 'mha'@'mysql-slave02' identified by 'manager';

# 批量刷新所有权限,确保生效
mysql> flush privileges; 
  1. 搭建一主两从架构
bash 复制代码
# 主库查看二进制日志状态,记录日志名与偏移量
mysql> show master status;

# 所有从库配置主从同步,关联主库节点
mysql> change master to master_host='192.168.108.131',master_user='myslave',master_password='123',master_log_file='master-bin.000001',master_log_pos=1897;
mysql> start slave; 
mysql> show slave status\G;

# 从库开启只读模式,防止人为误写入破坏数据一致性
mysql> set global read_only=1;

3.4 MHA组件安装

安装顺序:所有节点先装node组件 → 管理节点装manager组件

Manager 提供监控、检查、故障转移等人工可操作脚本;Node 节点工具由 MHA 自动调用,主要用于日志保存、差异中继日志应用、清理中继日志。

bash 复制代码
# 1.所有节点安装MHA所需全部依赖环境
[root@all ~]# yum install epel-release --nogpgcheck -y   # 安装第三方扩展源
[root@all ~]# yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker perl-CPAN

# 2.所有MySQL数据节点安装MHA Node组件
[root@all ~]# tar zxvf mha4mysql-node-0.57.tar.gz
[root@all ~]# cd mha4mysql-node-0.57
[root@all ~]# perl Makefile.PL                     # 生成编译配置文件
[root@all ~]# make && make install                 # 编译并安装组件

# 3.MHA管理节点单独安装Manager管理组件
[root@mha ~]# tar zxvf mha4mysql-manager-0.57.tar.gz
[root@mha ~]# cd mha4mysql-manager-0.57
[root@mha ~]# perl Makefile.PL
[root@mha ~]# make && make install

MHA Manager(管理节点,/usr/local/bin 工具)

  1. masterha_check_ssh:检查 SSH 免密配置
  2. masterha_check_repl:检查 MySQL 主从复制状态
  3. masterha_manager:启动 MHA 管理服务
  4. masterha_check_status:查看 MHA 运行状态
  5. masterha_master_monitor:监控主库是否宕机
  6. masterha_master_switch:故障转移(手动 / 自动)
  7. masterha_conf_host:增删配置里的数据库节点
  8. masterha_stop:停止 MHA 管理服务

MHA Node(所有数据库节点,工具由 Manager 自动调用,一般不用手动执行)

  1. save_binary_logs:保存、复制主库 binlog
  2. apply_diff_relay_logs:识别中继日志差异,把缺失事件应用到其他从库
  3. filter_mysqlbinlog:剔除无用回滚事件(MHA 已废弃不用)
  4. purge_relay_logs:清理中继日志,不会阻塞 SQL 线程

3.5 集群免密SSH配置

所有节点两两免密登录,保证MHA正常通信

bash 复制代码
# 所有节点生成RSA密钥对(全程回车,无需设置密钥密码)
[root@all ~]# ssh-keygen -t rsa

# MHA管理节点分发密钥,实现管理节点到数据节点免密通信
[root@mha ~]# ssh-copy-id 192.168.108.131
[root@mha ~]# ssh-copy-id 192.168.108.132
[root@mha ~]# ssh-copy-id 192.168.108.133

# 所有数据节点需两两分发密钥,保证集群全节点免密互通
[root@mysql-master ~]# ssh-keygen -t rsa
[root@mysql-master ~]# ssh-copy-id 192.168.108.132
[root@mysql-master ~]# ssh-copy-id 192.168.108.133

[root@mysql-slave01 ~]# ssh-keygen -t rsa
[root@mysql-slave01 ~]# ssh-copy-id 192.168.108.131
[root@mysql-slave01 ~]# ssh-copy-id 192.168.108.133

[root@mysql-slave02 ~]# ssh-keygen -t rsa
[root@mysql-slave02 ~]# ssh-copy-id 192.168.108.131
[root@mysql-slave02 ~]# ssh-copy-id 192.168.108.132

3.6 MHA核心配置(VIP漂移)

  1. 配置VIP自动切换脚本
bash 复制代码
# 复制官方VIP漂移脚本至系统命令目录,方便全局调用
[root@mha ~]# cp /root/mha4mysql-manager-0.57/samples/scripts/master_ip_failover /usr/local/bin
bash 复制代码
[root@mha ~]# vim /usr/local/bin/master_ip_failover
#!/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.108.200';        # 高可用虚拟IP
my $brdc = '192.168.108.255';       # 网段广播地址
my $ifdev = 'ens33';                # 服务器物理网卡名称
my $key = '1';                      # 虚拟子网卡序号,生成 ens33:1

# 方案1:使用ifconfig命令管理VIP(CentOS7常用,部分新版系统已弃用ifconfig)
my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig ens33:$key down";

my $exit_code = 0;

# 方案2:ip命令版本(推荐,现代Linux系统,取消注释即可替换上面方案)
# 添加VIP + ARP广播刷新交换机MAC表,解决VIP切换后网络不通问题
#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";
}
  1. 集群主配置文件
bash 复制代码
# 创建MHA集群专属配置目录
[root@mha ~]# mkdir /etc/masterha

# 复制官方模板配置文件,快速初始化集群配置
[root@mha ~]# cp /root/mha4mysql-manager-0.57/samples/conf/app1.cnf /etc/masterha/

# 编辑MHA集群核心配置文件
[root@mha ~]# 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=/usr/local/mysql/data                     # MySQL binlog日志存储路径
master_ip_failover_script=/usr/local/bin/master_ip_failover # VIP漂移脚本路径
user=mha                                                    # MHA集群管理账号
password=manager                                            # MHA集群管理密码
ping_interval=1                                             # 集群节点心跳检测间隔(秒)
repl_user=myslave                                           # 主从同步账号
repl_password=123                                           # 主从同步密码
ssh_user=root                                               # 集群SSH免密登录用户

[server1]
hostname=192.168.108.131     # 原主库节点IP
port=3306                    # MySQL服务默认端口

[server2]
hostname=192.168.108.132     # 从库1节点IP(备选主库)
port=3306
candidate_master=1           # 开启备选主库资格,故障优先切换
check_repl_delay=0           # 忽略日志同步延迟,提升切换效率

[server3]
hostname=192.168.108.133     # 从库2节点IP
port=3306

3.7 集群验证与启动

bash 复制代码
# 1.校验集群所有节点SSH免密通信是否正常
[root@mha ~]# masterha_check_ssh -conf=/etc/masterha/app1.cnf

# 2.校验MySQL主从复制集群状态是否正常
[root@mha ~]# masterha_check_repl -conf=/etc/masterha/app1.cnf

# 3.主库手动初始化绑定VIP,对外提供统一访问入口
[root@mysql-master ~]# /sbin/ifconfig ens33:1 192.168.108.200/24

# 4.后台启动MHA监控服务,保留故障节点配置,避免节点被剔除
[root@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 &

# 5.查看MHA服务运行状态,确认监控启动成功
[root@mha ~]# masterha_check_status --conf=/etc/masterha/app1.cnf

3.8 故障模拟与修复

  1. 模拟主库宕机,MHA自动切换备选主库(slave01)
bash 复制代码
# 模拟原主库MySQL服务宕机,触发MHA自动故障切换机制
[root@mysql-master ~]# systemctl stop mysqld

# 实时监控MHA日志,观察VIP漂移、主库切换完整流程
[root@mha ~]# tailf /var/log/masterha/app1/manager.log
  1. 故障原主库修复
bash 复制代码
# 修复原主库故障,重启MySQL服务
[root@mysql-master ~]# systemctl start mysqld

# 配置原主库为新主库(slave01)的从节点,重新接入集群
[root@mysql-master ~]# mysql -uroot -phuawei
mysql> change master to master_host='192.168.108.132',master_user='myslave',master_password='123',master_log_file='master-bin.000002',master_log_pos=2210;
mysql> start slave;
mysql> show slave status\G;

四、总结

  1. 数据备份:物理冷备份适合整机快速恢复,mysqldump逻辑备份适合灵活迁移,binlog增量备份实现数据零丢失;

  2. 主从复制:实现数据冗余,读写分离分担查询压力,大幅提升数据库并发能力;

  3. MHA高可用:解决主库单点故障,秒级自动切换,修改启动参数和节点配置可实现原主库复用,完善集群冗余架构,适配生产高可用场景。

相关推荐
..Dauntless..1 小时前
【Linux】进程地址空间初步理解
linux·运维·服务器
Julien20041 小时前
Docker 网络(一)
linux·运维·服务器·ssh·学习方法
字节跳动的猫2 小时前
LikeShop 积分体系全链路改造:获取规则、订单抵扣与积分商品兑换二开
运维·数据结构
杨云龙UP2 小时前
一次数据库查询缓慢故障复盘:大表数据增长、SQL全表扫描导致系统响应异常
linux·运维·服务器·数据库·sql·mysql
stark张宇2 小时前
从页、区、段到 B+Tree:InnoDB 表空间如何组织数据?
mysql
PellyKoo3 小时前
【linux运维】ubuntu+samba 用户组独占目录权限配置踩坑记
linux·运维·ubuntu
wtblszn3 小时前
空压机在线监测物联网方案
大数据·运维·物联网·自动化·能源
AR-26710-3 小时前
Linux Day15——系统管理复习
linux·运维
吴声子夜歌3 小时前
Nginx应用与运维——Nginx HTTP模块详解(动态赋值功能模块)
运维·nginx·http