这是《MySQL 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 异步复制性能好但可能丢事务;半同步复制让主库至少等待从库确认接收日志;组复制则通过协议多数派共识,提供更强的自动协调能力。
25.1 复制一致性等级
| 模式 | 主库是否等待 | RPO | 复杂度 |
|---|---|---|---|
| 异步 | 不等待 | 可能丢未传输事务 | 低 |
| 半同步 | 等待至少一个从库收到 Binlog | 通常可避免 MySQL 崩溃丢接收前事务 | 中 |
| 组复制 | 事务提交依赖多数派认证 | 多数派存活时一致性更强 | 高 |
| 强一致分布式协议 | 多数派持久化 | 取决于协议和部署 | 最高 |
RPO 是目标恢复点,表示最多可接受丢多少数据;RTO 是恢复时间目标。选型前先回答这两个指标,而不是只看技术名词。
25.2 半同步复制流程
AFTER_SYNC 流程:
1. 主库提交事务;
2. 写 Binlog;
3. 从库接收并写 Relay Log;
4. 从库 ACK;
5. 主库持久化提交并返回客户端;
AFTER_SYNC 在从库应用前确认接收,可减少过期读,也称为 lossless semi-sync。
AFTER_COMMIT 流程:
1. 主库提交事务;
2. 等待从库 ACK;
3. 主库返回客户端;
如果事务已在主库对其他会话可见而从库未 ACK,极端故障下可能出现读感知差异。
25.3 半同步配置
安装插件:
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
MySQL 8.0 插件名可能使用新的别名:
INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so';
INSTALL PLUGIN rpl_semi_sync_replica SONAME 'semisync_replica.so';
主库:
SET GLOBAL rpl_semi_sync_source_enabled = ON;
SET GLOBAL rpl_semi_sync_source_timeout = 3000;
SET GLOBAL rpl_semi_sync_source_wait_point = 'AFTER_SYNC';
从库:
SET GLOBAL rpl_semi_sync_replica_enabled = ON;
STOP REPLICA IO_THREAD;
START REPLICA IO_THREAD;
查看:
SHOW STATUS LIKE 'Rpl_semi_sync_source_status';
SHOW STATUS LIKE 'Rpl_semi_sync_source_yes_tx';
SHOW STATUS LIKE 'Rpl_semi_sync_source_no_tx';
SHOW STATUS LIKE 'Rpl_semi_sync_source_clients';
25.4 半同步降级
如果 timeout 内没有从库 ACK:
主库可降级为异步;
查看降级:
SHOW STATUS LIKE 'Rpl_semi_sync_source_status';
SHOW STATUS LIKE 'Rpl_semi_sync_source_no_tx';
风险:
- 半同步状态可能是动态的;
- 网络抖动导致性能毛刺;
- 降级期间的事务仍可能丢;
- 应用无法感知复制模式;
- 故障切换仍需外部仲裁。
生产必须告警 no_tx 增长和半同步状态变化。
25.5 半同步的误区
误区一:半同步代表从库已完成重放。
实际上它通常只保证日志接收,不保证从库可读。
误区二:有半同步就不会丢数据。
主库磁盘损坏、ACK 后从库损坏、错误切换、降级窗口都可能影响 RPO。
误区三:等待 ACK 一定能提升数据安全。
如果 ACK 节点与主库同机房同时故障,价值有限。
正确做法:
- 至少一个 ACK 从库在不同故障域;
- 使用
AFTER_SYNC; - 设置合理超时;
- 监控降级;
- 切换前校验 GTID 集合;
- 定期演练故障。
25.6 组复制概述
MySQL Group Replication(MGR)是 MySQL 官方的高可用方案:
应用
-> 主节点
-> Group Communication
-> 多数派成员认证和复制
核心机制:
- 事务在主节点执行;
- 通过组通信广播;
- 多数派成员达成一致;
- 冲突检测和认证;
- 各节点按相同顺序应用;
- 故障检测和成员变更。
25.7 单主与多主
| 模式 | 说明 | 适合 |
|---|---|---|
| Single-Primary | 组内只有一个主节点可写 | 大多数在线业务 |
| Multi-Primary | 所有成员可写 | 冲突少、多写需求明确的业务 |
单主优点:
- 语义接近传统主从;
- 冲突少;
- 运维简单;
- 应用改造成本低。
多主风险:
- 事务冲突认证失败;
- 死锁跨节点;
- 热点写放大;
- 应用必须处理新错误;
- 需要严格控制表主键和业务分片。
25.8 MGR 配置要求
基础要求:
- InnoDB 表必须有主键;
- 开启 GTID 和 Binlog;
- ROW 格式;
- 所有成员版本兼容;
- 网络低延迟且稳定;
- 多数派成员可用;
- 服务器 UUID 唯一;
- 事务隔离级别推荐 RC;
- 外键和级联需谨慎;
- 停止复制时避免写不可认证数据。
示例配置:
[mysqld]
server_id = 1
gtid_mode = ON
enforce_gtid_consistency = ON
log_bin = mysql-bin
binlog_format = ROW
log_replica_updates = ON
transaction_isolation = READ-COMMITTED
plugin_load_add = 'group_replication.so'
group_replication_group_name = '11111111-2222-3333-4444-555555555555'
group_replication_start_on_boot = OFF
group_replication_bootstrap_group = OFF
首个节点启动组:
SET GLOBAL group_replication_bootstrap_group = ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group = OFF;
其他节点加入:
START GROUP_REPLICATION;
查看:
SELECT * FROM performance_schema.replication_group_members;
SELECT * FROM performance_schema.replication_group_member_stats;
25.9 MGR 故障检测
组复制依赖多数派判断成员故障:
- 成员之间心跳;
- 超时后被怀疑;
- 多数派达成一致;
- 移除故障成员;
- 单主模式触发选主。
关键参数:
SHOW VARIABLES LIKE 'group_replication_member_expel_timeout';
SHOW VARIABLES LIKE 'group_replication_unreachable_majority_timeout';
脑裂防护:
- 多数派不可达时只读;
- 使用至少 3 个或 5 个节点;
- 跨机房按故障域分布;
- 避免偶数成员导致的多数派风险;
- 外部仲裁不能替代正确部署。
25.10 InnoDB Cluster
InnoDB Cluster 是官方组合方案:
MySQL Shell
+ MGR
+ MySQL Router
组件职责:
| 组件 | 职责 |
|---|---|
| MGR | 数据复制、成员管理、故障检测 |
| MySQL Router | 读写端口、读端口、故障切换路由 |
| MySQL Shell | 集群创建、配置、状态检查 |
典型端口:
6446:读写
6447:只读
查看集群:
dba.getCluster().status();
MySQL Router 自动感知拓扑,但应用仍要处理短暂连接失败和事务重试。
25.11 方案对比
| 需求 | 推荐方案 |
|---|---|
| 小规模、可人工介入 | 异步主从 + 备份 |
| 降低丢失窗口 | 半同步 |
| 自动高可用 | MGR / InnoDB Cluster |
| 超大规模写 | 业务分片 + 每分片高可用 |
| 异地容灾 | 独立集群 + 复制,避免低延迟共识跨地域 |
| 强一致多主 | 谨慎评估业务冲突模型 |
不要用多副本代替备份,也不要用高可用代替容量规划。
本章小结
半同步通过等待从库 ACK 降低丢失窗口,但可能降级且不保证从库已应用。组复制通过多数派协议和认证机制提供自动成员管理,InnoDB Cluster 在 MGR 上叠加 Router 和 Shell 管理能力。方案选择必须围绕 RPO、RTO、网络质量和应用冲突模型。
思考题
- 半同步的 ACK 代表从库已应用事务吗?
AFTER_SYNC和AFTER_COMMIT有什么区别?- MGR 为什么要求数据表必须有主键?
- 单主和多主分别适合什么业务?
- 设计一个跨机房 MGR 部署的故障域方案。