Mysql主从同步延迟受到多种因素影响, 比如大事务, 从库查询压力, 网路延迟等; 这些比较常见; 但还受到主从机器系统时钟差的影响,这一点可能容易被忽视。
上周, 就遇到了这样的情况, 主库的系统时间由于某种原因落后于从库几十秒, 结果频繁的出现大的主从延迟同步 ,查了N久业务方面的问题,都找不出原因; 在和同事的交流中,发现大家对参数Seconds_Behind_Master的理解有点补一样,基本有两种理解:
一种理解是来源于 Mysql手册上的描述,大体意思是这个时间是从库线程处理的最近的日志事件的时间戳减去从库IO线程处理的最近一条日志记录的时间戳得到的, 可以简单理解为从库线程与IO线程所处理的最近的日志事件的时间戳差;这个计算方式给人的感觉不是在计算主从延迟,而是在计算从库上两个线程的处理的日志的时差。
另一种理解来源于《High Performace Mysql》上的的描述,大体意思这个参数反映的结果是当前系统时间减去从库IO线程所处理的最近一条日志记录的时间戳; 但这个说法有一个明显的不太让人信服的地方,就是如果机器的系统时间相差比较大怎么办? 显然, 如果系统时间相差比较大的话, 以这样的方式计算主从延迟毫无意义。
在有分歧的情况下, 去查看了一下Mysql的源代码, 结果发现手册上的描述居然不那么准确, 代码大致如下:
......if ((mi->slave_running==MYSQL_SLAVE_RUN_CONNECT) &&mi->rli.slave_running){
long time_diff=((long)(time(0) - mi->rli.last_master_timestamp) - mi->clock_diff_with_master);
protocol->store((longlong)(mi->rli.last_master_timestamp ? max(0, time_diff) : 0));
......}else{
protocol->store_null();
}
从代码看, 如果从库IO线程到主库的连接有问题或者线程没有在运行, Seconds_Behind_Master直接返回NULL; 否则的话, 用从库当前系统时间减去IO线程处理的最近的事件的时间戳;代码里用mi->clock_diff_with_master来排除系统时间差对计算的影响, 那这个值又是怎么计算来的呢? 继续看代码:
......if (!mysql_real_query(mysql, STRING_WITH_LEN("SELECT UNIX_TIMESTAMP()")) &&(master_res=mysql_store_result(mysql)) &&(master_row=mysql_fetch_row(master_res))){ mi->clock_diff_with_master=(long) (time((time_t*) 0) - strtoul(master_row[0], 0, 10));}else if (!check_io_slave_killed(mi->io_thd, mi, NULL)){ mi->clock_diff_with_master=0; ......}
原来这个值是通过在主库上执行SELECT UNIX_TIMESTAMP()来取得主库的系统时间, 然后去减从库的当前系统时间。
原来系统时间差还真的对主从同步延迟参数Seconds_Behind_Master有影响。
转载:http://hi.baidu.com/zhencaishu/blog/item/355f8c1078d537f5c2ce79c2.html
在今天的一次主从部署中,发现主从库所在系统时间差别较大时(差别20天左右),同步的性能也非常差。但没有找到证据,暂且如此怀疑,以后留意
原文地址:https://www.cnblogs.com/sqlservertongbu/p/11013649.html