MySQL主从复制是企业级数据库架构里最基础也最核心的高可用手段。在搭建一主多从集群时,研发和运维人员必须搞清楚异步复制与半同步复制在工作机制和可靠性上的本质区别,否则一旦主库宕机,就可能面临数据丢失或业务误判的麻烦。这两种模式并不是简单的配置开关,而是涉及事务提交路径、网络往返开销以及故障转移策略的系统设计问题。

一、异步复制的基本原理与特点
异步复制是MySQL默认的主从同步方式。主库在处理完客户端提交的事务并写入本地二进制日志(binlog)之后,立刻向客户端返回提交成功的响应,而不会等待任何从库是否接收到这些日志。主库之后通过独立的dump线程将binlog事件推送给各个从库的I/O线程,从库再写入自己的中继日志(relay log)并由SQL线程回放。
这种机制的最大优势是主库写入延迟极低,完全不受从库负载或网络抖动的影响。比如在一个高并发订单写入场景中,主库只需要保证本地磁盘落盘即可返回,TPS可以做到很高。但缺点也同样明显:如果主库突然宕机且尚未把最新binlog传给从库,那么这部分已提交事务就会永久丢失,从库提升为新主后数据并不完整。
-- 查看当前主从复制状态(异步模式下无半同步相关参数) SHOW MASTER STATUS; SHOW SLAVE STATUSG -- 主库创建测试库表 CREATE DATABASE IF NOT EXISTS repl_test; USE repl_test; CREATE TABLE order_log ( id BIGINT PRIMARY KEY AUTO_INCREMENT, amount DECIMAL(10,2), created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 主库插入数据,异步复制下立即返回 INSERT INTO order_log(amount) VALUES (99.50);
从上面代码可以看到,在异步复制架构中,INSERT语句执行完毕即代表主库事务提交完成。此时即使从库因为网络断开没有收到这条记录,主库也不会感知,应用层也以为写入成功了。因此异步复制适合对数据绝对一致性要求不高、但追求高吞吐的日志类或统计类业务。
二、半同步复制的工作机制
半同步复制(Semi-Synchronous Replication)是在MySQL 5.5之后引入的插件式能力。它的核心变化是:主库在提交事务时,必须等待至少一个从库已经接收到binlog事件并写入中继日志(不要求从库执行完SQL),然后向主库发送ACK确认,主库收到这个ACK之后才真正向客户端返回成功。
这个“半”字意味着并不是所有从库都要确认,只要一个就够,且从库只需落盘中继日志而不必完成回放,所以相比全同步复制,它的性能损耗可控。但如果从库响应超时(由rpl_semi_sync_master_timeout控制,默认10秒),主库会自动降级为异步模式继续提供服务,避免主库被从库拖死。这种超时退化机制是半同步在生产环境能够落地的关键。
-- 安装半同步插件(主库与从库均需执行对应插件) -- 主库 INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; -- 从库 INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; -- 开启半同步(动态参数) SET GLOBAL rpl_semi_sync_master_enabled = 1; SET GLOBAL rpl_semi_sync_slave_enabled = 1; -- 设置主库等待从库ACK的超时时间为1秒,避免过长阻塞 SET GLOBAL rpl_semi_sync_master_timeout = 1000; -- 查看半同步运行状态 SHOW STATUS LIKE 'Rpl_semi_sync_master_status'; SHOW STATUS LIKE 'Rpl_semi_sync_slave_status';
通过上面的配置,主库在每次事务提交时会经由dump线程发送binlog,并阻塞等待从库ACK。如果一切正常,Rpl_semi_sync_master_status会显示为ON。一旦从库崩溃或网络中断超过1秒,状态就会变成OFF,主库切回异步。对于支付、账户变动这类不能丢事务的场景,半同步能以极小代价大幅提升容灾等级。
三、异步与半同步的核心差异对比
要直观理解两者的区别,可以从数据一致性、性能影响、故障表现三个维度来比较。异步复制主库不关心从库,一致性最弱;半同步复制保证从库至少收到日志,一致性明显增强。性能上异步几乎无额外网络等待,半同步增加一次RTT往返延迟。
在故障切换时,异步架构如果主库损坏,未同步数据不可恢复;半同步架构下,只要ACK过的从库存活,就不会丢已提交事务。但需要注意,半同步并不等于读写强一致,因为从库中继日志可能还没被SQL线程执行,读从库仍可能看不到最新数据,除非配合延迟感知或走主库读。
| 对比项 | 异步复制 | 半同步复制 |
|---|---|---|
| 主库提交是否等从库 | 不等,直接返回 | 等至少一个从库ACK |
| 数据丢失风险 | 主库宕机可能丢最新事务 | 已ACK事务不丢,未ACK仍可能丢 |
| 写入延迟 | 仅本地落盘时间 | 本地落盘加网络RTT |
| 从库超时表现 | 无影响 | 主库退化为异步 |
| 适用场景 | 日志、缓存、统计 | 交易、账户、配置核心数据 |
四、同步模式选型与配置建议
实际项目中不必全库统一一种模式。可以利用不同集群角色区分:核心交易库开启半同步并调小timeout,避免主库长时间卡住;旁路分析库使用异步减轻主库压力。同时建议监控Rpl_semi_sync_master_status以及从库延迟,发现频繁退化就要排查网络或从库性能。
另外,MySQL 5.7之后还提供了无损半同步(after_sync),即主库在存储引擎提交前就等ACK,进一步避免幻读问题。配置时务必确认插件版本与参数语义,错误设置rpl_semi_sync_master_wait_point可能导致预期外的行为。下面是一段检查与无损模式开启的示例。
-- 查看当前等待点(默认AFTER_SYNC为无损) SHOW VARIABLES LIKE 'rpl_semi_sync_master_wait_point'; -- 若需显式设置为无损模式(需重启会话生效) SET GLOBAL rpl_semi_sync_master_wait_point = 'AFTER_SYNC'; -- 检查从库延迟,确保半同步开启后回放不堆积 SHOW SLAVE STATUSG -- 关注 Seconds_Behind_Master 与 Relay_Log_Pos 增长情况
总之,异步和半同步并非优劣对立,而是不同一致性等级的工具。理解它们底层线程协作与ACK边界,才能根据业务容忍度做出正确架构决策,既保住性能又守住数据底线。