如何查看延迟呢,有的同学可能会说,我们有show slave status里面的Seconds_behind_master的选项,但是那个可不能当做严格意义上的主从延迟标准,这句话该如何理解呢,或者可以换一个问题,为什么SBM(Seconds_behind_master)仅供参考呢,我们来聊一下延迟的一些问题。
首先我们来看一个MySQL复制的流程图,如下所示:
如果需要界定一个时间边界,那就是数据从Master端写入binlog开始到Slave端应用产生binlog为止,这个过程是相对完整的数据同步过程。所以如果要产生延迟,那么就存在诸多的可能性,比如上面画叉的一些环节。
SBM的逻辑是比较sql_thread执行的event的timestamp和io_thread复制好的 event的timestamp(简写为ts)进行比较,而得到的这么时间差值。
源码中我们可以得到一些更加明确清晰的信息,在源码文件sql/rpl_slave.cc中:
从代码来看,有以下的三点需要注意:
1)time(0) 是从库当前系统时间戳,是系统函数
2)mi->rli.last_master_timestamp 是当前从库正在执行SQL的event时间戳
3)mi->clock_diff_with_master 是主从的时间差异值,可以理解是一个校准值
看起来没有问题,但是显然有一些问题,比如:
1)如果Master和Slave端的网路情况不好,即IO_thread的同步是瓶颈,而从Slave端来看,sql_thread能够很快的应用日志数据,SBM值却是0,这样就会造成一个幻觉,感觉没有延迟,但是实际上因为网络条件不佳,已经产生了很大的延迟,对于应用来说,这种差异感受是最直接的。
2)如果Master和Slave端的时间不一致,那么推送过来的延迟是根据日志中的event时间来计算的,很明显这样的结果是不对的,不过从代码中我们可以看到是有mi->clock_diff_with_master来做这个校准的,所以这个问题可以忽略。
3)当从库长时间为收到主库传来的数据,等待超过参数slave_net_timeout默认的3600秒之后,Slave的状态Slave_IO_Running的值为变为No,而在这个过程中,其实得到的就是比较尴尬的假象数据。
4)如果从库存在大量的查询导致处理性能底下,也会造成延迟时间,而这个延迟时间其实是属于额外的资源消耗导致。
5)如果一个数据库在1分钟内产生了大量的binlog,如果按照日志中的timestamp来作为标记,这个延迟其实是很小的,比如延迟是5秒,但是差异的日志量是2G,这种差异带来的负面影响是大的,或者说这种延迟会是一种毛刺。
所以延迟是一个比较难以衡量的指标,在理解方式上存在较大的差异,可以基于日志维度进行衡量,比如根据binlog的偏移量差异,或者是基于时间维度,通过时间戳差值来衡量延迟。
一种相对容易理解的延迟计算方式是基于心跳机制,周期性发送一个标志位,以这个标志位数据到达从库的时间为准,得到的这个值就是延迟,如果说要得到较为准确的延迟情况,可以使用pt-heartbeat。这个工具使用起来也非常便捷,属于pt工具集的一部分。