半同步复制

简介

半同步复制是指主库在执行完客户端提交的事务后不会立刻把结果返回给客户端,会调用dump线程通知从库有新事务产生,从库调用IO线程把获取到的主库binlog写入relay log然后返回ack报文给主库,同时调用SQL线程回放relay log把更新写入本地磁盘,主库调用dump线程接收到一个从库返回的ack报文后确认事务执行成功,把结果返回客户端。MySQL 5.5开始,MySQL官方提供了半同步复制插件,主库在发生故障后从库可以拥有完整的数据副本,所以半同步复制解决了异步复制主从数据不一致问题,但同时造成一定程度的时延,会影响业务性能。

业务流程

  1. 客户端调用用户线程向主库发起数据更新请求,主库在执行完更新操作后把变更写入binlog,主库启动dump线程时调用add_slave()函数将所有从库添加到一个监测队列中,向从库发送报文时调用updateSyncHeader()函数更新报文头中的semi-sync标记。
  2. 从库调用IO线程获取主库的binlog后,调用slaveReadSyncHeader()函数判断报文头中是否有semi-sync标记。如果报文头中有semi-sync标记,从库把接收到的binlog写入relay log后,调用slaveReplay()函数返回ack报文给主库。从库调用SQL线程回放relay log,即把更新写入本地磁盘。
  3. 主库调用ack_receiver线程监测所有从库,调用handleAck()函数将当前binlog中的位置记录到ack_array数组中,收到一个从库回复(rpl_semi_sync_master_wait_for_slave_count == 1)后调用reportReplyBinlog()函数唤醒工作线程,返回成功给客户端。
图1 MySQL半同步复制

事务提交阶段的处理逻辑

事务提交阶段的处理逻辑分为after_sync(更可靠)和after_commit,推荐使用after_sync模式。

适用场景

半同步复制的优点是数据丢失为零,但其缺点是时延较大,所以半同步复制适用于网络时延高,不接受数据丢失的业务场景。