详解MySQL的Seconds_Behind_Master


Posted in MySQL onMay 18, 2021

Seconds_Behind_Master

对于mysql主备实例,seconds_behind_master是衡量master与slave之间延时的一个重要参数。通过在slave上执行"show slave status;"可以获取seconds_behind_master的值。

原始实现

Definition:The number of seconds that the slave SQL thread is behind processing the master binary log.

Type:time_t(long)

计算方式如下:

rpl_slave.cc::show_slave_status_send_data()
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);
     protocol->store(
         (longlong)(mi->rli->last_master_timestamp ? max(0L, time_diff) : 0));
   }

主要分为以下两种情况:

  • SQL线程等待IO线程获取主机binlog,此时seconds_behind_master为0,表示备机与主机之间无延时;
  • SQL线程处理relay log,此时seconds_behind_master通过(long)(time(0) ? mi->rli->last_master_timestamp) ? mi->clock_diff_with_master计算得到;

last_master_timestamp

定义:

主库binlog中事件的时间。

type: time_t (long)

计算方式:

last_master_timestamp根据备机是否并行复制有不同的计算方式。

非并行复制:

rpl_slave.cc:exec_relay_log_event()
if ((!rli->is_parallel_exec() || rli->last_master_timestamp == 0) &&
    !(ev->is_artificial_event() || ev->is_relay_log_event() ||
     (ev->common_header->when.tv_sec == 0) ||
     ev->get_type_code() == binary_log::FORMAT_DESCRIPTION_EVENT ||
     ev->server_id == 0))
{
 rli->last_master_timestamp= ev->common_header->when.tv_sec +
                             (time_t) ev->exec_time;
 DBUG_ASSERT(rli->last_master_timestamp >= 0);
}

在该模式下,last_master_timestamp表示为每一个event的结束时间,其中when.tv_sec表示event的开始时间,exec_time表示事务的执行时间。该值的计算在apply_event之前,所以event还未执行时,last_master_timestamp已经被更新。由于exec_time仅在Query_log_event中存在,所以last_master_timestamp在应用一个事务的不同event阶段变化。以一个包含两条insert语句的事务为例,在该代码段的调用时,打印出event的类型、时间戳和执行时间

create table t1(a int PRIMARY KEY AUTO_INCREMENT ,b longblob) engine=innodb;
begin;
insert into t1(b) select repeat('a',104857600);
insert into t1(b) select repeat('a',104857600);
commit;

10T06:41:32.628554Z 11 [Note] [MY-000000] [Repl] event_type: 33 GTID_LOG_EVENT

2020-02-10T06:41:32.628601Z 11 [Note] [MY-000000] [Repl] event_time: 1581316890

2020-02-10T06:41:32.628614Z 11 [Note] [MY-000000] [Repl] event_exec_time: 0

2020-02-10T06:41:32.628692Z 11 [Note] [MY-000000] [Repl] event_type: 2   QUERY_EVENT

2020-02-10T06:41:32.628704Z 11 [Note] [MY-000000] [Repl] event_time: 1581316823

2020-02-10T06:41:32.628713Z 11 [Note] [MY-000000] [Repl] event_exec_time: 35

2020-02-10T06:41:32.629037Z 11 [Note] [MY-000000] [Repl] event_type: 19   TABLE_MAP_EVENT

2020-02-10T06:41:32.629057Z 11 [Note] [MY-000000] [Repl] event_time: 1581316823

2020-02-10T06:41:32.629063Z 11 [Note] [MY-000000] [Repl] event_exec_time: 0

2020-02-10T06:41:33.644111Z 11 [Note] [MY-000000] [Repl] event_type: 30    WRITE_ROWS_EVENT

2020-02-10T06:41:33.644149Z 11 [Note] [MY-000000] [Repl] event_time: 1581316823

2020-02-10T06:41:33.644156Z 11 [Note] [MY-000000] [Repl] event_exec_time: 0

2020-02-10T06:41:43.520272Z 0 [Note] [MY-011953] [InnoDB] Page cleaner took 9185ms to flush 3 and evict 0 pages

2020-02-10T06:42:05.982458Z 11 [Note] [MY-000000] [Repl] event_type: 19   TABLE_MAP_EVENT

2020-02-10T06:42:05.982488Z 11 [Note] [MY-000000] [Repl] event_time: 1581316858

2020-02-10T06:42:05.982495Z 11 [Note] [MY-000000] [Repl] event_exec_time: 0

2020-02-10T06:42:06.569345Z 11 [Note] [MY-000000] [Repl] event_type: 30    WRITE_ROWS_EVENT

2020-02-10T06:42:06.569376Z 11 [Note] [MY-000000] [Repl] event_time: 1581316858

2020-02-10T06:42:06.569384Z 11 [Note] [MY-000000] [Repl] event_exec_time: 0

2020-02-10T06:42:16.506176Z 0 [Note] [MY-011953] [InnoDB] Page cleaner took 9352ms to flush 8 and evict 0 pages

2020-02-10T06:42:37.202507Z 11 [Note] [MY-000000] [Repl] event_type: 16    XID_EVENT

2020-02-10T06:42:37.202539Z 11 [Note] [MY-000000] [Repl] event_time: 1581316890

2020-02-10T06:42:37.202546Z 11 [Note] [MY-000000] [Repl] event_exec_time: 0

并行复制:

rpl_slave.cc   mts_checkpoint_routine
ts = rli->gaq->empty()
          ? 0
          : reinterpret_cast<Slave_job_group *>(rli->gaq->head_queue())->ts;
 rli->reset_notified_checkpoint(cnt, ts, true);
 /* end-of "Coordinator::"commit_positions" */

在该模式下备机上存在一个分发队列gaq,如果gaq为空,则设置last_commit_timestamp为0;如果gaq不为空,则此时维护一个checkpoint点lwm,lwm之前的事务全部在备机上执行完成,此时last_commit_timestamp被更新为lwm所在事务执行完成后的时间。该时间类型为time_t类型。

ptr_group->ts = common_header->when.tv_sec +
                   (time_t)exec_time;  // Seconds_behind_master related
rli->rli_checkpoint_seqno++;
if (update_timestamp) {
 mysql_mutex_lock(&data_lock);
 last_master_timestamp = new_ts;
 mysql_mutex_unlock(&data_lock);
}

在并行复制下,event执行完成之后才会更新last_master_timestamp,所以非并行复制和并行复制下的seconds_behind_master会存在差异。

clock_diff_with_master

定义:

  • The difference in seconds between the clock of the master and the clock of the 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 the I/O thread does a SELECT UNIX_TIMESTAMP() on the master.
  • type: long
rpl_slave.cc::get_master_version_and_clock()
if (!mysql_real_query(mysql, STRING_WITH_LEN("SELECT UNIX_TIMESTAMP()")) &&
     (master_res= mysql_store_result(mysql)) &&
     (master_row= mysql_fetch_row(master_res)))
 {
   mysql_mutex_lock(&mi->data_lock);
   mi->clock_diff_with_master=
     (long) (time((time_t*) 0) - strtoul(master_row[0], 0, 10));
   DBUG_EXECUTE_IF("dbug.mts.force_clock_diff_eq_0",
     mi->clock_diff_with_master= 0;);
   mysql_mutex_unlock(&mi->data_lock);
 }

该差值仅被计算一次,在master与slave建立联系时处理。

其他

exec_time

定义:

  • the difference from the statement's original start timestamp and the time at which it completed executing.
  • type: unsigned long
struct timeval end_time;
ulonglong micro_end_time = my_micro_time();
my_micro_time_to_timeval(micro_end_time, &end_time);
exec_time = end_time.tv_sec - thd_arg->query_start_in_secs();

时间函数

(1)time_t time(time_t timer) time_t为long类型,返回的数值仅精确到秒;

(2)int gettimeofday (struct timeval *tv, struct timezone *tz) 可以获得微秒级的当前时间;

(3)timeval结构

#include <time.h>
stuct timeval {
   time_t tv_sec; /*seconds*/
   suseconds_t tv_usec; /*microseconds*/
}

总结

使用seconds_behind_master衡量主备延时只能精确到秒级别,且在某些场景下,seconds_behind_master并不能准确反映主备之间的延时。主备异常时,可以结合seconds_behind_master源码进行具体分析。

以上就是详解MySQL的Seconds_Behind_Master的详细内容,更多关于MySQL Seconds_Behind_Master的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
MySQL复制问题的三个参数分析
Apr 07 MySQL
MySQL的join buffer原理
Apr 29 MySQL
MySQL创建高性能索引的全步骤
May 02 MySQL
MySQL 分组查询的优化方法
May 12 MySQL
MySQL官方导出工具mysqlpump的使用
May 21 MySQL
mysql联合索引的使用规则
Jun 23 MySQL
Mysql数据库按时间点恢复实战记录
Jun 30 MySQL
mysql中整数数据类型tinyint详解
Dec 06 MySQL
解析MySQL索引的作用
Mar 03 MySQL
MySQL事务的隔离级别详情
Jul 15 MySQL
MySQL数据管理操作示例讲解
Dec 24 MySQL
MySQL优化之如何写出高质量sql语句
May 17 #MySQL
mysql数据库入门第一步之创建表
MySQL 隔离数据列和前缀索引的使用总结
May 14 #MySQL
MySQL 使用自定义变量进行查询优化
May 14 #MySQL
MySQL 逻辑备份与恢复测试的相关总结
May 14 #MySQL
MySQL 可扩展设计的基本原则
May 14 #MySQL
MySQL主从搭建(多主一从)的实现思路与步骤
May 13 #MySQL
You might like
SESSION信息保存在哪个文件目录下以及能够用来保存什么类型的数据
2012/06/17 PHP
php 模拟POST提交的2种方法详解
2013/06/17 PHP
PHP array_multisort() 函数的深入解析
2013/06/20 PHP
PHP设置一边执行一边输出结果的代码
2013/09/30 PHP
joomla数据库操作示例代码
2016/01/06 PHP
PHP中in_array的隐式转换的解决方法
2018/03/06 PHP
JS实多级联动下拉菜单类,简单实现省市区联动菜单!
2007/05/03 Javascript
extjs_02_grid显示本地数据、显示跨域数据
2014/06/23 Javascript
jQuery实现的网格线绘制方法
2016/06/20 Javascript
深入浅出ES6新特性之函数默认参数和箭头函数
2016/08/01 Javascript
微信开发 消息推送实现代码
2016/10/21 Javascript
vue如何引用其他组件(css和js)
2017/04/13 Javascript
微信小程序选择图片和放大预览图片功能
2017/11/02 Javascript
使用VUE+iView+.Net Core上传图片的方法示例
2019/01/04 Javascript
解决layer弹出层自适应页面大小的问题
2019/09/16 Javascript
webpack中的模式(mode)使用详解
2020/02/20 Javascript
[04:26]DOTA2上海特锦赛小组赛第二日 TOP10精彩集锦
2016/02/27 DOTA
Python函数中定义参数的四种方式
2014/11/30 Python
Sanic框架配置操作分析
2018/07/17 Python
python3.6的venv模块使用详解
2018/08/01 Python
python爬虫租房信息在地图上显示的方法
2019/05/13 Python
Ubuntu下Python+Flask分分钟搭建自己的服务器教程
2019/11/19 Python
详解Python中第三方库Faker
2020/09/25 Python
德国EGOIST网店:销售畅销的设计师品牌
2017/04/18 全球购物
计算机应用与科学个人的自我评价
2013/11/15 职场文书
业务主管岗位职责范本
2013/12/25 职场文书
迟到检讨书400字
2014/01/13 职场文书
医学生求职自荐书
2014/06/12 职场文书
学校会议通知范文
2015/04/15 职场文书
2015年公司国庆放假通知
2015/07/30 职场文书
安全生产隐患排查制度
2015/08/05 职场文书
Golang实现AES对称加密的过程详解
2021/05/20 Golang
MySQL 重命名表的操作方法及注意事项
2021/05/21 MySQL
Python OpenCV 彩色与灰度图像的转换实现
2021/06/05 Python
redis不能访问本机真实ip地址的解决方案
2021/07/07 Redis
vue 数字翻牌器动态加载数据
2022/04/20 Vue.js