半同步复制:平衡性能与数据安全
概述
半同步复制(Semi-Synchronous Replication)在异步复制的基础上增加了一个约束:主库在提交事务后,必须等待至少一个从库确认收到并写入 Relay Log,才返回给客户端成功。 它在性能和数据安全之间取得了较好的平衡。
半同步复制的工作流程
主库 从库
│ │
│── 1. 事务提交 │
│ ├── 写入 Binlog │
│ └── 不马上返回客户端 │
│ │
│── 2. 发送 Binlog 给从库 │
│ ├── 等待从库确认收到 │
│ └── 等待超时 rpl_semi_sync_master_timeout
│ │
│ 3. 从库收到 Binlog
│ I/O 线程写入 Relay Log
│ 发送 ACK 给主库 ✅
│ │
│── 4. 收到 ACK │
│ ├── 确认至少一个从库收到了 │
│ └── 返回客户端成功 ✅ │
│ │
│ 5. SQL 线程回放(异步)
│ 实际应用到从库数据
关键变化:步骤 1-2 之间增加了等待,步骤 4 确认后再返回客户端。
配置半同步复制
安装插件
-- 主库安装(发送端)
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
-- 从库安装(接收端)
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
配置文件
# 主库配置
[mysqld]
plugin-load = "rpl_semi_sync_master=semisync_master.so"
rpl_semi_sync_master_enabled = ON -- 开启半同步复制(主库)
rpl_semi_sync_master_timeout = 5000 -- 等待超时(毫秒),默认 10s
rpl_semi_sync_master_wait_for_slave_count = 1 -- 等待几个从库确认
rpl_semi_sync_master_wait_point = AFTER_SYNC -- 等待时机
# 从库配置
[mysqld]
plugin-load = "rpl_semi_sync_slave=semisync_slave.so"
rpl_semi_sync_slave_enabled = ON -- 开启半同步复制(从库)
运行时配置
-- 主库
SET GLOBAL rpl_semi_sync_master_enabled = ON;
SET GLOBAL rpl_semi_sync_master_timeout = 5000;
-- 从库
SET GLOBAL rpl_semi_sync_slave_enabled = ON;
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD; -- 需要重启 I/O 线程生效
验证配置
-- 主库检查
SHOW VARIABLES LIKE 'rpl_semi_sync%';
SHOW STATUS LIKE 'Rpl_semi_sync%';
-- 重点关注:
-- Rpl_semi_sync_master_status: ON ← 半同步模式是否启用
-- Rpl_semi_sync_master_clients: 1 ← 有几个从库使用半同步
-- Rpl_semi_sync_master_yes_tx: 100 ← 成功半同步的事务数
-- Rpl_semi_sync_master_no_tx: 0 ← 降级为异步的事务数
AFTER_SYNC vs AFTER_COMMIT
MySQL 5.7+ 支持两种等待时机:
AFTER_SYNC(推荐)
1. 写入 Binlog(Sync)
2. 等待从库 ACK ← 先等待再提交
3. 提交事务
4. 返回客户端成功
优势:
– 所有客户端同时看到数据(主库和从库都可见)
– 主库崩溃时,所有已提交事务在从库都有
– 故障切换零数据丢失
AFTER_COMMIT(旧模式,不推荐)
1. 写入 Binlog
2. 提交事务
3. 等待从库 ACK ← 先提交再等待
4. 返回客户端成功
问题:
– 主库提交后,其他客户端能看到新数据,但从库可能还没收到
– 主库在等待 ACK 时崩溃 → 数据存在主库但从库没有
– 故障切换可能丢数据
推荐使用 AFTER_SYNC,这是 5.7 的默认值。
超时降级
如果从库在 rpl_semi_sync_master_timeout 时间内没有返回 ACK:
主库等待从库 ACK
│
├── ACK 到达 ✅ → 正常提交
│
└── 超时 ❌ → 降级为异步复制
├── 写入错误日志:Warning: 半同步超时,降级为异步
└── 后续事务按异步方式提交
(不会无限等待)
从库恢复后,主库会检测到并自动切换回半同步模式:
-- 主库状态变化
Rpl_semi_sync_master_status: OFF → 降级为异步
Rpl_semi_sync_master_status: ON → 自动恢复为半同步
优缺点
| 维度 | 说明 |
|---|---|
| 优点:数据更安全 | 主库已确认的事务,至少一个从库有 |
| 优点:自动降级 | 从库不可用时,自动降级为异步 |
| 优点:配置简单 | 插件安装 + 几行配置 |
| 缺点:性能下降 | 每次提交增加一个网络往返(~0.5-2ms) |
| 缺点:不是 100% 同步 | 从库确认后到 SQL 应用有一段时间 |
| 缺点:网络敏感 | 跨机房延迟会影响写入性能 |
面试要点
- 半同步复制 = 异步复制 + 等待从库 ACK
- 至少一个从库确认收到 Binlog 后才返回客户端成功
- 超时自动降级为异步复制,保证可用性
- MySQL 5.7+ 推荐
AFTER_SYNC模式 - 数据安全较高但性能下降:每次提交增加一个网络 RTT
- 适用场景:核心业务,对数据一致性和写入性能都有要求
- 不是从库应用后才返回,是从库收到 Relay Log 就 ACK,不等到 SQL 线程回放
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容