1. 准备工作
测试版本: MySQL:5.7.19
innobackupex:innobackupex version 2.4.9 Linux (x86_64)
innobackupex备份期间会阻塞ddl操作,不管是先DDL还是先执行备份,这里简单模拟下执行DDL过程中,发生备份的情况。
session 1 | session 2 | session 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; |
加锁情况:
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很多。这种情况下,在主节点加一张心跳表,不停去更新时间字段,从节点判断这个时间与当前系统时间的差值,也算是可行的方法之一。
参考文档: