mysql5.6 半同步复制 after_commit 缺陷, 5.7新增after_sync 目的是解决什么问题?为什么能解决

草稿 有些点待确认

在生产环境中,为了减少mysql主从之间的数据延时,尽可能的保证数据的一致性,我们可以开启mysql的半同步复制。

     mysql默认的复制是异步的,master在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心slave是否已经接收并处理。全同步复制则是master执行客户端提交的事务,会先确保所有从库都执行完事务,才会将结果返回客户端。而半同步复制则介于异步复制以及全同步复制中间,master执行完客户端提交的事务之后,不会立即返回结果给客户端,而是等待一个或一个以上的slave接收到执行事务并写入到relay-log之后才会返回结果给客户端。

    在mysql5.6里面,半同步复制采用的是after commit的模式,如下图1。master执行事务,在接收到客户端的commit请求之后,是在引擎层提交完毕之后,才等待salve的ack信号,最终将结果返回给客户端。在等待salve发出ack信号的过程中, 其他客户端是能在master上看到提交的事务的。下面我们来看看在这种模式下,会存在的问题。(双一模式分析)

 1)对于事务A,master引擎层写入之后,slave还没来得及写入relay log的时候,master宕机了。HA提升slave为master之后。由于client端没有收到commit成功的信号,会有以下两种行为:

        1.1)client重新提交事务A,如果宕机的old master 被作为new slave加入集群之后,事务A在new slave上就被会执行两次。

        1.2)client没有重新提交事务A,其他client端在old master上读到的事务A,在new master上再次读取,就会存在数据不存在的现象。如果宕机的old master 被作为new slave加入集群之后,就会存在主从数据不一致的问题。

    2)对于事务A,master引擎层写入之后,slave写入relay log 还没有提交的时候,master宕机了。HA提升slave为master之后。由于client端没有收到commit成功的信号,会有以下两种行为。

        2.1)client重新提交事务A。这时候事务A在new master上就会执行两次。

        2.2)client没有重新提交事务A。但是事务A实际上已经执行成功。

图1


草稿 有些点待确认

   mysql5.7针对这个问题,做了改造,改造后的模式称为  after sync,如下图2。master在接收到客户端的commit请求之后,会先写入binlog,然后等待salve的ack确认之后,才进行引擎层的写入,并返回结果给客户端。在client端收到确认反馈之前,其他客户端是感知不到该事务的。我们在看看after commit中存在的问题,在after sync中是否存在。(双一模式分析)

    1)对于事务A,master binlog 写入之后,slave还没来得及写入relay log的时候,master宕机了。HA提升slave为master之后。由于client端没有收到commit成功的信号,会有以下两种行为:

        1.1)client重新提交事务A。如果宕机的old master 被作为new slave加入集群之后,由于事务A在old master中执行的时候,没有被引擎层commit,所以会该事务会先回滚。在作为salve加入集群后,接收了new master的事务A重新提交的请求后,会重新提交事务。该事务在new slave上只会成功执行一次。

        1.2)client没有重新提交事务A。如果宕机的old master 被作为new slave加入集群之后,没有被引擎层commit的事务A会先在new slave上进行回滚。因此整个集群的数据是一致的。

    2)对于事务A,master引擎层写入之后,slave写入relay log 还没有提交的时候,master宕机了。HA提升slave为master之后。由于client端没有收到commit成功的信号,会有以下两种行为。

        2.1)client重新提交事务A。这时候事务A在new master上就会执行两次。

        2.2)client没有重新提交事务A。但是事务A已经写入了new master的relay log中。如果宕机的old master 被作为new slave加入集群之后,原事务A回滚之后,会接收到new master的binlog,该事务A会重新应用到从库,整个集群主从数据一致。

图2

相关设置参数如下:

设置应答模式:mysql> SET rpl_semi_sync_master_wait_point= AFTER_SYNC;

设置master接收到N个slave的应答后,才commit 事务:mysql> SET GLOBAL rpl_semi_sync_master_wait_for_slave_count= N;

设置master等待slave应答时间:mysql> SET  rpl_semi_sync_master_timeout= N;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容