MySQL主从复制延迟原因以及解决方案

 更新时间:2020年09月23日 08:42:31   作者:老叶茶馆  
这篇文章主要介绍了MySQL主从复制延迟原因以及解决方案,帮助大家更好的理解和使用数据库,感兴趣的朋友可以了解下

来源:公众号「神谕的暗影长廊」

在异步或半同步的复制结构中,从库出现延迟是一件十分正常的事。
虽出现延迟正常,但是否需要关注,则一般是由业务来评估。
如:从库上有需要较高一致性的读业务,并且要求延迟小于某个值,那么则需要关注。

简单概述一下复制逻辑:

1、主库将对数据库实例的变更记录到binlog中。
2、主库会有binlog dump线程实时监测binlog的变更并将这些新的events推给从库(Master has sent all binlog to slave; waiting for more updates
3、从库的IO Thread接收这些events,并将其记录入relaylog。
4、从库的SQL Thread读取relaylog的events,并将这些events应用(或称为重放)到从库实例。

上述为默认的异步复制逻辑,半同步复制又有些许不同,此处不再赘述。

此外,判断从库有延迟是十分简单的一件事:
在从库上通过SHOW SLAVE STATUS
检查Seconds_Behind_Master值即可。

产生延迟的原因及处理思路

〇 主库DML请求频繁(tps较大)

即主库写请求较多,有大量insert、delete、update并发操作,短时间产生了大量的binlog。

【原因分析】

主库并发写入数据,而从库SQL Thread为单线程应用日志,很容易造成relaylog堆积,产生延迟。

【解决思路】

做sharding,通过scale out打散写请求。或考虑升级到MySQL 5.7+,开启基于逻辑时钟的并行复制。

〇 主库执行大事务

比如大量导入数据,INSERT INTO $tb1 SELECT * FROM $tb2、LOAD DATA INFILE
比如UPDATEDELETE了全表等
Exec_Master_Log_Pos一直未变,Slave_SQL_Running_StateReading event from the relay log
分析主库binlog,看主库当前执行的事务也可知晓。

【原因分析】

假如主库花费200s更新了一张大表,在主从库配置相近的情况下,从库也需要花几乎同样的时间更新这张大表,此时从库延迟开始堆积,后续的events无法更新。

【解决思路】

拆分大事务,及时提交。

〇 主库对大表执行DDL语句

现象和主库执行大事务相近。
检查Exec_Master_Log_Pos一直未动,也有可能是在执行DDL。
分析主库binlog,看主库当前执行的事务也可知晓。

【原因分析】

1、DDL未开始,被阻塞,SHOW SLAVE STATUS检查到Slave_SQL_Running_Statewaiting for table metadata lock,且Exec_Master_Log_Pos不变。
2、DDL正在执行,SQL Thread单线程应用导致延迟增加。Slave_SQL_Running_Statealtering tableExec_Master_Log_Pos不变

【解决思路】

通过processlistinformation_schema.innodb_trx来找到阻塞DDL语句的查询,干掉该查询,让DDL正常在从库执行。
DDL本身造成的延迟难以避免,建议考虑:
① 业务低峰期执行
set sql_log_bin=0后,分别在主从库上手动执行DDL(此操作对于某些DDL操作会造成数据不一致,请务必严格测试)

〇 主库与从库配置不一致:

【原因分析】

硬件上:主库实例服务器使用SSD,而从库实例服务器使用普通SAS盘、cpu主频不一致等
配置上:如RAID卡写策略不一致,OS内核参数设置不一致,MySQL落盘策略不一致等

【解决思路】

尽量统一DB机器的配置(包括硬件及选项参数)
甚至对于某些OLAP业务,从库实例硬件配置高于主库等

〇 表缺乏主键或唯一索引

binlog_format=row的情况下,如果表缺乏主键或唯一索引,在UPDATEDELETE的时候可能会造成从库延迟骤增。
此时Slave_SQL_Running_StateReading event from the relay log
并且SHOW OPEN TABLES WHERE in_use=1的表一直存在。
Exec_Master_Log_Pos不变。
mysqld进程的cpu几近100%(无读业务时),io压力不大

【原因分析】

做个极端情况下的假设,主库更新一张500w表中的20w行数据,该update语句需要全表扫描
而row格式下,记录到binlog的为20w次update操作,此时SQL Thread重放将特别慢,每一次update可能需要进行一次全表扫描

【解决思路】

检查表结构,保证每个表都有显式自增主键,并建立合适索引。

〇 从库自身压力过大

【原因分析】

从库执行大量select请求,或业务大部分select请求被路由到从库实例上,甚至大量OLAP业务,或者从库正在备份等。
此时可能造成cpu负载过高,io利用率过高等,导致SQL Thread应用过慢。

【解决思路】

建立更多从库,打散读请求,降低现有从库实例的压力。

〇 MyISAM存储引擎

此时从库Slave_SQL_Running_StateWaiting for table level lock

【原因分析】

MyISAM只支持表级锁,并且读写不可并发操作。
主库在设置@@concurrent_insert对应值的情况下,能并发在select时执行insert,但从库SQL Thread重放时并不可并发,有兴趣可以再去看看myisam这块的实现。

【解决思路】

当然是选择原谅它了,既然选择了MyISAM,那么也应该要有心理准备。(还存在其他场景,也不推荐MyISAM在复制结构中使用)
改成InnoDB吧。

总结:

通过SHOW SLAVE STATUSSHOW PROCESSLIST查看现在从库的情况。(顺便也可排除在从库备份时这种原因)
Exec_Master_Log_Pos不变,考虑大事务、DDL、无主键,检查主库对应的binlog及position即可。
Exec_Master_Log_Pos变化,延迟逐步增加,考虑从库机器负载,如io、cpu等,并考虑主库写操作与从库自身压力是否过大。

如果上述原因都没有,那么请教请教DBA大佬们吧。

当然,Seconds_Behind_Master也不一定准确,存在在少部分场景下,虽Seconds_Behind_Master为0,但主从数据不一致的情况。
这将是另一篇博文了。

全文完。

以上就是MySQL主从复制延迟原因以及解决方案的详细内容,更多关于MySQL主从复制延迟的资料请关注脚本之家其它相关文章!

相关文章

  • MySQL之范式的使用详解

    MySQL之范式的使用详解

    这篇文章主要介绍了MySQL之范式的使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • mysql 日期和时间函数

    mysql 日期和时间函数

    这里是一个使用日期函数的例子。下面的查询选择所有 date_col 值在最后 30 天内的记录。
    2009-11-11
  • MySQL8.0版本如何正确的使用窗口函数详解

    MySQL8.0版本如何正确的使用窗口函数详解

    MySQL 8.0引入的窗口函数,增强了数据分析能力,窗口函数允许对数据集(窗口)进行操作,与GROUPBY类似,但每个查询行生成独立结果,包括聚合函数如SUM、AVG,专用窗口函数如ROW_NUMBER等,窗口函数应用于数据分组、排序、排名,并支持复杂分析场景,需要的朋友可以参考下
    2024-11-11
  • MySQL学习之事务与并发控制

    MySQL学习之事务与并发控制

    这篇文章主要介绍了MySQL中的事务与并发控制,一个事务可以理解为一组操作,这一组操作要么全部执行,要么全部不执行,想了解更多的小伙伴,可以参考阅读本文
    2023-03-03
  • mysql的binlog三种配置模式小结

    mysql的binlog三种配置模式小结

    本文主要介绍了mysql的binlog三种配置模式小结,主要是binlog_format的值有3个选项,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-07-07
  • MySQL使用MRG_MyISAM(MERGE)实现分表后查询的示例

    MySQL使用MRG_MyISAM(MERGE)实现分表后查询的示例

    这篇文章主要介绍了MySQL使用MRG_MyISAM(MERGE)实现分表后查询的示例,帮助大家更好的理解和使用MySQL数据库,感兴趣的朋友可以了解下
    2020-12-12
  • Windows mysql 双向同步设置方法 详细篇

    Windows mysql 双向同步设置方法 详细篇

    如果你需要windows mysql 主、备机双向同步环境,可按照以下步骤进行操作
    2011-05-05
  • Mysql中调试存储过程最简单的方法

    Mysql中调试存储过程最简单的方法

    以前同事告诉我用临时表插入变量数据来查看,但是这种方法过于麻烦,而且Mysql没有比较好的调试存储过程的工具。今天google了下发现可以用select + 变量名的方法来调试
    2021-06-06
  • MySQL中建表与常见的类型设计陷阱详解

    MySQL中建表与常见的类型设计陷阱详解

    这篇文章详细讲解了MySQL的建表语句、以及表结构的设计规范和陷阱,并对网络上常见的资料给出的设计方案。文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2022-11-11
  • 解决xmapp启动mysql出现Error: MySQL shutdown unexpectedly.问题

    解决xmapp启动mysql出现Error: MySQL shutdown unexpec

    这篇文章主要介绍了解决xmapp启动mysql出现Error: MySQL shutdown unexpectedly.问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06

最新评论