半同步复制仅保证至少一个从库收到并写入relay log,不保证事务已执行完成;金融级需组合gtid、after_sync、sync_binlog=1等配置并校验executed_gtid_set。

半同步复制本身不保证“无损”,MySQL 8.0 的 rpl_semi_sync_master_enabled + rpl_semi_sync_slave_enabled 只能确保至少一个从库收到并写入 relay log,但不保证该事务已执行(apply)完成。金融级场景要求的是「主库提交后,至少一个从库已持久化且已执行完毕」,这需要组合配置与额外校验。
确认半同步插件已加载且生效
半同步不是默认启用的模块,必须手动安装、启用,并验证状态。
- 主库执行:
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';;从库执行:INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; - 主从均需在
my.cnf中显式开启:rpl_semi_sync_master_enabled=1和rpl_semi_sync_slave_enabled=1,重启 MySQL 后才生效 - 检查是否真正激活:
SELECT plugin_name, plugin_status FROM information_schema.plugins WHERE plugin_name LIKE 'rpl_semi%';—— 状态必须是ACTIVE,而非INSTALLED - 常见错误:
Unknown plugin 'rpl_semi_sync_master'表示插件文件缺失或路径不对(CentOS 默认在/usr/lib64/mysql/plugin/,Ubuntu 在/usr/lib/mysql/plugin/)
设置超时与等待策略:避免退化为异步
默认 rpl_semi_sync_master_timeout=10000(10秒),超时后主库自动降级为异步模式,Rpl_semi_sync_master_status 变为 OFF —— 这对金融业务是危险信号。
- 必须监控状态变量:
SHOW STATUS LIKE 'Rpl_semi_sync%';,重点关注Rpl_semi_sync_master_status(应恒为ON)和Rpl_semi_sync_master_no_tx(非零说明已退化) - 建议将
rpl_semi_sync_master_timeout设为较小值(如500毫秒),配合从库性能调优,宁可快速失败也不静默降级 - 启用
rpl_semi_sync_master_wait_point=AFTER_SYNC(MySQL 5.7+ 默认,8.0 仍有效):主库写 binlog + fsync 后即等待从库 ACK,不等自身 commit,降低主库阻塞风险 - 禁用
rpl_semi_sync_master_wait_for_slave_count的多从等待(默认 1),金融级通常只强依赖一个高质量从库,不盲目堆数量
GTID + START SLAVE UNTIL SQL_AFTER_GTIDS 实现故障后精确恢复
仅靠半同步无法解决主库宕机后「最后几条事务是否已在从库 apply」的问题。必须结合 GTID 定位并验证。
- 主从必须统一开启:
gtid_mode=ON、enforce_gtid_consistency=ON,且binlog_format=ROW - 主库宕机前,记下最后成功提交的 GTID 集合:
SELECT @@global.gtid_executed; - 从库上执行:
SELECT @@global.gtid_executed;,比对是否完全包含主库 GTID;若不一致,用STOP SLAVE; START SLAVE UNTIL SQL_AFTER_GTIDS = 'xxx';精确追平 - 关键点:
Seconds_Behind_Master为 0 ≠ 数据已 apply 完毕,它只反映 relay log 读取进度,需用Retrieved_Gtid_Set和Executed_Gtid_Set差值判断真实延迟
规避 auto.cnf UUID 冲突与复制过滤陷阱
克隆虚拟机部署从库时,/var/lib/mysql/auto.cnf 中的 server-uuid 若重复,会导致从库拒绝连接或复制中断,且错误日志中无明确提示。
- 克隆后必须手动修改从库
auto.cnf,生成新 UUID(可用uuidgen或 Pythonimport uuid; print(uuid.uuid4())) - 禁止使用
binlog_do_db/replicate_do_db做库级过滤:它们在 statement 格式下行为不可靠,GTID 模式下已被弃用;改用replicate_rewrite_db或应用层路由 - 从库务必关闭
read_only=ON(默认 8.0 已启用),但金融环境建议额外加super_read_only=ON防止误操作 - 最易忽略的一点:主库
sync_binlog=1和innodb_flush_log_at_trx_commit=1必须同时开启,否则半同步的“持久化”前提就不存在











