读mysql45讲-主备延迟

本文深入探讨了MySQL主备延迟的产生原因,包括备库性能、大事务、并行复制能力等因素。分析了主备切换的可靠性优先和可用性优先两种策略,强调在数据可靠性与可用性之间的权衡。同时,讨论了不同binlog_format对数据一致性的影响,并提出了应对主备延迟的优化措施。
摘要由CSDN通过智能技术生成

正常在主库中执行完的事务会被写入到binlog中,然后通过线程发送给备库,备库解析出binlog日志再执行,来保证数据的一致性,其中与数据同步的有关的时间点有三个:

  1. 主库A执行完一个事务,并且写入到binlog中,这个称为时刻T1
  2. 写完的binlog传输给备库,备库接收到binlog文件,这个称为时刻T2
  3. 备库开始执行binlog日志的解析结果,执行完的这个时刻称为时刻T3

所谓的主备延迟就是同一个事务,在备库执行完成的时间和在主库中执行完的时间的差值,也就是上面的T3-T1。

在备库上执行show slave statue命令,会显示seconds_behind_master,用于显示当前备库延迟了多少秒。

seconds_behind_master的计算方式如下:

  1. 每个事务的binlog都会记录一个时间字段,用来表明主库上开始写入的时间。
  2. 备库取出这个时间字段,计算和当前系统的时间的差值,就是seconds_behind_master

如果主库和备库的系统时间不一样,备库在连接到主库的时候,会通过SELECTUNIX_TIMESTAMP()函数来获取当前时间主库上的时间,如果主库的时间和备库的时间不一致,在计算seconds_behind_master的时候会扣掉这个差值。

主备延迟的最主要来源是备库接收到binlog和执行完binlog记录的事务之间的时间差,也就是T3-T2,最直接的表现就是备库消费中专日志(relay log)的速度比不上主库发送到备库的binlog的速度。

主备延迟的来源

备库的性能比不上主库
备库的压力大

通常情况下会将一些查询语句分配到备库上执行,如果对备库的查询没有做控制,会导致对备库的查询压力很大,耗费CPU资源,从而会影响到同步速度,导致了主备延迟。
这种情况可以通过一主多从的方式,也就是除了备库之外,多连接几个从库,分担压力。

大事务

因为主库将binlog传输给备库的前提是主库需要写完事务,如果一个事务在主库上写完需要10分钟,那从主库写入到备库写入肯定就是超过10分钟的。

常见的业务背景是,一些归档类的数据,平时没有删除数,一直到了空间不够用的时候才来删除旧数据。这个时候如果用delete来一次性的删除大量数据就会很慢。

还有就是大表的DDL也会出现这个情况。

备库的并行复制能力

因为主备延迟的存在,所以在主备切换的时候就会有不同的策略。

可靠性优先策略

在双M的结构下,进行主备切换的过程大致如下:

  1. 判断备库的seconds_behind_master,如果小于某个定义好的指(5s),那就开始下一步;否则就继续重试这一步。
  2. 把主库A改成只读状态,也即是readonly=true
  3. 判断备库B的seconds_behind_master的值,直到这个值等于0为止。
  4. 把备库B的状态改为可读写,也即是readonly=false
  5. 把业务请求切换到库B

在这一系列的步骤中,是有一段时间中数据库是不可用状态的。在步骤2和步骤5之间,数据库都是只读状态的。

在这个不可用状态中,比较耗费时间的是步骤3,可能需要耗费好几秒的时间。这也是为什么需要在步骤1先做判断,确保seconds_behind_master的值足够小。

试想如果一开始主备延迟就长达30分钟,而不先做判断直接切换的话,系统的不可用时间就会 长达30分钟,这种情况一般业务都是不可接受的。

可用性优先策略

如果强行把步骤4和步骤5调整到最开始执行,也就是说不等数据同步之后就直接让业务端操作备库B,那基本上就没有数据库不可用时间了。但是这个操作可能会出现数据不一致的情况。

使用可用性策略,并且binlog_format=mixed,假设现在的主备延迟是5s:

  1. 主库A执行完一个事务并且写完binlog,这个时候新开启了一个事务insert(4,4),之后进行主备切换。
  2. 因为主备延迟5s的影响,所以备库B还没消费insert(4,4)这个中转日志的时候,备库B已经切换为主库,可以进行读写,如果这个时候需要插入insert(5,5)。
  3. 备库B插入之后,将操作insert(5,5)对应的binlog也发给主库A。
  4. insert语句都假设是不带主键的,主键自增的。那备库B将主库发过来的insert(4,4)执行完,主库A执行备库发过来的insert(5,5);两行数据在两个数据库中的主键都是不一样的,就出现了数据不一致的情况。

如果使用可用性优先策略,并且binlog_format=row会出现这个情况么?

因为row格式在记录binlog的时候,会记录新插入的行的所有字段值,所以最后只会有一行不一致。而且,两边的主备同步的应用线程会报错duplicate keyerror并停止。也就是说,这种情况下,备库B的(5,4)和主库A的(5,5)这两行数据,都不会被对方执行。

1.使用row格式的binlog时,数据不一致的问题更容易被发现。而使用mixed或者statement格 式的binlog时,数据很可能悄悄地就不一致了。如果你过了很久才发现数据不一致的问题, 很可能这时的数据不一致已经不可查,或者连带造成了更多的数据逻辑不一致。

2.主备切换的可用性优先策略会导致数据不一致。因此,大多数情况下,我都建议你使用可靠 性优先策略。毕竟对数据服务来说的话,数据的可靠性一般还是要优于可用性的。

在满足数据可靠性的前提下,MySQL高可用系统的可用性,是依赖于主备延迟的。延迟的时间越小,在主库故障的时候,服务恢复需要的时间就越短,可用性就越高

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值