【2019-10-08】阿里云RDS同步延迟原因与处理

2019年10月8日11:55:06 发表评论 1,334 热度

只读实例延迟介绍

RDS for MySQL只读实例通常用于分担主实例的查询压力,或者用于运行OLAP类型的分析应用,避免复杂统计查询对主实例的性能影响。
【2019-10-08】阿里云RDS同步延迟原因与处理

由于RDS只读实例采用MySQL原生的基于Binlog的复制技术(异步复制或半异步复制),必然会有延迟。延迟会导致只读实例与主实例的数据出现不一致,进而导致业务出现问题。另外延迟也有可能引起Binlog堆积,导致只读实例空间被迅速消耗(如果主实例当前正产生大量的Binlog),这种情况下有可能会使只读实例被锁定。

只读实例产生延迟的原因及解决方案

  • 只读实例规格过小

    分析

    这类延迟场景经常出现在只读实例规格和主实例规格相差较大,而且只读实例上负载较重,比如只读实例上IOPS打满。

    只读实例的数据为了和主实例保持同步,采用了MySQL原生的binlog复制技术,由一个IO线程和一个SQL线程来完成。IO线程负责将主实例的binlog拉取到只读实例,SQL线程负责将这些binlog日志应用到只读实例。这两个线程会消耗只读实例的IO资源,所以当只读实例的IOPS配置不够的时候,会导致只读实例的数据出现延迟。

    解决方案

    建议您升级只读实例规格,避免由于只读实例规格较小导致延迟。RDS推荐只读实例的配置大于或者等于主实例的配置。

  • 主实例的TPS(Transaction Per Second)过高

    分析

    由于只读实例与主实例同步采用的是单线程同步,而主实例的压力是并发多线程写入,这样在主实例TPS过高的情况下容易出现只读实例的数据延迟,可以通过观察只读实例的TPS与主实例的TPS性能数据来判断。

    解决方案

    排查主实例的TPS是否正常,如果正常则需要对业务进行优化或者拆分,保证主实例的TPS不会导致只读实例出现延迟。

  • 主实例的大事务

    分析

    主实例执行一个涉及数据量非常大的update、delete、insert…select、replace…select等事务操作,生成大量的binlog数据传送到只读实例。只读实例需要花费与主实例相同的时间来完成该事务,进而导致了只读实例的同步延迟。例如在主实例上执行一个持续80秒的删除操作,只读实例进行相同操作时也需要花费很长时间,这时就出现了延迟。

    在只读实例出现大事务导致延迟时,通过 show slave status \G命令,可以看到 Seconds Behind_Master不断变化,而 Exec_Master_Log_Pos却保持不变,这样可以判断只读实例的SQL线程在执行一个大的事务或者DDL操作。
    【2019-10-08】阿里云RDS同步延迟原因与处理

    解决方案

    建议将大事务拆分为小事务(例如在delete语句中增加where条件子句,限制每次删除的数据量,将一次删除操作拆分为多次数据量较小的删除操作进行),这样只读实例可以迅速的完成事务的执行,不会造成数据的延迟。

  • 主实例的DDL语句执行时间长

    分析

    • 只读实例和主实例数据同步是串行进行的,如果DDL操作在主实例执行时间很长,那么同样在只读实例也会消耗同样的时间导致延迟。常见操作例如create index、repair table、alter table add column等。
    • 只读实例上执行的查询或未完成的事务阻塞了来自主实例的DDL执行。在只读实例上执行show processlist命令查看SQL线程的状态为waiting for table metadata lock

    解决方案

    • 对于DDL直接引起的只读实例延迟,建议在业务低峰期执行这些DDL。
    • 对于来自主实例的DDL在只读实例上被阻塞的情况,需要kill掉只读实例上引起阻塞的会话来恢复只读实例和主实例的数据同步,详情请参见解决MDL锁导致无法操作数据库的问题

总结

当只读实例出现延迟的时候,排查方向如下:

  • 控制台查看监控,检查只读实例的IOPS,确认只读实例是否存在资源瓶颈。
  • 控制台查看监控,检查只读实例的MySQL_COMDML,确认主实例是否TPS过高。
  • 检查只读实例的binlog增长量,确定是否存在大事务。
  • 只读实例执行show slave status \G,确定是否有元数据锁。
  • 控制台查看SQL慢日志,是否有alter,repair,create等DDL操作。
  • 检查只读实例是否存在无主键表的删除或者更新操作,可以通过在只读实例执行show engine innodb status\G查看,或者执行show open tables后查看输出结果的in_use列里值为1的表。

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: