###异步复制
MySQL 提供了异步复制,主库并不关心备库是否收到日志,从而可能导致较多
的数据丢失。从MySQL5.5开始引入了一种半同步复制功能,该功能可以确保主
服务器和至少一台从服务器之间的数据一致性和冗余,从而可以减少数据的丢失
master将binlog event发送给slave后,不去确认slave是否已经收到就返回成功给客户端。
###半同步介绍
介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。
#####半同步复制的潜在问题
客户端事务在存储引擎层提交后,在得到从库确认的过程中,主库宕机了,此时,可能的情况有两种
######事务还没发送到从库上
此时,客户端会收到事务提交失败的信息,客户端会重新提交该事务到新的主上,当宕机的主库重新启动后,以从库的身份重新加入到该主从结构中,会发现,该事务在从库中被提交了两次,一次是之前作为主的时候,一次是被新主同步过来的。
######事务已经发送到从库上
此时,从库已经收到并应用了该事务,但是客户端仍然会收到事务提交失败的信息,重新提交该事务到新的主上。
针对上述潜在问题,MySQL 5.7引入了一种新的半同步方案:Loss-Less半同步复制。
具体逻辑为master将每个事务写入binlog , 传递到slave刷新到磁盘(relay log)。master等待slave反馈接收到relay log的ack之后,再提交事务并且返回commit OK结果给客户端。即使主库crash,所有在主库上已经提交的事务都能保证已经同步到slave的relay log中。同时引入了参数rpl_semi_sync_master_wait_point来控制使用的策略,默认值为AFTER_SYNC,即5.7的改进做法,还有一个可选值为AFTER_COMMIT,即5.6中的策略。
MySQL5.6处理逻辑图
MySQL5.7处理逻辑图
参考:http://blog.itpub.net/15498/viewspace-2143986/
-
在一主多从的架构中,如果要开启半同步复制,并不要求所有的从都是半同步复制。
-
MySQL 5.7极大的提升了半同步复制的性能。
###独立线程处理ACK
5.6版本的半同步复制,dump thread 承担了两份不同且又十分频繁的任务:传送binlog 给slave ,还需要等待slave反馈信息,而且这两个任务是串行的,dump thread 必须等待 slave 返回之后才会传送下一个 events 事务。dump thread 已然成为整个半同步提高性能的瓶颈。在高并发业务场景下,这样的机制会影响数据库整体的TPS 。
5.7版本的半同步复制中,独立出一个 ack collector thread ,专门用于接收slave 的反馈信息。这样master 上有两个线程独立工作,可以同时发送binlog 到slave ,和接收slave的反馈。
####master支持等待多个slave
在MySQL5.6中当半同步开启时,master只是保证一个slave接收到日志,这样当在一主多从的场景下,master和接收到最新日志的slave都挂掉了,那就会丢失数据。这样增加多个备库也不会提高HA的可用性。
在MySQL5.7.3中新增了参数rpl_semi_sync_master_wait_slave_count,可以用来控制master需要保证多少个slave接收到日志。