Seconds_Behind_Master之困惑與解釋

1.以前一直對這個參數很模糊,今天閒下心來看源碼文件 sql/rpl_slave.cc (MySQL 5.6.16)

if (mi->rli->slave_running) 
    {
      /* Check if SQL thread is at the end of relay log
           Checking should be done using two conditions
           condition1: compare the log positions and
           condition2: compare the file names (to handle rotation case)
      */
      if ((mi->get_master_log_pos() == mi->rli->get_group_master_log_pos()) &&
           (!strcmp(mi->get_master_log_name(), mi->rli->get_group_master_log_name())))
      {
        if (mi->slave_running == MYSQL_SLAVE_RUN_CONNECT)    #IO SQL都處於runing且空閒時刻 time_diff=0
          protocol->store(0LL);
        else
          protocol->store_null();
      }
      else
      {
        long time_diff= ((long)(time(0) - mi->rli->last_master_timestamp)    #計算公式
                                - mi->clock_diff_with_master);
      /*
        Apparently on some systems time_diff can be <0. Here are possible
        reasons related to MySQL:
        - the master is itself a slave of another master whose time is ahead.
        - somebody used an explicit SET TIMESTAMP on the master.
        Possible reason related to granularity-to-second of time functions
        (nothing to do with MySQL), which can explain a value of -1:
        assume the master's and slave's time are perfectly synchronized, and
        that at slave's connection time, when the master's timestamp is read,
        it is at the very end of second 1, and (a very short time later) when
        the slave's timestamp is read it is at the very beginning of second
        2. Then the recorded value for master is 1 and the recorded value for
        slave is 2. At SHOW SLAVE STATUS time, assume that the difference
        between timestamp of slave and rli->last_master_timestamp is 0
        (i.e. they are in the same second), then we get 0-(2-1)=-1 as a result.
        This confuses users, so we don't go below 0: hence the max().

        last_master_timestamp == 0 (an "impossible" timestamp 1970) is a
        special marker to say "consider we have caught up".
      */
        protocol->store((longlong)(mi->rli->last_master_timestamp ?
                                   max(0L, time_diff) : 0));                               #diff_tiime< 0 當做0處理。
      }
    }
    else
    {
      protocol->store_null(); #IO或SQL線程時NO,或者同時爲NO,Seconds_Behind_Master爲NULL
    }

總結

1.從上面的源碼部分看出,Seconds_Behind_Master=當前slave 系統時間減去sql_thread最近接受到的binlog的timestamp,然後再減去master和slave的系統時間差。當值< 0 ,處理成0了。

從上面也可以看出,((long)(time(0) - mi->rli->last_master_timestamp)    #計算公式

                                - mi->clock_diff_with_master);

可以分析出 延時 跟master和slave的時區無關。M +7   S +8  M在10點執行  diff_time=(11-10)- (11-10) = 0 ,只要S 沒有延時。


2.IO或SQL線程時NO,或者同時爲NO,Seconds_Behind_Master爲NULL,這也是在複製中斷時看到爲NULL。

很好奇就算可以出現負數的情況,但是已經都處理成0了。


3.* 出現負數的情況:

1.人爲的set master 的系統時間小於 slave

2. A--->B-->C  :計算C 延時binlog 的時間取的是A的時間,有在主從之外的節點的時間值加入計算,有可能出現負值。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章