【MySQL】请不要用SECONDS_BEHIND_MASTER来衡量MySQL主备的延迟时间

关于SECONDS_BEHIND_MASTER:

这个参数在我们使用show slave status的时候会看到,这个参数可用于参考从库同步主库的一个进度,当为0时,可认为主从数据已完全同步,但需要注意的是,这个参数只适合作为一个参考,并不能完全依赖这个参数判断从库进度是否已追上了主库,说白了,不要用SECONDS_BEHIND_MASTER来衡量MYSQL主备的延迟时间

曾有网友遇到过以下场景:
Seconds_Behind_Master 为 0 , 备库的 show slave status 显示 IO/SQL 线程都是正常的 , MySQL 的主库上的变更却长时间无法同步到备库上。如果没有人为干预,直到一个小时以后(可设置重连时间), MySQL 才会自动重连主库,继续复制主库的变更。

而这个问题的影响范围是:MySQL , Percona , MariaDB 的所有版本。

这个问题遇到的概率并不高,但还是有必要记录一下。

一、问题重现步骤:

搭建主备的复制,临时断开主库的网络,并 kill 掉主库 MySQL 的 binlog dump 线程。
此时观察备库的复制情况, show slave status 中:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0
但是此时你把网络恢复以后,在主库做任何变更,备库都无法获得数据更新了。而且备库上的show slave status 显示: IO 线程 SQL 线程一切正常,复制延迟一直是 0 。
一切正常,普通的监控软件都不会发现备库有数据延迟。

原理分析:

MySQL 的 Replication 是区别于其他数据库很关键的地方。也是可扩展性和高可用的基础。它本身已经非常智能化,只需要我们调用 Change Master 指定 Binlog 文件名和偏移位置就可以搭建从主库到备库的复制关系。
MySQL 复制 线程 会自动将目前复制位置记录下来,在主备复制中断的时候自动连上主库,并从上次中断的位置重新开始复制。这些操作都是全自动化的。

关于MySQL主从是“推”还是“拉”
首先说明一下,MySQL主从是使用“推”的方式实现的:
关于推拉说明:
推:主库上数据更新时,将消息推送给从库,然后从库再进行更新
拉:从库会通过轮询的方式不断查询主库是否更新了数据,资源消耗巨大

问题分析:

当我们kill掉主库的进程的时候,主库就不能向从库推送数据消息,导致从库一直收不到数据消息而不会更新数据,从库如果长时间没有收到主库发过来的变更,,从库会每隔一段时间重连主库

问题避免:

修改延迟的监控方法:
正确设置:--master-connect-retry ,--slave-net-timeout ,--master_heartbeat_period重试参数

slave_net_timeout:
MySQL主从复制的时候, 当Master和Slave之间的网络中断,但是Master和Slave无法察觉的情况下(比如防火墙或者路由问题)。Slave会等待slave_net_timeout设置的秒数后,才能认为网络出现故障,然后才会重连并且追赶这段时间主库的数据。

备库过了 slave-net-timeout 秒还没有收到主库来的数据,它就会开始第一次重试。然后每过 master-connect-retry 秒,备库会再次尝试重连主库,直到--master-retry-count次后才结束。

--master-retry-count(该参数在mysql5.6.1及其后续版本废除)。MASTER_RETRY_COUNT = 0表示重连次数无限制。

master_heartbeat_period参数:
设置复制心跳的周期,取值范围为0 到 4294967秒。精确度可以达到毫秒,最小的非0值是0.001秒。心跳信息由master在主机binlog日志文件在设定的间隔时间内没有收到新的事件时发出,以便slave知道master是否正常。
slave连接到master后,该参数可通过mysql.slave_master_info表查看。

slave_net_timeout 的默认是 3600,也就是一小时。也就是说,在之前的情况下,Slave 要延误 1 小时后才会尝试重连。而在没有设置 master_heartbeat_period 时,将 slave_net_timeout 设得很短会造成 Master 没有数据更新时频繁重连。

mysql> stop slave;  
mysql> change master to master_heartbeat_period = 10;  
mysql> set global slave_net_timeout = 25;  
mysql> start slave;  

Master 在没有数据的时候,每 10 秒发送一个心跳包。这样 Slave 就能知道 Master 是不是还正常

mysql> show status like 'slave%';  
+----------------------------+---------------------+  
| Variable_name              | Value               |  
+----------------------------+---------------------+  
| Slave_heartbeat_period     | 10.000              |  
| Slave_last_heartbeat       | 2015-01-08 10:28:16 |  
| Slave_open_temp_tables     | 0                   |  
| Slave_received_heartbeats  | 1645                |  
| Slave_retried_transactions | 0                   |  
| Slave_running              | ON                  |  
+----------------------------+---------------------+  

参考文章:
http://chenxy.blog.51cto.com/729966/1361558
http://blog.csdn.net/JesseYoung/article/details/42914577

你可能感兴趣的:(【MySQL】请不要用SECONDS_BEHIND_MASTER来衡量MySQL主备的延迟时间)