Skip to content

综合实验三 MySQL 主从复制与高可用部署实战

综合实验三 MySQL 主从复制与高可用部署实战

Section titled “综合实验三 MySQL 主从复制与高可用部署实战”

🎯 本实验学习目标

  • 能从零搭建 MySQL 主从复制环境(两台 Ubuntu 虚拟机)
  • 能配置主库 binlog 和从库 relay log,实现数据实时同步
  • 能通过 SHOW REPLICA STATUS 诊断复制状态
  • 能模拟并排除 4 种常见的复制故障
  • 能理解 MHA、InnoDB Cluster 等高可用方案的原理与适用场景

公司电商系统上线后,数据量和访问量持续增长。为了保证数据安全和读写分离,管理层要求搭建 MySQL 主从复制架构:主库负责写操作,从库负责读操作并作为热备。作为数据库运维工程师,你需要完成从环境搭建到故障排查的全流程。


任务一 复制环境准备(30 分钟)

Section titled “任务一 复制环境准备(30 分钟)”

在 VMware 中将主库虚拟机克隆为从库:

  1. 关闭主库虚拟机
  2. 右键主库虚拟机 → 管理克隆
  3. 选择”创建完整克隆”
  4. 虚拟机名称:Ubuntu-MySQL-Slave
  5. 启动克隆后的虚拟机
Terminal window
# 在从库虚拟机中执行
sudo nano /etc/netplan/01-netcfg.yaml

将 IP 地址修改为 192.168.100.21(主库是 .20,从库用 .21):

network:
version: 2
ethernets:
ens33:
dhcp4: no
addresses:
- 192.168.100.21/24
routes:
- to: default
via: 192.168.100.2
nameservers:
addresses:
- 192.168.100.2
- 8.8.8.8
Terminal window
# 应用网络配置
sudo netplan apply
# 验证 IP 地址
ip addr show ens33 | grep "inet "

第 2 步:修改主机名(可选,方便区分)

Section titled “第 2 步:修改主机名(可选,方便区分)”
Terminal window
# 在从库执行
sudo hostnamectl set-hostname ubuntu-slave
# 在主库执行(如果主机名需要区分)
sudo hostnamectl set-hostname ubuntu-master
Terminal window
# 在主库上 ping 从库
ping -c 4 192.168.100.21
# 在从库上 ping 主库
ping -c 4 192.168.100.20

克隆的虚拟机应该已经安装了 MySQL,验证一下:

Terminal window
# 在从库上检查 MySQL 服务状态
sudo systemctl status mysql --no-pager
# 确认 MySQL 版本
mysql --version
# 登录 MySQL 验证
sudo mysql -u root -p123456 -e "SELECT VERSION();"
Terminal window
# 停止 MySQL 服务
sudo systemctl stop mysql
# 删除 auto.cnf(MySQL 重启后会自动生成新的 UUID)
sudo rm /var/lib/mysql/auto.cnf
# 重新启动 MySQL
sudo systemctl start mysql
# 验证新的 UUID 已生成
sudo cat /var/lib/mysql/auto.cnf
Terminal window
# 在主库上执行
sudo mysql -u root -p123456 -e "SHOW VARIABLES LIKE 'server_id';"
# 在从库上执行
sudo mysql -u root -p123456 -e "SHOW VARIABLES LIKE 'server_id';"

如果两台的 server_id 相同(克隆导致),后续复制会出问题。我们将在任务二和任务三中分别配置。


Terminal window
# 在主库 (192.168.100.20) 上执行
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

[mysqld] 段中添加或修改以下配置:

[mysqld]
# ========= 复制相关配置 =========
# 服务器唯一标识(每个节点必须不同)
server-id = 1
# 开启二进制日志(主从复制的基础)
log_bin = /var/lib/mysql/mysql-bin
# binlog 格式:ROW 模式(最安全,推荐)
binlog_format = ROW
# binlog 过期时间(7 天)
binlog_expire_logs_seconds = 604800
# 单个 binlog 文件最大 100MB
max_binlog_size = 100M
# 允许从库远程连接
bind-address = 0.0.0.0
Terminal window
# 在主库上执行
sudo systemctl restart mysql
sudo systemctl status mysql --no-pager
sudo mysql
-- 验证 binlog 已开启
SHOW VARIABLES LIKE 'log_bin'; -- 应为 ON
SHOW VARIABLES LIKE 'binlog_format'; -- 应为 ROW
SHOW VARIABLES LIKE 'server_id'; -- 应为 1
-- 查看当前 binlog 文件和位置(后面要用)
SHOW BINARY LOG STATUS;
SHOW MASTER STATUS;

输出类似:

+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 157 | | |
+------------------+----------+--------------+------------------+
-- 在主库上执行
sudo mysql
-- 创建复制专用账号
CREATE USER 'repl'@'192.168.100.%'
IDENTIFIED WITH mysql_native_password BY '123456';
-- 授予复制权限
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.100.%';
-- 刷新权限
FLUSH PRIVILEGES;
-- 验证账号创建成功
SELECT user, host, plugin FROM mysql.user WHERE user = 'repl';
Terminal window
# 在主库上执行
# 查看防火墙状态
sudo ufw status
# 如果防火墙已启用,允许从库所在网段访问 MySQL 端口
sudo ufw allow from 192.168.100.0/24 to any port 3306 proto tcp
# 如果防火墙未启用,跳过此步骤
Terminal window
# 在从库上执行——测试能否连接主库的 MySQL
mysql -h 192.168.100.20 -u repl -p123456 -e "SELECT 1;"

预期输出:

+---+
| 1 |
+---+
| 1 |
+---+

如果连接失败,排查顺序:

  1. 主库 bind-address 是否为 0.0.0.0
  2. 主库防火墙是否放通 3306
  3. repl 账号的 host 是否为 192.168.100.%
  4. 网络是否互通

任务三 从库配置与数据同步(30 分钟)

Section titled “任务三 从库配置与数据同步(30 分钟)”
Terminal window
# 在从库 (192.168.100.21) 上执行
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

[mysqld] 段中添加或修改以下配置:

[mysqld]
# ========= 复制相关配置 =========
# 服务器唯一标识(必须与主库不同)
server-id = 2
# 中继日志(从库接收主库 binlog 后写入的本地日志)
relay_log = /var/lib/mysql/mysql-relay
# 从库设为只读(防止误写入破坏数据一致性)
read_only = ON
# 超级用户也只读(防止 root 误操作)
super_read_only = ON
# 允许远程连接(方便 Navicat 监控)
bind-address = 0.0.0.0
Terminal window
# 在从库上执行
sudo systemctl restart mysql
sudo systemctl status mysql --no-pager
-- 验证从库配置
sudo mysql -u root -p123456
SHOW VARIABLES LIKE 'server_id'; -- 应为 2
SHOW VARIABLES LIKE 'relay_log'; -- 应为 /var/lib/mysql/mysql-relay
SHOW VARIABLES LIKE 'read_only'; -- 应为 ON
SHOW VARIABLES LIKE 'super_read_only'; -- 应为 ON

在主库上对数据进行加锁备份,确保备份数据的一致性:

Terminal window
# ====== 在主库上执行以下操作 ======
# 第 1 步:登录 MySQL,加全局读锁
sudo mysql -u root -p123456
-- 加锁(阻止所有写入,确保数据一致性)
FLUSH TABLES WITH READ LOCK;
-- 查看当前 binlog 位置(关键信息!)
--SHOW BINARY LOG STATUS;
SHOW MASTER STATUS;

记录输出中的 File 和 Position,例如:

+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 157 | | |
+------------------+----------+--------------+------------------+
Terminal window
# 第 2 步:另开一个终端窗口,执行全量备份
# (不要关闭上面的 MySQL 会话!)
sudo mysqldump -u root -p123456 \
--all-databases \
--single-transaction \
--source-data=2 \
--routines \
--triggers \
--events \
--set-gtid-purged=OFF \
> /tmp/master_full_backup.sql

参数说明:

参数含义
--all-databases备份所有数据库(包括系统库,主从复制需要)
--single-transactionInnoDB 一致性快照
--source-data=2在备份文件中以注释形式记录 binlog 位置(方便后续查阅)
--routines包含存储过程和函数
--triggers包含触发器
--events包含定时事件
--set-gtid-purged=OFF不输出 GTID 信息(课堂环境简化)
Terminal window
# 第 3 步:确认备份文件生成成功
ls -lh /tmp/master_full_backup.sql
# 查看备份文件中记录的 binlog 位置
grep "CHANGE REPLICATION" /tmp/master_full_backup.sql | head -2
-- 第 4 步:回到之前的 MySQL 会话,解锁
UNLOCK TABLES;
Terminal window
# 在主库上执行
scp /tmp/master_full_backup.sql admin@192.168.100.21:/tmp/
Terminal window
# 在从库上执行
mysql -u root -p123456 < /tmp/master_full_backup.sql
-- 验证数据还原成功
sudo mysql -u root -p123456
SHOW DATABASES;
USE ecommerce;
SHOW TABLES;
SELECT COUNT(*) AS 'users行数' FROM users;
SELECT COUNT(*) AS 'products行数' FROM products;
SELECT COUNT(*) AS 'orders行数' FROM orders;

任务四 复制启动与验证(30 分钟)

Section titled “任务四 复制启动与验证(30 分钟)”
-- 在从库上执行
sudo mysql -u root -p123456
-- 停止可能已运行的复制(如果是重新配置)
STOP REPLICA;
RESET REPLICA;
-- 配置从库连接主库
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = '192.168.100.20',
SOURCE_PORT = 3306,
SOURCE_USER = 'repl',
SOURCE_PASSWORD = '123456',
SOURCE_LOG_FILE = 'mysql-bin.000001',
SOURCE_LOG_POS = 157,
SOURCE_CONNECT_RETRY = 10,
GET_SOURCE_PUBLIC_KEY = 1;

参数说明:

参数含义
SOURCE_HOST主库 IP 地址
SOURCE_PORT主库 MySQL 端口(默认 3306)
SOURCE_USER复制账号(之前创建的 repl)
SOURCE_PASSWORD复制账号密码
SOURCE_LOG_FILE主库的 binlog 文件名(备份时记录的 File)
SOURCE_LOG_POS主库的 binlog 位置(备份时记录的 Position)
SOURCE_CONNECT_RETRY连接失败后重试间隔(秒)
GET_SOURCE_PUBLIC_KEY公钥认证(mysql_native_password 可省略)
-- 在从库上执行
START REPLICA;
-- 查看复制状态
SHOW REPLICA STATUS\G

SHOW REPLICA STATUS\G 的输出中,重点关注以下字段:

字段期望值含义
Replica_IO_RunningYesIO 线程:从主库拉取 binlog
Replica_SQL_RunningYesSQL 线程:回放 relay log 中的事件
Seconds_Behind_Source0 或较小值从库落后主库的秒数
Last_IO_ErrorIO 线程的最新错误信息
Last_SQL_ErrorSQL 线程的最新错误信息
Source_Log_File与主库一致从库当前读取的主库 binlog 文件
Read_Source_Log_Pos逐步增长从库读取到的主库 binlog 位置
-- 精简查看关键字段
SHOW REPLICA STATUS\G

预期看到:

Replica_IO_Running: Yes
Replica_SQL_Running: Yes
Seconds_Behind_Source: 0
Last_IO_Error:
Last_SQL_Error:

MySQL 8.0.23 起引入了新的复制语法。以下是对照表:

旧语法(8.0.23 前)新语法(8.0.23 起)
CHANGE MASTER TOCHANGE REPLICATION SOURCE TO
START SLAVESTART REPLICA
STOP SLAVESTOP REPLICA
SHOW SLAVE STATUS\GSHOW REPLICA STATUS\G
MASTER_HOSTSOURCE_HOST
MASTER_USERSOURCE_USER
MASTER_PASSWORDSOURCE_PASSWORD
MASTER_LOG_FILESOURCE_LOG_FILE
MASTER_LOG_POSSOURCE_LOG_POS
Slave_IO_RunningReplica_IO_Running
Slave_SQL_RunningReplica_SQL_Running
Seconds_Behind_MasterSeconds_Behind_Source
SQL_SLAVE_SKIP_COUNTERsql_replica_skip_counter

任务五 数据同步验证(20 分钟)

Section titled “任务五 数据同步验证(20 分钟)”
-- 在主库上执行
sudo mysql -u root -p123456
USE ecommerce;
-- 记录当前数据量
SELECT COUNT(*) AS '插入前orders行数' FROM orders;
-- 插入一条新订单
INSERT INTO orders (user_id, product_id, quantity, total_amount, order_status)
VALUES (1, 1, 2, 598.00, 0);
-- 再插入一条
INSERT INTO orders (user_id, product_id, quantity, total_amount, order_status)
VALUES (3, 2, 1, 89.90, 1);
-- 确认插入成功
SELECT COUNT(*) AS '插入后orders行数' FROM orders;
SELECT * FROM orders ORDER BY order_id DESC LIMIT 2;
-- 在从库上执行(稍等 1~2 秒让复制完成)
sudo mysql -u root -p123456
USE ecommerce;
-- 验证数据已同步
SELECT COUNT(*) AS '从库orders行数' FROM orders;
SELECT * FROM orders ORDER BY order_id DESC LIMIT 2;
-- 在从库上尝试写入
USE ecommerce;
INSERT INTO orders (user_id, product_id, quantity, total_amount, order_status)
VALUES (2, 1, 1, 299.00, 0);

预期报错:

ERROR 1290 (HY000): The MySQL server is running with the --read-only option
so it cannot execute this statement
  1. 打开 Navicat,新建两个 MySQL 连接:
    • 主库192.168.100.20,端口 3306,root / 123456
    • 从库192.168.100.21,端口 3306,root / 123456
  2. 分别打开 ecommerceorders
  3. 确认两边数据完全一致

任务六 复制故障排查(40 分钟)

Section titled “任务六 复制故障排查(40 分钟)”

故障 1:从库连接不上主库(IO 线程停止)

Section titled “故障 1:从库连接不上主库(IO 线程停止)”
Terminal window
# 在主库上执行——用防火墙阻止从库连接
sudo ufw deny from 192.168.100.21 to any port 3306 proto tcp

然后在从库上重启复制,观察故障:

-- 在从库上执行
STOP REPLICA;
START REPLICA;
SHOW REPLICA STATUS\G

关键字段输出:

Replica_IO_Running: Connecting
Last_IO_Error: error connecting to master 'repl@192.168.100.20:3306' ...
线索判断
Replica_IO_Running: ConnectingIO 线程正在尝试连接,但连不上
Last_IO_Error 中包含 connection refusedtimeout网络层面的问题

常见原因:

  • 主库防火墙阻止了连接
  • 主库 bind-address 不是 0.0.0.0
  • 主库 MySQL 服务未启动
  • IP 地址配置错误
Terminal window
# 在主库上执行——删除刚才的阻止规则
sudo ufw delete deny from 192.168.100.21 to any port 3306 proto tcp
-- 在从库上执行
STOP REPLICA;
START REPLICA;
SHOW REPLICA STATUS\G

确认 Replica_IO_Running: Yes 已恢复。


-- 在从库上执行——故意修改为错误的密码
STOP REPLICA;
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = '192.168.100.20',
SOURCE_USER = 'repl',
SOURCE_PASSWORD = 'wrong_password',
SOURCE_LOG_FILE = 'mysql-bin.000001',
SOURCE_LOG_POS = 157;
START REPLICA;
SHOW REPLICA STATUS\G
Replica_IO_Running: Connecting
Last_IO_Error: Error connecting to source 'repl@192.168.100.20:3306'.
This is attempt 1/86400, ...
Message: Authentication plugin 'mysql_native_password' reported error:
Access denied for user 'repl'@'192.168.100.21' (using password: YES)
线索判断
Access denied认证失败,用户名或密码错误
using password: YES确实传了密码,但密码不正确
-- 在从库上执行
STOP REPLICA;
-- 重新配置正确的密码
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = '192.168.100.20',
SOURCE_USER = 'repl',
SOURCE_PASSWORD = '123456',
SOURCE_LOG_FILE = 'mysql-bin.000001',
SOURCE_LOG_POS = 157;
START REPLICA;
SHOW REPLICA STATUS\G

确认 Replica_IO_Running: Yes 已恢复。


-- 在从库上执行——故意填写错误的 binlog 文件名
STOP REPLICA;
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = '192.168.100.20',
SOURCE_USER = 'repl',
SOURCE_PASSWORD = '123456',
SOURCE_LOG_FILE = 'mysql-bin.999999',
SOURCE_LOG_POS = 1;
START REPLICA;
SHOW REPLICA STATUS\G
Replica_IO_Running: No
Replica_SQL_Running: Yes
Last_IO_Error: Got fatal error 1236 from source when reading data from binary log:
'Could not find first log file name in binary log index file'
线索判断
Could not find first log file指定的 binlog 文件在主库上不存在
Replica_IO_Running: NoIO 线程已停止

常见原因:

  • binlog 文件名写错了
  • 主库 binlog 已经过期被清理
  • 备份时记录的 File 值有误
Terminal window
# 在主库上确认当前的 binlog 文件和位置
sudo mysql -u root -p123456 -e "SHOW BINARY LOG STATUS;"
-- 在从库上执行
STOP REPLICA;
-- 使用正确的 binlog 文件和位置
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = '192.168.100.20',
SOURCE_USER = 'repl',
SOURCE_PASSWORD = '123456',
SOURCE_LOG_FILE = 'mysql-bin.000001',
SOURCE_LOG_POS = 157;
START REPLICA;
SHOW REPLICA STATUS\G

故障 4:数据冲突导致 SQL 线程停止

Section titled “故障 4:数据冲突导致 SQL 线程停止”
-- ====== 第 1 步:在主库上创建一张新表 ======
-- 在主库上执行
sudo mysql -u root -p123456
USE ecommerce;
CREATE TABLE test_conflict (
id INT PRIMARY KEY,
name VARCHAR(50)
);
INSERT INTO test_conflict VALUES (1, '数据A');
-- ====== 第 2 步:在从库上临时关闭 read_only,插入冲突数据 ======
-- 在从库上执行
sudo mysql -u root -p123456
USE ecommerce;
-- 临时关闭 read_only(需要 root 权限)
SET GLOBAL read_only = OFF;
SET GLOBAL super_read_only = OFF;
-- 手动在从库上插入一条与主库冲突的数据
INSERT INTO test_conflict VALUES (1, '冲突数据B');
-- 恢复 read_only
SET GLOBAL read_only = ON;
SET GLOBAL super_read_only = ON;
-- ====== 第 3 步:在主库上对同一行做更新 ======
-- 在主库上执行
UPDATE test_conflict SET name = '数据A已修改' WHERE id = 1;
-- ====== 第 4 步:观察从库复制状态 ======
-- 在从库上执行
SHOW REPLICA STATUS\G
Replica_IO_Running: Yes
Replica_SQL_Running: No
Last_SQL_Error: Could not execute Update_rows event on table ecommerce.test_conflict;
Can't find record in 'test_conflict', Error_code: 1032;
...
线索判断
Replica_SQL_Running: NoSQL 线程已停止,数据不再同步
Can't find record从库找不到要更新的记录(因为数据不一致)
Error_code: 1032找不到目标行(数据冲突的典型错误码)

这是最严重的故障类型——数据不一致导致 SQL 线程崩溃,后续所有数据变更都不会再同步。

-- 在从库上执行(适用于仅跳过 1 个事件的情况)
STOP REPLICA;
SET GLOBAL sql_replica_skip_counter = 1;
START REPLICA;
SHOW REPLICA STATUS\G

修复方法 B:手动修正数据后重启

Section titled “修复方法 B:手动修正数据后重启”
-- 在从库上执行——先确认 test_conflict 表中的数据
USE ecommerce;
SELECT * FROM test_conflict;
-- 手动修正从库数据,使其与主库一致
-- (实际应该先查主库的数据,再在从库上修正)
UPDATE test_conflict SET name = '数据A已修改' WHERE id = 1;
-- 重启复制
START REPLICA;
SHOW REPLICA STATUS\G
故障类型IO 线程SQL 线程典型错误信息修复思路
连接失败Connecting / NoYesconnection refused / timeout检查防火墙、bind-address、网络
认证失败Connecting / NoYesAccess denied检查用户名、密码、host 限制
binlog 位置错误NoYesCould not find ... log file回主库确认正确的 File 和 Position
数据冲突YesNoCan't find record / Error 1032修正数据或跳过事件

任务七 高可用方案认知(30 分钟)

Section titled “任务七 高可用方案认知(30 分钟)”

方案一:MHA(Master High Availability)

Section titled “方案一:MHA(Master High Availability)”

MHA 是目前最成熟的 MySQL 高可用方案之一,由日本工程师开发。

项目说明
原理MHA Manager 节点监控主库,当主库故障时自动将数据最新的从库提升为新主库
切换流程检测到主库宕机 → 从宕机主库的从库中选一个数据最新的 → 将其提升为主库 → 其他从库指向新主库
数据补偿切换前会尝试从宕机主库获取未同步的 binlog 并应用到新主库,最大程度减少数据丢失
优点成熟稳定、自动切换、数据损失小
缺点需要额外部署 MHA Manager 节点、配置较复杂、社区维护减少
MHA Manager(监控节点)
|
┌─────────┼─────────┐
| | |
主库(M) 从库(S1) 从库(S2)
.20 .21 .22
主库宕机 → MHA 自动提升 S1 为新主 → S2 改指向 S1

方案二:InnoDB Cluster(MySQL 官方方案)

Section titled “方案二:InnoDB Cluster(MySQL 官方方案)”

InnoDB Cluster 是 MySQL 官方推出的高可用方案,基于 Group Replication 技术。

项目说明
原理多个 MySQL 节点组成一个组,数据在组内自动同步,任意节点故障后自动选主
组件MySQL Shell + MySQL Router + Group Replication
选主机制基于 Paxos 协议投票,超过半数节点同意即可选出新主
优点官方方案、自动选主、配置工具完善
缺点至少需要 3 个节点(保证多数派)、对服务器性能有一定要求
应用 → MySQL Router(自动路由)
|
┌───────┼───────┐
| | |
节点1 节点2 节点3
(Primary) (Secondary) (Secondary)
↑____________↑____________↑
Group Replication(自动同步)

方案三:ProxySQL / MySQL Router(中间件)

Section titled “方案三:ProxySQL / MySQL Router(中间件)”

这类方案不直接管理复制,而是在应用和数据库之间加一个中间件层。

项目说明
原理中间件感知后端数据库状态,自动将读请求路由到从库,写请求路由到主库
故障转移检测到主库不可用时,自动将写流量切换到新的主库
优点对应用透明、支持读写分离、连接池管理
缺点增加一层网络延迟、中间件本身也需要高可用
对比维度传统主从复制MHAInnoDB Cluster中间件方案
自动故障切换不支持支持支持支持
数据一致性最终一致接近一致强一致依赖底层复制
最少节点数2(1主1从)3(1 Manager + 1主1从)32 + 中间件
配置复杂度中高
适用场景小型项目、学习中大型生产环境企业级、云原生需要读写分离
初学者理解难度★☆☆★★☆★★★★★☆

序号任务耗时完成
任务一复制环境准备(克隆、改 IP、改主机名、修 UUID)30 min
任务二主库配置(binlog、repl 账号、防火墙)30 min
任务三从库配置与数据同步(relay_log、read_only、mysqldump)30 min
任务四复制启动与验证(CHANGE REPLICATION SOURCE TO、双 Yes)30 min
任务五数据同步验证(主库写入、从库只读、Navicat 对比)20 min
任务六复制故障排查(4 种故障模拟与修复)40 min
任务七高可用方案认知(MHA、InnoDB Cluster、方案对比)30 min
知识点关键内容
复制原理主库 binlog → 从库 IO 线程拉取 → relay log → SQL 线程回放
binlog_formatROW 最安全,STATEMENT 日志量小但可能不一致
read_only保护从库数据不被误写入
关键命令CHANGE REPLICATION SOURCE TOSTART REPLICASHOW REPLICA STATUS
排错思路SHOW REPLICA STATUS\G → 看 IO/SQL 线程状态 → 看 Last_Error → 针对性修复
高可用主从复制 ≠ 高可用,需要自动故障切换能力
症状可能原因快速修复
IO_Running: Connecting网络不通、防火墙、认证失败ping → telnet 3306 → 检查账号
IO_Running: Nobinlog 位置错误、主库 binlog 已清理重新确认 File 和 Position
SQL_Running: No数据冲突、表结构不一致跳过事件或手动修正数据
Seconds_Behind_Source 很大从库性能不足、网络延迟大检查从库负载、网络质量
UUID 冲突克隆虚拟机未处理删 auto.cnf 重启 MySQL

附录 A:MySQL 主从复制数据流向图

Section titled “附录 A:MySQL 主从复制数据流向图”
┌──────────────────────┐ ┌──────────────────────┐
│ 主库 (Master) │ │ 从库 (Slave) │
│ 192.168.100.20 │ │ 192.168.100.21 │
│ │ │ │
│ 应用写入 → InnoDB 引擎 │ │ │
│ ↓ │ │ │
│ binlog (ROW 格式) │ ──TCP──→ │ IO Thread 拉取 binlog │
│ │ 3306 │ ↓ │
│ │ │ relay log (本地中继日志) │
│ │ │ ↓ │
│ │ │ SQL Thread 回放事件 │
│ │ │ ↓ │
│ │ │ InnoDB 引擎 → 数据落盘 │
│ │ │ │
│ read_only = OFF │ │ read_only = ON │
└──────────────────────┘ └──────────────────────┘

附录 B:SHOW REPLICA STATUS 关键字段速查

Section titled “附录 B:SHOW REPLICA STATUS 关键字段速查”
字段名含义正常值
Replica_IO_RunningIO 线程状态Yes
Replica_SQL_RunningSQL 线程状态Yes
Seconds_Behind_Source从库落后主库的秒数0 或很小
Source_Host主库 IP192.168.100.20
Source_Log_File从库正在读取的主库 binlog 文件与主库一致
Read_Source_Log_Pos从库读取到的 binlog 位置逐步增长
Relay_Log_File从库当前的 relay log 文件名有值
Relay_Log_Posrelay log 当前位置逐步增长
Last_IO_ErrorIO 线程最后的错误空(正常)
Last_SQL_ErrorSQL 线程最后的错误空(正常)
Source_Server_Id主库的 server-id1
Replica_SQL_Running_StateSQL 线程的详细状态Slave has read all relay log
Executed_Gtid_Set已执行的 GTID 集合视配置而定
Last_IO_ErrnoIO 线程最后的错误码0(正常)
Last_SQL_ErrnoSQL 线程最后的错误码0(正常)
准备阶段 主库配置 从库配置
┌────────────┐ ┌──────────────┐ ┌──────────────┐
│ 克隆虚拟机 │ │ 编辑 mysqld.cnf │ │ 编辑 mysqld.cnf │
│ 改 IP (.21) │ │ server-id = 1 │ │ server-id = 2 │
│ 改主机名 │ │ log_bin = ON │ │ relay_log = ...│
│ 删 auto.cnf │ │ binlog_format │ │ read_only = ON │
│ 互 ping │ │ bind-address │ │ bind-address │
└────────────┘ │ 重启 MySQL │ │ 重启 MySQL │
│ 创建 repl 账号 │ └──────┬───────┘
│ 放通防火墙 │ │
└──────┬───────┘ │
│ │
┌──────┴───────┐ ┌──────┴───────┐
│ SHOW BINARY │ │ mysqldump 还原 │
│ LOG STATUS │ ──scp──→ │ 到从库 │
│ 记录 File/Pos │ 备份文件 └──────┬───────┘
└──────────────┘ │
┌──────┴───────┐
│ CHANGE REPLIC.│
│ SOURCE TO ... │
│ START REPLICA │
│ SHOW REPLICA │
│ STATUS\G │
│ → 双 Yes ✓ │
└──────────────┘