半同步复制不能完全避免主从切换时的数据丢失,但能显著降低概率;需正确安装匹配版本的插件、主从分别启用对应参数、重启从库io线程,并将rpl_semi_sync_master_wait_point设为after_commit以兼顾一致性与可见性。

半同步复制不能完全避免主从切换时的数据丢失,但能显著降低概率——前提是正确安装插件、启用参数,并确认 rpl_semi_sync_master_wait_point 设置合理。盲目开启 rpl_semi_sync_master_enabled=1 不等于数据不丢。
确认 MySQL 版本与插件文件是否存在
MySQL 5.5+ 才支持半同步,但 5.7+ 才默认带 semisync_master.so 和 semisync_slave.so;低于 5.7 需手动下载对应版本的 Google 官方插件(注意架构匹配:x86_64 vs aarch64)。常见错误是直接执行 INSTALL PLUGIN 报错 “Can’t open shared library”,本质就是插件文件缺失或路径不对。
检查方式:
mysql> SELECT @@version; mysql> SHOW VARIABLES LIKE 'plugin_dir';
然后在系统中确认文件存在:
ls -l $(mysql -Nse "SELECT @@plugin_dir")/semisync_*.so
- 若无输出,需先拷贝插件到该目录(如从 MySQL 官方 tar 包解压提取)
- 插件名大小写敏感:
semisync_master.so≠semisync_master.SO - MySQL 8.0.26+ 默认启用
group_replication,可能与半同步冲突,需先禁用或确认兼容性
主库和从库必须分别安装对应插件并动态启用
主库只装 rpl_semi_sync_master,从库只装 rpl_semi_sync_slave;装反或漏装会导致 Rpl_semi_sync_master_clients 始终为 0,看似开启实则未生效。
操作顺序必须严格:
- 主库执行:
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';,再SET GLOBAL rpl_semi_sync_master_enabled = 1; - 从库执行:
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';,再SET GLOBAL rpl_semi_sync_slave_enabled = 1; -
关键一步:从库必须重启 IO 线程才能激活插件响应能力:
STOP SLAVE IO_THREAD; START SLAVE IO_THREAD; - 仅
START SLAVE不够,因为 SQL 线程不参与半同步确认流程
调整 rpl_semi_sync_master_wait_point 避免幽灵事务
MySQL 5.7+ 默认值是 after_sync,主库在收到从库 relay log 写入 ACK 后才提交事务——这看似安全,但若主库在发 ACK 前崩溃,从库已有该事务而客户端未收到成功响应,故障切换后就出现“幽灵事务”(phantom transaction)。
更稳妥的选择是 after_commit:
- 主库先在存储引擎层提交事务(其他会话可见),再等 ACK;即使主库宕机,从库回放后数据状态与主库一致
- 设置命令:
SET GLOBAL rpl_semi_sync_master_wait_point = 'AFTER_COMMIT'; - 该参数必须在插件启用后设置,且只对后续事务生效
- 注意:
after_commit下主库性能略低(因多一次等待),但数据一致性更强
验证是否真正进入半同步状态
别只看 rpl_semi_sync_master_enabled=ON,要查实时运行态指标:
mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
重点关注:
-
Rpl_semi_sync_master_status:必须为ON(不是OFF或TIMEOUT) -
Rpl_semi_sync_master_clients:至少为 1,否则说明从库没连上或插件未激活 -
Rpl_semi_sync_master_no_times:该值持续增长,说明频繁超时降级,需检查网络延迟或rpl_semi_sync_master_timeout是否过小(建议设为 3000–5000ms) -
Rpl_semi_sync_master_yes_tx与Rpl_semi_sync_master_no_tx比值应远大于 1,否则大部分事务仍走异步
最容易被忽略的是:主库重启后,rpl_semi_sync_master_enabled 会重置为 OFF,除非你在 my.cnf 中显式配置了 rpl-semi-sync-master-enabled = 1 并重启 mysqld —— 动态 SET 只作用于当前会话生命周期。











