设为首页 加入收藏

TOP

再议Seconds_Behind_Master(一)
2015-11-21 02:08:24 来源: 作者: 【 】 浏览:1
Tags:再议 Seconds_Behind_Master

两年前就写过一篇文章解释Seconds_Behind_Master代表的含义以及它为什么不准确,今天同事高老师又提了一个有趣的问题:Seconds_Behind_Master到底是怎么计算的呢?高老师还特地去翻了一下 源码来解释,我发现我之前的理解还是有出入的,于是自己也动手去翻了一下源码,下面就来更全面的解释一下它是怎么计算的,为什么不能完全可信。

我平时读MySQL源码比较少,一般来说通过源码也是查一些基本的问题,对于我来说如果对关键代码位置不熟,比较快捷的方法就是cd到源码的根目录,然后grep "Seconds_Behind_Master" . -R -n。结果如下:
./sql/rpl_rli.cc:1209: Seconds_Behind_Master - not critical).
./sql/slave.cc:1345: "do not trust column Seconds_Behind_Master of SHOW "
./sql/slave.cc:1874: field_list.push_back(new Item_return_int("Seconds_Behind_Master", 10,
./sql/slave.cc:1963: Seconds_Behind_Master: if SQL thread is running and I/O thread is
./sql/slave.cc:3254: alive and connected, this is going to make Seconds_Behind_Master be 0
./sql/slave.cc:3258: Seconds_Behind_Master grows. No big deal.
./sql/slave.cc:4666: We say in Seconds_Behind_Master that we have "caught up". Note that
./sql/slave.cc:4679: Seconds_Behind_Master would be zero only when master has no


从搜索结果来看,主要设计到sql/slave.cc以及sql/rpl_rli.cc,而恰好这两个文件已经可以解决我们的疑惑了。

首先第一个问题,Seconds_Behind_Master到底是怎么计算的?

我们先来看手册上的解释:

This field is an indication of how “late” the slave is:
When the slave is actively processing updates, this field shows the difference between the current timestamp on the slave and the original timestamp logged on the master for the event currently being processed on the slave.
When no event is currently being processed on the slave, this value is 0.

大意就是如果slave正在处理更新,那么sbm的计算方式就是:slave当前的时间戳-正在执行更新的binlog event上附带的timestamp.如果slave没有处理更新,那么sbm=0

那么这么解释对吗?答案是基本上算对,但是里面没解释一些细节。然后我们通过在slave.cc里面找到这个真正的计算公式:
1962     /*
1963       Seconds_Behind_Master: if SQL thread is running and I/O thread is
1964       connected, we can compute it otherwise show NULL (i.e. unknown).
1965     */
1966     if ((mi->slave_running == MYSQL_SLAVE_RUN_CONNECT) &&
1967         mi->rli.slave_running)
1968     {
1969       long time_diff= ((long)(time(0) - mi->rli.last_master_timestamp)
1970                        - mi->clock_diff_with_master);                  
此处省略很多注释
1991       protocol->store((longlong)(mi->rli.last_master_timestamp ?
1992                                  max(0, time_diff) : 0));
1993     }
1994     else
1995     {
1996       protocol->store_null();
1997     }


关键的代码如下:
1. long time_diff= ((long)(time(0) - mi->rli.last_master_timestamp)
                        - mi->clock_diff_with_master); 
2. protocol->store((longlong)(mi->rli.last_master_timestamp ?
                                  max(0, time_diff) : 0)); 

到这里终于看到传说中的sbm计算方法了,这里解释各个变量的含义:
time(0) //从库当前系统时间戳,Linux系统函数
mi->rli.last_master_timestamp //当前从库正在执行语句binlog event时间戳
mi->clock_diff_with_master //主从系统时间戳的差值,slave-master

到这里我们就知道手册上其实描述不准确,还少了一部分clock_diff_with_master,因为主库上记录binlog event的时间戳与从库上计算本地时间戳time(0)都是调用系统的时间函数,而此时假如说主从时间设置不一致,那么这个值不就完全没意义了吗?因此为了尽量避免这种情况出现,每次在从库与主库建立连接的时候都会获取主从的时间戳,然后算出一个差值作为一个常量保存,以后每次算sbm时都会减去这个值。但是有一个问题存在,MySQL只会在建立主从复制连接的时候算这个值,以后都不会再更新,因此假如说主从连接建立好了后去更改主从时间设置,比如NTPD,比如set timestamp=xxx之类的操作,那么此时看到的sbm的值就会更加不可靠了。

在正常情况下第一句就已经是我们show slave status看到的sbm值了,那么第二句是为了解决什么问题呢?
1. clock_diff_with_master是主从SELECT UNIX_TIMESTAMP()的差值,很有可能主库执行的时候是1,从库执行的时候是2(因为并不能保证主从是同一时刻执行),那么此时clock_diff_with_master=1, 那么假设此时time(0)-last_master_timestamp的值等于0,那么0-1=-1,而-1会给用户歧义,于是官方在这种情况下会强制把负值变成0
2. 前面说了sbm的值分两种情况,从库有SQL线程在处理语句时计算方法刚详细解释过,从库SQL线程没有处理语句是把这个值设为0,那么第二句代码就实现了这个功能,第二句的三元表达式告诉我们,当mi->rli.last_master_timestamp值为0的时候,sbm=0。那么mi-
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇mysql explain type 下一篇ubuntu上安装mysql

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: