半同步复制配置
导学
异步复制是 MySQL 主从的默认模式——主库写完 binlog 就返回成功,不等待从库。如果主库在从库收到数据前崩溃,这部分数据就永久丢失。半同步复制(Semi-Synchronous Replication)让主库至少等待一个从库确认收到 binlog 后才返回成功,在性能和数据安全之间取得平衡。
定义
半同步复制:主库在执行事务提交后,等待至少一个从库将 binlog 写入其 relay log 并返回 ACK 确认,才向客户端返回提交成功。如果等待超时,自动降级为异步复制,不阻塞业务。
安装半同步插件
MySQL 5.7 的半同步复制通过插件实现,主库和从库都需要安装。
主库安装
-- 安装主库半同步插件
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
-- 验证安装
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS
WHERE PLUGIN_NAME LIKE '%semi%';
| PLUGIN_NAME | PLUGIN_STATUS |
|---|---|
| rpl_semi_sync_master | ACTIVE |
从库安装
-- 安装从库半同步插件
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
-- 验证安装
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS
WHERE PLUGIN_NAME LIKE '%semi%';
| PLUGIN_NAME | PLUGIN_STATUS |
|---|---|
| rpl_semi_sync_slave | ACTIVE |
结果解读:
semisync_master.so和semisync_slave.so是 MySQL 5.7 自带的插件文件,位于plugin_dir目录下- 验证
plugin_dir:SHOW VARIABLES LIKE 'plugin_dir'; - 插件安装后持久化到
mysql.plugin表,重启后自动加载
场景一:基础半同步配置(一主一从)
主库配置
-- 开启半同步复制
SET GLOBAL rpl_semi_sync_master_enabled = ON;
-- 查看主库半同步状态
SHOW STATUS LIKE 'Rpl_semi_sync_master%';
| Variable_name | Value |
|---|---|
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_yes_tx | 0 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 0 |
结果解读:
Rpl_semi_sync_master_status = ON:主库半同步模式已激活Rpl_semi_sync_master_yes_tx:成功通过半同步提交的事务数Rpl_semi_sync_master_no_tx:降级为异步提交的事务数
从库配置
-- 开启半同步复制
SET GLOBAL rpl_semi_sync_slave_enabled = ON;
-- 重启从库 IO 线程使配置生效(必须)
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;
-- 查看从库半同步状态
SHOW STATUS LIKE 'Rpl_semi_sync_slave%';
| Variable_name | Value |
|---|---|
| Rpl_semi_sync_slave_status | ON |
结果解读:
- 从库必须重启 IO 线程,半同步插件才能与主库建立半同步连接
Rpl_semi_sync_slave_status = ON表示从库当前正以半同步方式连接主库
场景二:超时降级机制
核心参数:rpl_semi_sync_master_timeout
-- 查看默认超时时间(毫秒)
SELECT @@rpl_semi_sync_master_timeout;
| @@rpl_semi_sync_master_timeout |
|---|
| 10000 |
默认 10000 毫秒 = 10 秒。如果从库在 10 秒内未返回 ACK,主库自动降级为异步复制。
操作语句:调整超时时间。
-- 设为 2 秒(2000 毫秒),更敏感地降级
SET GLOBAL rpl_semi_sync_master_timeout = 2000;
-- 或设为 1 秒
SET GLOBAL rpl_semi_sync_master_timeout = 1000;
结果解读:
- 超时时间越短,主库越快地降级为异步,业务延迟越小,但数据丢失风险越大
- 超时时间越长,主库等待从库越久,数据安全性越高,但事务提交延迟越大
- 生产环境推荐:根据网络延迟设置。同城机房建议 1~2 秒,跨城建议 3~5 秒。如果超过 5 秒从库仍无响应,说明从库已严重延迟或网络故障,降级为异步是合理选择。
场景三:等待多个从库确认
核心参数:rpl_semi_sync_master_wait_for_slave_count
-- 查看默认等待从库数量
SELECT @@rpl_semi_sync_master_wait_for_slave_count;
| @@rpl_semi_sync_master_wait_for_slave_count |
|---|
| 1 |
默认只等待1 个从库确认。如果有一主两从架构,可以要求等待 2 个从库都确认。
操作语句:
-- 要求至少 2 个从库确认后才返回成功
SET GLOBAL rpl_semi_sync_master_wait_for_slave_count = 2;
结果解读:
- 等待从库数越多,数据安全性越高(多个副本确认),但事务提交延迟越大
- 如果实际从库数 < 配置的等待数(如只有 1 个从库但要求 2 个),主库会永远等不到足够 ACK,最终超时降级为异步
- 生产环境推荐:一主两从时设为 1(默认),一主三从时可考虑设为 2,形成"多数派"确认
场景四:等待点控制(After Commit vs After Sync)
MySQL 5.7 引入了更安全的半同步模式。
核心参数:rpl_semi_sync_master_wait_point
-- 查看当前等待点
SELECT @@rpl_semi_sync_master_wait_point;
| @@rpl_semi_sync_master_wait_point |
|---|
| AFTER_SYNC |
| 等待点 | 行为 | 数据安全性 | 性能 |
|---|---|---|---|
AFTER_COMMIT(5.6 默认) | 主库先提交事务,再等待从库 ACK | 低。如果主库提交后崩溃,从库未收到数据,主库已提交的数据无法找回 | 稍好 |
AFTER_SYNC(5.7 默认) | 主库先写 binlog 并等待从库 ACK,收到 ACK 后才提交事务 | 高。如果等待期间主库崩溃,事务未提交,可回滚,数据不会不一致 | 稍差 |
结果解读:
- 5.7 默认
AFTER_SYNC是重大改进。在AFTER_COMMIT模式下,存在"主库已提交、从库未收到"的窗口期,如果此时主库崩溃且无法恢复,已提交的数据就丢失了(因为 binlog 可能也未持久化到从库)。 AFTER_SYNC下,主库收到从库 ACK 后才真正提交,崩溃时事务未提交,可安全回滚,然后从库提升为主库继续服务。- 不要改回
AFTER_COMMIT,除非有极其特殊的兼容性需求。
场景五:监控半同步降级频率
操作语句:
-- 主库查看半同步统计
SHOW STATUS LIKE 'Rpl_semi_sync_master%';
关键指标:
| Variable_name | Value | 含义 |
|---|---|---|
| Rpl_semi_sync_master_status | ON | 当前是否处于半同步模式 |
| Rpl_semi_sync_master_yes_tx | 1500 | 成功半同步提交的事务数 |
| Rpl_semi_sync_master_no_tx | 23 | 降级为异步提交的事务数 |
| Rpl_semi_sync_master_tx_avg_wait_time | 520 | 平均等待从库 ACK 的时间(微秒) |
| Rpl_semi_sync_master_net_avg_wait_time | 480 | 平均网络等待时间(微秒) |
| Rpl_semi_sync_master_trx_wait_time | 780000 | 总等待时间(微秒) |
结果解读:
no_tx / (yes_tx + no_tx)的比例反映降级频率。如果比例 > 5%,说明从库延迟严重或网络不稳定,需排查tx_avg_wait_time持续 > 超时时间的 50%,说明从库响应慢,考虑优化从库性能或降低超时阈值- 如果
Rpl_semi_sync_master_status频繁在 ON/OFF 之间切换,说明网络抖动或从库不稳定
场景六:持久化配置到 my.cnf
上述 SET GLOBAL 重启后失效,生产环境应写入配置文件。
主库 my.cnf:
[mysqld]
# 半同步插件
plugin-load = rpl_semi_sync_master=semisync_master.so
rpl_semi_sync_master_enabled = 1
rpl_semi_sync_master_timeout = 2000
rpl_semi_sync_master_wait_for_slave_count = 1
rpl_semi_sync_master_wait_point = AFTER_SYNC
从库 my.cnf:
[mysqld]
# 半同步插件
plugin-load = rpl_semi_sync_slave=semisync_slave.so
rpl_semi_sync_slave_enabled = 1
结果解读:
plugin-load在启动时加载插件,避免INSTALL PLUGIN的手动步骤- 半同步配置应在主从架构搭建时就规划好,而不是事后补丁式添加
常见误区
| 误区 | 正解 |
|---|---|
| "半同步复制不会丢数据" | 不是。半同步只保证 binlog 到达从库的 relay log,不保证从库已执行(apply)。如果主库崩溃,从库可能还有未执行的 relay log。且超时降级为异步后仍有丢失窗口。 |
| "半同步比异步慢很多" | 不一定。如果网络延迟 < 1ms(同城机房),等待 ACK 的开销通常 < 1ms,对业务几乎无感。跨城或从库压力大时才会明显延迟。 |
| "半同步需要所有从库确认" | 不是。默认只等 1 个,可通过 wait_for_slave_count 调整。 |
| "从库开启半同步后不用重启 IO 线程" | 必须重启。rpl_semi_sync_slave_enabled 只在 IO 线程建立连接时生效,不重启不会切换为半同步协议。 |
| "AFTER_COMMIT 和 AFTER_SYNC 没区别" | 区别很大。AFTER_COMMIT 有"提交后崩溃丢数据"的窗口;AFTER_SYNC 在收到 ACK 后才提交,更安全。5.7 默认 AFTER_SYNC 不要改。 |
面试考点
Q:半同步复制和异步复制的区别?
异步复制:主库写完 binlog 即返回成功,不等待从库。最快但主库崩溃时可能丢失未同步的数据。半同步复制:主库等待至少 N 个从库将 binlog 写入 relay log 并返回 ACK 后才返回成功。数据安全性更高,但有等待延迟。超时后自动降级为异步。
Q:rpl_semi_sync_master_timeout 怎么设?
根据网络延迟和从库性能设置。同城低延迟环境建议 1~2 秒;跨城或从库压力大建议 3~5 秒。太短会频繁降级失去半同步意义;太长会阻塞主库事务提交,影响业务。
Q:AFTER_COMMIT 和 AFTER_SYNC 的区别?
AFTER_COMMIT:主库先提交事务,再等待从库 ACK。如果提交后主库崩溃、从库未收到,数据丢失且无法找回。AFTER_SYNC:主库先写 binlog,等待从库 ACK 收到后才提交事务。崩溃时事务未提交,可安全回滚,数据不会不一致。5.7 默认 AFTER_SYNC,更安全。
Q:半同步复制能替代全同步(如 Paxos/Raft)吗?
不能。半同步只保证 binlog 到达从库 relay log,不保证从库已执行,也不处理脑裂。全同步要求多数派确认且已执行,一致性更强。MySQL 5.7 的 Group Replication(MGR)才是基于 Paxos 的全同步方案。
小结
- 半同步复制在主库等待从库 ACK 后返回成功,超时自动降级为异步
- 主库安装
rpl_semi_sync_master,从库安装rpl_semi_sync_slave,从库必须重启 IO 线程生效 rpl_semi_sync_master_timeout控制降级阈值,推荐 1~5 秒根据网络调整rpl_semi_sync_master_wait_for_slave_count控制等待从库数,默认 1,多从时可提高AFTER_SYNC(5.7 默认)比AFTER_COMMIT更安全,崩溃时未提交事务可回滚- 监控
Rpl_semi_sync_master_yes_tx和no_tx比例,评估半同步有效性
下一章引子:半同步复制提升了主从架构的数据安全性,但如果需要多主多从、自动故障切换和全同步一致性,MySQL 5.7.17+ 引入的 Group Replication(MGR)是更高级的解决方案。