MySQL主备延迟的原因
在上篇文章中记录了一次由主备延迟导致的relay log打满磁盘的问题,结合林奇大佬的《MySQL是怎么保证高可用的?》,分析一下主备延迟的原因。
主备同步
主库和备库之间的同步流程如图所示:
- 在备库B 上通过change master命令,设置主库A的IP、端口、用户名、密码,以及要从哪个位置开始请求binlog,这个位置包含文件名和日志偏移量。
- 在备库B 上执行start slave命令,此时备库会启动两个线程,io_thread和 sql_thread。其中io_thread负责与主库建立连接。
- 主库A校验完用户名、密码后, 开始按照备库B 传过来的位置,从本地读取binlog,发给B。
- 备库B拿到binlog后,写到本地文件,称为中转日志(relay log)。
- sql_thread 读取中转日志,解析出日志里的命令,回放执行。
主备延迟
与数据同步相关的时间点主要包括以下三个:
- 主库A执行完成一个事务,写入binlog, 记为T1
- 传给备库B,B接收完这个binlog的时刻为T2
- 备库B 执行完这个事务,T3
主备延迟:同一个事务,在备库执行完成的时间和主库执行完成的时间之间的差值,T3-T1。
可以通过 执行:
SHOW SLAVE STATUS
查看seconds_behind_master,用于表示当前备库延迟了多少秒。
主备延迟的一个直观表现就是:备库中relay log被消费的速度远小于主库生成binlog的速度, 就会导致备库中relay log的积压,最后打满磁盘。
主备延迟的原因
- 早期,备库所在机器的性能和主库的性能不一致,导致备库处理relay log跟不上主库生成binlog的速度。现在基本主备的机器都一样,而且是对称部署。
- 备库压力过大, 主库负责写, 备库除了承担读的工作,还会执行一些后台运营的分析语句,但是实际工作中,大家对于主库的使用都很克制, 反而忽视了备库的压力控制,结果就是备库上的资源压力很大,影响了主备同步。
- 应对措施: 采用一主多从的架构,就是有多个从库分担备库的压力,另外数据库需要定期全量备份数据,从库适合数据备份。
- 采取了一主多从的架构,还是会出现主备延迟,一般有两大原因:
-
大事务, 根据同步的流程,主库执行完一个事务花费10分钟,然后再写入binlog,传给备库,备库在此期间只能等待10分钟。典型场景:一次性使用delete语句 删除大量数据。
下图是产生问题的备库中relay log的大小,基本都是大事务。
-
DDL,在DDL期间,在mysql 5.5版本之前会阻塞DML,使用Online DDL也会因为需要扫描原表数据和构建临时文件,都是非常耗时的操作。
-
总结
为了设计一个高可用的系统, MySQL引入了主备切换的机制,在主库出现问题时可以快速切换到备库提供服务。但是为了维持主备库之间数据的一致性的同步机制,又带来了新的问题,主备延迟。主备延迟带来的后果是多方面的,比如会反过来影响数据的一致性和可用性,relaylog的积压等等问题。