在一个主备关系中,每个备库接收主库的binlog并执行。
正常情况下,只要主库执行更新生成的所有binlog,都可以传到备库并被正确执行,备库就能达到跟主库一致的状态,这就是最终一致性。
但MySQL要提供高可用能力,只有最终一致性还不够。为什么呢?
- MySQL主备切换流程–双M结构
主备延迟
主备切换可能是:
- 主动运维动作
比如软件升级、主库所在机器按计划下线等 - 被动操作
比如主库所在机器掉电。
同步延迟
与数据同步有关的时间点主要包括以下三个:
- 主库A执行完成一个事务,写入binlog,该时刻记为t1
- 之后传给备库B,备库B接收完该binlog的时刻记为t2
- 备库B执行完成该事务,该时刻记为t3
主备延迟,就是同一事务,在 备库执行完成的时间 和 主库执行完成的时间 之间的差值,即t3-t1。
可以在备库执行show slave status,它的返回结果会显示SBM(简称 SBM),表示当前备库延迟了多少s。
SBM 计算方法:
- 每个事务的binlog都有一一个时间字段,以记录主库上写入的时间
- 备库取出当前正在执行的事务的时间字段的值,计算它与当前系统时间的差值,得到SBM。
其实SBM就是t3-t1。所以,可以用SBM作为主备延迟的值,这个值的时间精度是s。
- 若主备库机器的系统时间设置不一致,不会导致主备延迟的值不准吗?
不会的。因为,备库连接到主库时,会通过执行SELECT UNIX_TIMESTAMP()函数获得当前主库系统时间。若此时发现主库系统时间与自己不一致,备库在执行SBM计算时,会自动扣掉该差值。
在网络正常时,日志从主库传给备库所需时间很短,即t2-t1非常小。即网络正常情况下,主备延迟的主要来源是备库接收完binlog和执行完该事务之间的时间差。
所以主备延迟最直接的表现是,备库消费中转日志(relay log)的速度,比主库生产binlog的速度要慢。这可能是由哪些原因导致的呢?
主备延迟的来源
备库所在机器的性能 < 主库所在的机器性能
部署的人会想,反正备库没有请求,所以可以用差点儿的机器。或把20个主库放在4台机器,而把备库集中在一台机器。
但更新请求对IOPS的压力,在主库和备库上是无差别的。所以,做这种部署时,一般都会将备库设置为“非双1”模式。
但实际上,更新过程中也会触发大量读操作。所以,当备库主机上的多个备库都在争抢资源时,就可能导致主备延迟。
这种部署现在少了。因为主备可能发生切换,备库随时可能变成主库,所以主备库必须选用相同规格机器,并且做对称部署。
我们也做了对称部署,但还有延迟,为啥?
很可能备库的压力大。主库既然提供了写能力,那么备库可以提供一些读能力。或一些运营后台需要的分析语句,不能影响正常业务,所以只能在备库上跑。
由于主库直接影响业务,大家使用起来会比较克制,反而忽视了备库的压力控制。结果备库上的查询耗费大量CPU,影响同步速度 =》主备延迟。
这时一般可以这么处理:
- 一主多从
除了备库外,可以多接几个从库,让这些从库来分担读压力。大多采用该方案,因为数据库系统必须保证有定期全量备份能力。而从库,很适合用来做备份。
- 通过binlog输出到外部系统
比如Hadoop,让外部系统提供统计类查询的能力。
从库和备库在概念上其实差不多。一般把会在HA过程中被选成新主库的,称为备库,其他的称为从库。
我们也采用了一主多从,保证备库压力不会超过主库,但还主备延迟,为啥?
可能就是大事务了。因为在主库,必须等事务执行完成才会写binlog,再传给备库。所以,若一个主库的语句执行10min,则该事务可能就会导致从库延迟10min。
delete一次性删除太多数据
比如,一些归档类数据,平时没有注意删除历史数据,等空间快满,SE要一次性删大量历史数据。又要避免在高峰期,所以会在
晚上执行这些大量数据删除。
结果,DBA半夜收到延迟报警。然后,DBA要求你后续再删数据时,要控制每个事务删除的数据量,分成多次删除。
大表DDL
计划内的DDL,建议使用gh-ost方案
我们主库也没大事务,怎么还主备延迟?
可能因为备库的并行复制能力。
其他情况
TODO。
由于主备延迟的存在,所以在主备切换时,就有不同