400 028 6601

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

MySQL中备库Seconds_Behind_Master计算的示例分析

这篇文章主要为大家展示了“MySQL中备库Seconds_Behind_Master计算的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“MySQL中备库Seconds_Behind_Master计算的示例分析”这篇文章吧。

创新互联长期为近千家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为岳西企业提供专业的成都网站设计、成都网站建设、外贸网站建设岳西网站改版等技术服务。拥有十载丰富建站经验和众多成功案例,为您定制开发。

背景

在mysql主备环境下,主备同步过程如下,主库更新产生binlog, 备库io线程拉取主库binlog生成relay log。备库sql线程执行relay log从而保持和主库同步。

MySQL中备库Seconds_Behind_Master计算的示例分析

理论上主库有更新时,备库都存在延迟,且延迟时间为备库执行时间+网络传输时间即t4-t2。

那么mysql是怎么来计算备库延迟的?

先来看show slave status中的一些信息,io线程拉取主库binlog的位置:

Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 107

sql线程执行relay log的位置:

 Relay_Log_File: slave-relay.000003 Relay_Log_Pos: 253

sql线程执行的relay log相对于主库binlog的位置:

Relay_Master_Log_File: mysql-bin.000001 Exec_Master_Log_Pos: 107

源码实现

Seconds_Behind_Master计算的源码实现如下:

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));
}

大致可以看出是通过时间和位点来计算的,下面详细分析下。

if里面条件表示如果io线程拉取主库binlog的位置和sql线程执行的relay log相对于主库binlog的位置相等,那么认为延迟为0。一般情况下,io线程比sql线程快。但如果网络状况特别差,导致sql线程需等待io线程的情况,那么这两个位点可能相等,会导致误认为延迟为0。

再看else里:

非并行复制:
备库sql线程读取了relay log中的event,event未执行之前就会更新last_master_timestamp,这里时间的更新是以event为单位。

rli->last_master_timestamp= ev->when.tv_sec + (time_t) ev->exec_time;

ev->when.tv_sec表示事件的开始时间。exec_time指事件在主库的执行时间,只有Query_log_event和Load_log_event才会统计exec_time。
另外一种情况是sql线程在等待io线程获取binlog时,会将last_master_timestamp设为0,按上面的算法Seconds_Behind_Master为0,此时任务备库是没有延迟的。

并行复制:

并行复制有一个分发队列gaq,sql线程将binlog事务读取到gaq,然后再分发给worker线程执行。并行复制时,binlog事件是并发穿插执行的,gaq中有一个checkpoint点称为lwm, lwm之前的binlog都已经执行,而lwm之后的binlog有些执行有些没有执行。
假设worker线程数为2,gap有1,2,3,4,5,6,7,8个事务。worker 1已执行的事务为1 4 6, woker 2执行的事务为2 3 ,那么lwm为4。

并行复制更新gap checkpiont时,会推进lwm点,同时更新last_master_timestamp为lwm所在事务结束的event的时间。因此,并行复制是在事务执行完成后才更新last_master_timestamp,更新是以事务为单位。同时更新gap checkpiont还受slave_checkpoint_period参数的影响。

这导致并行复制下和非并行复制统计延迟存在差距,差距可能为slave_checkpoint_period + 事务在备库执行的时间。这就是为什么在并行复制下有时候会有很小的延迟,而改为非并行复制时反而没有延迟的原因。

另外当sql线程等待io线程时且gaq队列为空时,会将last_master_timestamp设为0。同样此时认为没有延迟,计算得出seconds_Behind_Master为0。

位点信息维护

谈到位点更新就有必要说到两个事件:HEARTBEAT_LOG_EVENT 和 ROTATE_EVENT。

另外,在replicate_same_server_id为0时,备库接收到的binlog与主库severid相同时,备库会忽略此binlog,但位点仍然需要推进。为了效率,此binlog不需要记入relay log。而是替换为ROTATE_EVENT来推进位点。

延迟现象

初始主备是同步的,且没有任何更新。假设主备库执行某个DDL在都需要30s,执行某个大更新事务(例如insert..select * from )需要30s。

不考虑网络延迟。

MySQL中备库Seconds_Behind_Master计算的示例分析

相关bug

BUG#72376, PREVIOUS_GTIDS_LOG_EVENT 事件记录在每个binlog的开头,表示先前所有文件的gtid集合。relay-log本身event记录是主库的时间,但relay log开头的PREVIOUS_GTIDS_LOG_EVENT事件,是在slave端生成的,时间也是以slave为准的。因此不能用此时间计算last_master_timestamp。修复方法是在relay log写PREVIOUS_GTIDS_LOG_EVENT事件是标记是relay log产生的,在统计last_master_timestamp时,发现是relay产生的事件则忽略统计。

if (is_relay_log)
  prev_gtids_ev。set_relay_log_event();
   ...... if (!(ev->is_artificial_event()||...))
   rli->last_master_timestamp= ev->when。tv_sec + (time_t) ev->exec_time;

以上是“MySQL中备库Seconds_Behind_Master计算的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注创新互联行业资讯频道!


网页题目:MySQL中备库Seconds_Behind_Master计算的示例分析
地址分享:http://www.bluegullmedia.com/article/geiiss.html

其他资讯

让你的专属顾问为你服务

0.2782s