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的时间,有在主从之外的节点的时间值加入计算,有可能出现负值。