贵州 网站备案,如何加强旅游电子商务网站的建设,西安专业网络推广公司,建筑工程网格化管理的目的和意义作为MySQL DBA#xff0c;相信大家对参数 Seconds_Behind_Master 并不陌生#xff0c;该字段的值可以通过 show slave status\G的输出#xff0c;表示主从延迟的时间#xff0c;单位为秒。监控主从延迟一般取这个值就足够了。0 表示无延迟#xff0c;理想状态该值不要超…
作为MySQL DBA相信大家对参数 Seconds_Behind_Master 并不陌生该字段的值可以通过 show slave status\G的输出表示主从延迟的时间单位为秒。监控主从延迟一般取这个值就足够了。0 表示无延迟理想状态该值不要超过1。如果业务场景中有写后读而且读的是从库那么就会对主从延迟要求非常高。 理解了该字段的含义大家有没有探究过该值是如何计算的相信大家都可以说出来 是从库的时间 减去 SQL_thread应用到的主库binlog event的时间戳。
今天从官方文档 和 MySQL源码 探寻正确的计算方法 MySQL官方文档如何解释
原文 翻译
Seconds_Behind_Master
该字段表示复制实例相对于主实例的“延迟” 当复制实例正在处理更新时该字段显示复制实例上当前时间戳与正在处理的事件在主实例上原始时间戳之间的差异。 当复制实例上没有正在处理的事件时该值为0。
基本上该字段测量复制实例的SQL线程和复制实例的I/O线程之间的秒数差异。如果主实例和复制实例之间的网络连接很快复制实例的I/O线程非常接近主实例因此该字段是复制实例的SQL线程相对于主实例的延迟的良好近似值。如果网络速度较慢这就不是一个良好的近似值复制实例的SQL线程可能经常追赶读取速度较慢的复制实例的I/O线程因此Seconds_Behind_Master经常显示为0即使I/O线程相对于主实例是延迟的。换句话说该列仅在快速网络中才有用。
即使主实例和复制实例的时钟时间不同只要在复制实例的I/O线程启动时计算的差异保持不变此时间差异计算就有效。任何更改包括NTP更新都可能导致时钟偏差使Seconds_Behind_Master的计算变得不太可靠。
在MySQL 5.7中如果复制实例的SQL线程未运行或者SQL线程已经消耗完中继日志并且复制实例的I/O线程未运行该字段为NULL未定义或未知。 在MySQL的早期版本中如果复制实例的SQL线程或复制实例的I/O线程未运行或未连接到主实例则该字段为NULL。如果I/O线程正在运行但中继日志用尽Seconds_Behind_Master设置为0。
Seconds_Behind_Master的值基于存储在事件中的时间戳这些事件通过复制进行保留。这意味着如果主实例M1本身是主实例M0的复制实例M1二进制日志中源自M0二进制日志的任何事件都具有M0该事件的时间戳。这使得MySQL能够成功地复制时间戳。然而对于Seconds_Behind_Master而言问题在于如果M1还直接从客户端接收更新那么Seconds_Behind_Master的值会随机波动因为M1的最后一个事件有时源自M0有时是M1上的直接更新的结果。
在使用多线程复制时您应该记住该值基于Exec_Master_Log_Pos因此可能不反映最近提交的事务的位置。
官方文档的翻译也有两种计算方法
方法一该字段显示复制实例上当前时间戳与正在处理的事件在主实例上原始时间戳之间的差异
方法二该字段测量复制实例的SQL线程和复制实例的I/O线程之间的秒数差异前提主实例和复制实例之间的网络连接很快复制实例的I/O线程非常接近主实例 源码中如何计算
在源码中全局搜索 Seconds_Behind_Master 关键字 排除测试文件出现Seconds_Behind_Master关键字的文件也就几个。找到关于计算Seconds_Behind_Master 源码。 注释中也给出了 计算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;elseprint NULL;}elsecompute Seconds_Behind_Master;}elseprint NULL;*/ // 伪代码计算 Seconds_Behind_Masterif (SQL 线程正在运行) {if (SQL 线程已处理所有可用的中继日志) {if (IO 线程正在运行) {输出 0; // I/O 线程正在运行但中继日志已用尽因此 Seconds_Behind_Master 设置为 0。} else {输出 NULL; // I/O 线程不在运行因此 Seconds_Behind_Master 为 NULL。}} else {计算 Seconds_Behind_Master; // 计算复制实例相对于主实例的延迟。}
} else {输出 NULL; // SQL 线程不在运行因此 Seconds_Behind_Master 为 NULL。
}真实代码 if (mi-rli-slave_running){/*Check if SQL thread is at the end of relay logChecking should be done using two conditionscondition1: compare the log positions andcondition2: 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);elseprotocol-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 possiblereasons 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 masters and slaves time are perfectly synchronized, andthat at slaves connection time, when the masters timestamp is read,it is at the very end of second 1, and (a very short time later) whenthe slaves timestamp is read it is at the very beginning of second2. Then the recorded value for master is 1 and the recorded value forslave is 2. At SHOW SLAVE STATUS time, assume that the differencebetween 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 dont go below 0: hence the max().last_master_timestamp 0 (an impossible timestamp 1970) is aspecial marker to say consider we have caught up.*/protocol-store((longlong)(mi-rli-last_master_timestamp ?max(0L, time_diff) : 0));}}else{protocol-store_null();}
具体计算方式 long time_diff ((long)(time(0) - mi-rli-last_master_timestamp)- mi-clock_diff_with_master);
这行代码计算了一个名为 time_diff 的长整型变量其值是当前时间通过 time(0) 获取与主实例上最后一个事件的时间戳mi-rli-last_master_timestamp之间的差异减去主从实例之间的时钟差异mi-clock_diff_with_master。这个 time_diff 的值表示当前时间与主实例最后一个事件的时间戳之间的秒数差异减去主从实例之间的时钟差异。 clock_of_slave - last_timestamp_executed_by_SQL_thread - clock_diff_with_master /*The difference in seconds between the clock of the master and the clock ofthe slave (second - first). It must be signed as it may be 0 or 0.clock_diff_with_master is computed when the I/O thread starts; for this theI/O thread does a SELECT UNIX_TIMESTAMP() on the master.how late the slave is compared to the master is computed like this:clock_of_slave - last_timestamp_executed_by_SQL_thread - clock_diff_with_master*//*主时钟和从属时钟之间的差异second - first。它必须是有符号的因为它可能 0 或 0。clock_diff_with_master 是在 I/O 线程启动时计算的为此I/O 线程在主实例上执行 SELECT UNIX_TIMESTAMP()。“从属相对于主实例的延迟”是这样计算的clock_of_slave - last_timestamp_executed_by_SQL_thread - clock_diff_with_master
*/参考
官方文档 Seconds_Behind_Master 解释
MySQL :: MySQL 5.7 Reference Manual :: 13.7.5.34 SHOW SLAVE STATUS Statement MySQL 复制延迟 Seconds_Behind_Master 究竟是如何计算的 - 知乎