必须用半同步复制或group replication才能保证主库提交后至少一份副本已落盘;半同步适合轻量增强现有主从,group replication适合新建强一致高可用集群。

MySQL 实时热备不能只靠异步复制,必须用半同步复制或 Group Replication 才能保证主库提交后至少一份副本已落盘。二者不是替代关系,而是适用场景不同:半同步适合已有主从架构的轻量增强;Group Replication 适合需要多节点自动故障转移、强一致性保障的新建高可用集群。
半同步复制:在现有主从上加一层确认机制
半同步复制本质是让主库 DUMP 线程在发完 binlog 后,等至少一个从库写入 relay log 并刷盘(flush relay log)再返回成功。它不等 SQL 线程执行完,所以延迟可控,但能避免主库宕机丢事务。
- 主库必须加载插件:
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';从库对应加载rpl_semi_sync_slave -
rpl_semi_sync_master_timeout默认 10000 毫秒,超时即退化为异步——这是保护写入性能的关键开关,别设成 0 - 必须开启 GTID(
gtid_mode=ON+enforce_gtid_consistency=ON),否则切换主从时容易错位 - 检查状态用
SHOW VARIABLES LIKE 'rpl_semi_sync%'和SHOW STATUS LIKE 'Rpl_semi_sync%',重点关注Rpl_semi_sync_master_status和Rpl_semi_sync_slave_status是否为ON
Group Replication:多节点自动选主,但要求更严
Group Replication 是 MySQL 原生的 Paxos 协议实现,不是“主从”,而是“组内多数派确认”。它天然支持多写(multi-primary)或单主(single-primary),但所有节点都必须是 InnoDB 引擎,且不能用 MyISAM、MEMORY 等非事务引擎。
- 强制要求
disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY",否则启动失败 -
server_id、gtid_mode、enforce_gtid_consistency这三项是硬门槛,缺一不可 - 组名
group_replication_group_name必须是合法 UUID 格式,比如"aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",不能随便写字符串 - 启动前必须先
START GROUP_REPLICATION,不是START SLAVE;首次加入要用group_replication_start_on_boot=OFF避免自启失败卡住
常见错误现象和对应动作
配置后看似正常,但数据没同步或写入卡住,大概率是以下几类问题:
- 主库
rpl_semi_sync_master_status为OFF:检查插件是否真正加载(SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE 'rpl_semi%'),以及从库是否连上来并启用了半同步 - Group Replication 启动卡在
RECOVERING状态:通常是 donor 节点的group_replication_recovery通道没通,确认CHANGE REPLICATION SOURCE TO SOURCE_USER='repl', SOURCE_PASSWORD='xxx'已正确配置,且用户有BACKUP_ADMIN权限 - 写入变慢但没报错:半同步下检查
Rpl_semi_sync_master_no_times是否持续增长,说明频繁超时退化;Group Replication 下看performance_schema.replication_group_members中成员状态是否全为ONLINE - 从库无法加入 Group:检查防火墙是否放行
33061(Group Replication 专用端口),以及bind_address是否绑定到了可访问地址(不能是127.0.0.1)
半同步复制的确认粒度是「relay log 刷盘」,Group Replication 的确认粒度是「组内多数节点持久化事务」——前者快但弱一致,后者慢但真容灾。别指望用半同步实现跨机房强一致,也别拿 Group Replication 当普通主从去配 read_only=OFF 后乱写。配置项背后是协议逻辑,改一个参数前,先想清楚它在协议栈里管哪一层。











