Mysql5.7的新功能中,有一个就是无损复制,其说的无损复制,采用的依然是半同步的复制,跟mysql5.6的半同步有什么区别呢?
我们从两张由调试得来的图来看看这个想象吧?
第一张,主库的查询结果,目前主库是处于调试状态。
我们看到主库上面有两个窗口:
第一个窗口: insert语句正在执行,在此之前已经insert一条记录。
第二个窗口: select语句已经执行完成,因为第一个窗口的最后一个insert语句还没有执行完成,所以只能看到一条数据。特别说明一下,第二个窗口的查询时间T3晚于第一个窗口的最后一个insert语句执行时间T2.
因为是调试,我们堵塞了第一个窗口的最后一个insert语句的线程,让其无法继续进行后续的操作。
接下来,我们看看在从库此时执行查询的结果:
有没有有点惊奇, 在从库居然查到了主库还没有提交完成的数据? 这会不会有问题?从库的数据比主库还多? 不急,听happypig君慢慢给你道来其中的原因。
这就是mysql5.7的无损复制的特性,主库的事务在提交之前,也就是该事务的执行结果对其他线程可见之前,必须在半同步的超时时间内,将事务产生的binlog传送给从库,得到从库的ack包之后,才会进行最后的提交步骤。 简单的说来,就是事务的binlog没有传递到从库之前,主库还没有真正提交该事务。 这就是mysql5.7的无损复制的特性。 跟mysql5.6的区别在于,在mysql 5.6的版本中,是事务的执行结果已经被其他线程可见时,再将binlog 发送给从库,等待从库ack返回后,才给客户端返回结果。 等于是将binlog的输送又提前了一步。 下面来看看oracle技术嘉年华mysql官方画出的无损复制流程图吧。
流程图相当清晰,在T2这个时间点查询表t1, 查询的结果里没有出现T1时间点执行的insert. 但在这个时间点,从库已经收到的binlog ,将binlog变成的从库的relay log ,并可以由sql线程进行relay.
现在我们再来解释一下,之前我们看到在从库查询得到的数据比主库还多的原因,原因就是binlog 已经传送过来了,从库就可以relay binlog 了,因为调式中止了主库线程的继续执行,无法完成最后的提交,该事务在主库上不可见,但从库已经relay该事物的binlog ,所以看到了最新的记录。
上面看到的从库比主库的数据多,完全是调式造成的,在实际情况中,不可能存在。因为主库已经完成了该sql的执行,以及事务提交过程中的几乎所有的阶段,只差最后一步操作了,而从库得到binlog之后,需要重新执行这个sql, 几乎落后了一个sql从开始到结束的执行时间。 所以,理论上不存在从库的数据比主库还新的情况,按理论,至少相差一个事务执行的时间。 但这个时间真的很短。