seconds_behind_master計算方式

總是被問這個問題,不是準確值,之前看過記不清楚怎麼計算的了,還是看下源碼吧。。。

看下僞代碼
/*
     The pseudo code to compute Seconds_Behind_Master:
     if (SQL thread is running)
     {
       if (SQL thread processed all the available relay log)
       {
         if (IO thread is running)
            print 0;
         else
            print NULL;
       }
        else
          compute Seconds_Behind_Master;
      }
      else
       print NULL;
  */
代碼中的計算方式
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)
        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));
    }
  }
  

首先是隻要認爲sql線程應用完全部的relay log就認爲是0了,本身這個方式就不是精確的,在傳輸或sql應用的時候,主庫上一直有事務,肯定是有延時的,那麼如果傳輸慢或有問題,也是0了。

參考了http://mysql.taobao.org/monthly/2016/03/09/
clock_diff_with_master io線程啓動時會向主庫發送sql語句“SELECT UNIX_TIMESTAMP()”,獲取主庫當前時間,然而用備庫當前時間減去此時間或者主備時間差值即爲clock_diff_with_master。這裏如果有用戶中途修改了主庫系統時間或修改了timestamp變量,那麼計算出備庫延遲時間就是不準確的。

last_master_timestamp 表示主庫執行binlog事件的時間。此時間在並行複製和非並行複製時的計算方法是不同的

看到是用當前時間減去last_master_timestamp這個值在減去時間差,last_master_timestamp這個是主庫的binlog事件時間,那麼在導入備份後,啓動從庫的時候,如果備份文件很大,在導入完啓動複製的時候,所以我們會看到很大的延時出現。

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