参考:主从32讲的:27节、从库Seconds_Behind_Master的计算方式

                               28、从库Seconds_Behind_Master延迟总结

 

 

版本:5.7.24

 

 

--一、查看从库状态
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Connecting to master                //IO线程状态
                  Master_Host: 192.168.56.61                       //连接的master IP
                  Master_User: repl                                //连接的master username
                  Master_Port: 3306                                //连接的master port
                Connect_Retry: 60                                  
             Master_Log_File: mysql-bin.000023                     //IO线程读到的master的binlog
          Read_Master_Log_Pos: 682                                 //IO线程读到的master的binlog的pos
               Relay_Log_File: mysql-relay-bin.000018              //SQL线程执行到的relay log
                Relay_Log_Pos: 4                                   //SQL线程执行到的relay log的pos
        Relay_Master_Log_File: mysql-bin.000023                    //SQL线程执行到对应master的binlog
             Slave_IO_Running: Connecting                          //IO线程状态
            Slave_SQL_Running: Yes                                 //SQL线程状态
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 682                                  //SQL线程执行到对应master的binlog的pos
              Relay_Log_Space: 2064
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: NULL                                                                                    //和master差距的时间 单位:秒  (即使是延迟0秒 也可能又复制延迟 详见如下:)
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 2003                                                                                    //最近一个IO线程错误 id
                Last_IO_Error: error connecting to master 'repl@192.168.56.61:3306' - retry-time: 60  retries: 149     //最近一个IO线程错误 log
               Last_SQL_Errno: 0                                                                                       //最近一个SQL线程错误 id
               Last_SQL_Error:                                                                                         //最近一个SQL线程错误 log
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 0
                  Master_UUID: c959bdb9-f94c-11e9-b3b8-0800277143f5                                                    //master的uuid
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400                    
                  Master_Bind:
      Last_IO_Error_Timestamp: 191216 16:44:04
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set: c959bdb9-f94c-11e9-b3b8-0800277143f5:5-6                                                 //接受到的GTID集合
            Executed_Gtid_Set: c959bdb9-f94c-11e9-b3b8-0800277143f5:1-6,                                                //执行过的GTID集合
f7b23f20-f3ea-11e9-bdb9-080027781379:1-1183171
                Auto_Position: 1                                                                                        //GTID为自动指定位置
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
1 row in set (0.03 sec)






--二、Seconds_Behind_Master 为0秒也可能延迟的情况。

Seconds_Behind_Master的计算:
show_slave_status_send_data 方法
{
......
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()) &&           //1、计算IO线程读取到的主库binlog日志位置和SQL线程在备库应用主库binlog的位置 比较。如果一致说明不延迟 继续
        (!strcmp(mi->get_master_log_name(), mi->rli->get_group_master_log_name())))    //就是判断Read_Master_Log_Pos和Exec_Master_Log_Pos ,Master_Log_File和Relay_Master_Log_File  是否一致
    {
      if (mi->slave_running == MYSQL_SLAVE_RUN_CONNECT)
        protocol->store(0LL);                                                          //2、如果IO线程还在 Seconds_Behind_Master为0, 否则 Seconds_Behind_Master为NULL
      else
        protocol->store_null();
    }
    else                                                                               
    {
      long time_diff= ((long)(time(0) - mi->rli->last_master_timestamp)                //3、如果不一样 说明延迟,就计算相差的时间,就是:Seconds_Behind_Master。 具体计算如下:
                       - mi->clock_diff_with_master);
      protocol->store((longlong)(mi->rli->last_master_timestamp ?
                                   max(0L, time_diff) : 0));
    }
  }
  else
  {
    protocol->store_null();
  }
......
}


time(0):为当前从库的系统时间
mi->clock_diff_with_master: 为主库和备库的系统时间差。只是在从库IO线程启动时候 计算的时间差。可参考 handle_slave_io 线程方法中的 get_master_version_and_clock()方法。 
mi->rli->last_master_timestamp:分为以下的DML和DDL。
DML:dml普通语句 就是 各个EVENT的header的timestamp。  MTS的情况是XID_EVENT的header的timestamp
DDL:就是当前时间(QUERY_EVENT的header的timestamp) + 执行DDL的时间



准确查看:
在传统模式下,查看主库和从库的 binlog 的file和pos 是否一致  主从是否有延迟。
在GTID下,查看主库和从库的 执行过的GTID集合(executed_gtid_set) 是否一致  主从是否有延迟。

 

 

--三、延迟可能:
--1、SQL线程执行完了所有的binlog日志,  Seconds_Behind_Master也显示0  看起来虽然不延迟, 但如果有网络问题导致 IO线程读取的慢  也有延迟的可能性。
--2、如果在从库的IO线程启动后 修改了 从库的系统时间,影响了mi->clock_diff_with_master ,可能会有延迟的可能性。
--3、如果是DML语句,事务长时间没有提交 也可能造成延迟。 但Seconds_Behind_Master 延迟不会从0开始 会突然到这个事务所花费的时间, 因为在开头的GTID_EVENT和结尾XID_EVENT 事件都是事务提交时间(可参考《Mysql—binlog二进制日志 解析》 章节),
--4、如果是DDL语句,大表的DDL操作 也可能造成延迟。 但Seconds_Behind_Master 延迟是从0开始。
--5、没有主键或者索引 造成的延迟,参数slave_rows_search_algorithms(参考《Mysql主从复制的参数—slave_rows_search_algorithms 》 章节 ) 可设置index_scan和hash_scan 但不能完全消除问题。
--6、sync_relay_log=1 参数的设置 导致大量的relay log刷盘 ,可能造成延迟。
--7、从库是否开启了log_slave_updates参数(从库 开启binlog日志)。 如果从库不是级联库  5.7之后可以不开启,降低延迟的可能
--8、行锁和mdl索 操作的影响  有延迟的可能性。
--9、MTS中的slave_checkpoint_period参数。默认300毫秒检查一次。  如果设置为1分钟  可能Seconds_Behind_Master显示延迟可能。