MySQLNotes

第 24 章:主从复制

zjc 于 2026-01-24 发布

这是《MySQL 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 主从复制让一份数据拥有多个副本,用于容灾、读写隔离、异地容灾和水平扩展读能力。它也带来延迟、一致性和运维复杂度。

24.1 复制的基本流程

异步复制流程:

主库提交事务
  -> 写 Binlog
  -> Dump Thread 推送 Binlog
  -> 从库 Receiver Thread 写 Relay Log
  -> 从库 Applier Thread 重放 Relay Log
  -> 从库数据更新

关键点:

  1. 主库提交不等待从库应用;
  2. 从库可能落后;
  3. 主从间传输的是 Binlog 事件;
  4. 重放顺序要保证事务一致性;
  5. 从库位点必须持久可靠。

24.2 位点与 GTID

文件位点

mysql-bin.000010:123456

查看主库:

SHOW BINARY LOG STATUS;

查看从库:

SHOW REPLICA STATUS\G

老版本使用:

SHOW SLAVE STATUS\G

GTID

3E11FA47-71CA-11E1-9E33-C80AA9429562:1-100

GTID 让事务有全局身份,主从切换和重建更容易。

配置示例:

[mysqld]
gtid_mode = ON
enforce_gtid_consistency = ON
log_bin = mysql-bin
log_replica_updates = ON
read_only = ON
super_read_only = ON

24.3 搭建主从

主库创建账号:

CREATE USER 'repl'@'10.0.%' IDENTIFIED BY 'Repl123456!'
  REQUIRE SSL;

GRANT REPLICATION SLAVE ON *.* TO 'repl'@'10.0.%';

备份主库:

mysqldump -h10.0.0.11 -uroot -p \
  --single-transaction \
  --source-data=2 \
  --routines --triggers --events \
  --all-databases > primary_backup.sql

恢复到从库:

mysql -h10.0.0.12 -uroot -p < primary_backup.sql

GTID 自动定位:

CHANGE REPLICATION SOURCE TO
  SOURCE_HOST='10.0.0.11',
  SOURCE_USER='repl',
  SOURCE_PASSWORD='Repl123456!',
  SOURCE_AUTO_POSITION=1,
  SOURCE_SSL=1;

START REPLICA;

检查:

SHOW REPLICA STATUS\G

必须确认:

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

24.4 复制线程

线程 职责
Binlog Dump 主库推送 Binlog
Replica I/O 从库接收并写 Relay Log
Replica SQL 从库应用 Relay Log
Coordinator 并行复制协调器
Worker 并行应用事务

查看线程:

SHOW PROCESSLIST;

IO 停说明网络、权限或 Binlog 位点问题;SQL 停说明应用冲突、表结构差异或数据不一致。

24.5 异步复制

默认模式:

主库提交完成即返回客户端;

优点:

  1. 延迟低;
  2. 主库不依赖从库;
  3. 结构简单。

风险:

  1. 主库崩溃时未传事务丢失;
  2. 自动切换需要额外仲裁;
  3. 不适合零 RPO 场景;
  4. 异地延迟会影响更强同步方案。

24.6 并行复制

传统单线程应用是复制延迟的常见瓶颈。MySQL 8.0 支持基于组提交的逻辑时钟并行:

SHOW VARIABLES LIKE 'replica_parallel_type';
SHOW VARIABLES LIKE 'replica_parallel_workers';
SHOW VARIABLES LIKE 'binlog_transaction_dependency_tracking';

配置示例:

replica_parallel_type = LOGICAL_CLOCK
replica_parallel_workers = 8
binlog_transaction_dependency_tracking = WRITESET

适用:

  1. 主库并发高;
  2. 事务粒度小;
  3. 写入模型可并行;
  4. 从库 CPU 和 IO 有余量。

局限:

  1. 单个大事务仍无法拆开;
  2. 热点行顺序限制并行度;
  3. Worker 不是越大越好;
  4. 主库必须提供依赖信息。

24.7 主从延迟

常见原因:

来源 原因
主库 大事务、高频写入、Binlog 洪峰
网络 带宽不足、跨地域 RTT
从库 单线程应用、机器规格差、IO 慢
查询 从库重查询、锁等待
表结构 从库缺少索引导致重放慢
资源 CPU、内存、磁盘瓶颈

排查:

SHOW REPLICA STATUS\G

重点:

Seconds_Behind_Source
Replica_IO_Running
Replica_SQL_Running
Last_SQL_Error
Retrieved_Gtid_Set
Executed_Gtid_Set

更精细的 Performance Schema:

SELECT *
FROM performance_schema.replication_applier_status_by_worker;

Seconds_Behind_Source 有局限:网络长时间断开、时钟差异或状态更新时机都可能让它不准确。需要结合位点差、GTID 差和心跳表监控。

24.8 复制过滤

过滤可以只复制指定库或表:

replicate_do_db = shop
replicate_ignore_db = audit_log

风险:

  1. GTID 一致性管理复杂;
  2. 容易造成主从数据差异;
  3. 切换后拓扑混乱;
  4. 备份和恢复范围不完整;
  5. 应用和数据库过滤规则不完全等价。

高可用集群内节点应尽量保持完整复制。过滤更适合同步特定数据的下游只读节点,并且要有明确标识。

24.9 读写分离

典型应用:

写 -> 主库
强一致读 -> 主库或延迟确认的从库
可容忍旧数据读 -> 从库

一致性问题:

1. 写主库;
2. 立即读从库;
3. 从库还没应用;
4. 用户看到旧数据;

处理方式:

  1. 写后固定时间读主库;
  2. 会话粘性;
  3. 关键路径读主库;
  4. 使用 GTID 等待从库追上;
  5. 版本号或缓存失效;
  6. 明确业务可接受的旧数据窗口。

从库执行等待示例:

SELECT WAIT_FOR_EXECUTED_GTID_SET('<gtid_set>', 1);

不要把所有读都无条件打到从库,也不要把所有读都打到主库。

24.10 主从一致性校验

常用工具:

  1. Percona pt-table-checksum
  2. pt-table-sync
  3. 云厂商一致性校验;
  4. 自研抽样对账;
  5. 业务级指标对账。

原则:

  1. 定期校验核心表;
  2. 低峰执行;
  3. 控制校验范围和频率;
  4. 发现差异先备份;
  5. 分析根因后修复;
  6. 禁止未确认的随意覆盖;
  7. GTID 不代表数据一定一致。

24.11 从库重建

触发条件:

  1. 数据不一致;
  2. 位点丢失;
  3. 复制错误无法安全跳过;
  4. 从库磁盘损坏;
  5. 大范围 DDL 后需要重建;
  6. 主从延迟长期无法收敛。

流程:

1. 评估从库是否仍承载流量;
2. 选择主库低峰备份;
3. 使用物理备份或 Clone Plugin;
4. 恢复到新节点;
5. 配置 GTID 自动定位;
6. 追平延迟;
7. 校验一致性;
8. 恢复流量;

Clone Plugin 示例:

INSTALL PLUGIN clone SONAME 'mysql_clone.so';

CLONE INSTANCE FROM
  'clone_user'@'10.0.0.11':3306
  IDENTIFIED BY 'Clone123456!';

24.12 常见复制错误

1062 主键冲突

原因可能是从库被写入、位点重复、数据损坏或双写。

不要立刻跳过,先确认事务来源和影响。

1032 记录不存在

常见于 STATEMENT 复制、从库缺数据或手工修改。

1396 权限错误

检查复制账号、密码、SSL 和来源主机。

网络中断

确认 Replica_IO_Running 和错误日志,GTID 自动定位后通常可重连。

处理原则:

  1. 保留日志和状态;
  2. 判断单事务差异还是整库差异;
  3. 能重建就重建;
  4. 跳过必须记录 GTID;
  5. 事后校验一致性;
  6. 补齐告警和防再发措施。

本章小结

主从复制通过 Binlog、Relay Log 和 Applier 线程传播数据。GTID 简化位点管理和切换,并行复制缓解应用瓶颈。读写分离必须明确一致性策略,延迟监控不能只依赖 Seconds_Behind_Source,核心数据要定期校验并具备快速重建能力。

思考题

  1. 主从复制的三个关键线程分别做什么?
  2. GTID 相比文件位点有什么优势?
  3. 主从延迟的常见来源有哪些?
  4. 读写分离后如何避免写后读旧数据?
  5. 设计一套从库延迟超阈值的应急处理流程。