从innobackupex阻塞DDL谈到Seconds_Behind_master

134 阅读2分钟

1. 准备工作

测试版本: MySQL:5.7.19

innobackupex:innobackupex version 2.4.9 Linux (x86_64)

innobackupex备份期间会阻塞ddl操作,不管是先DDL还是先执行备份,这里简单模拟下执行DDL过程中,发生备份的情况。

session 1session 2session 3
begin;
select * from t limit 1;alter table t add col1 int;// 模拟执行时间超长的DDL,等待表t的mdl锁(blocked)
flush table with read lock// 模拟备份,等待表t的mdl锁(blocked)
commit;// 释放表t的锁Query OK, 0 rows affected (5 min 0.30 sec)Query OK, 0 rows affected (1 min 42.83 sec)
unlock tables;

加锁情况: a89858e07fb115251c2e6fbd84a49a5fa2cf0daf.png

2. 由此延伸

如果主库执行了一个时间超长的DDL操作,从库执行这个DDL期间发生了备份操作,会造成备份失败(xtrabackup检查机制),等待从库DDL执行完成后,会发现Seconds_Behind_master值变得很大。 这里看下Seconds_Behind_master的描述:发现,在网络通畅的情况下:

  • 每个事务的binlog里都有一个时间字段用于记录主库上写入的时间,备库读出当前正在执行的事务的时间字段的值,计算它与当前系统时间的差值;

  • 当前slave系统时间减去sql_thread最近接受到的binlog的timestamp,再减去master和slave的系统时间差,当值<0,处理成0;

  • IO或SQL线程为NO,或同时为NO,seconds_behind_master记为null(复制中断)

3. 一些想法

由此可见,单纯通过Seconds_Behind_master值取判断主从延迟有时并不靠谱,当发生网络阻塞,执行大的DDL,flush table with read lock等等情况下,当前relog已经被全部消费完,虽然Seconds_Behind_Master是0,而实际slave已经落后master很多。这种情况下,在主节点加一张心跳表,不停去更新时间字段,从节点判断这个时间与当前系统时间的差值,也算是可行的方法之一。

参考文档:

www.cnblogs.com/xuliuzai/p/…

www.mytecdb.com/blogDetail.…

www.cnblogs.com/gomysql/p/3…