如何解决 MySQL 主从延时问题?

最近面试了十几个同学,关于 MySQL 主从延时问题,笔者一般都会问 。

  • MySQL 主从延时的原因是什么?
  • 具体哪个环节发生延时?
  • 如何解决呢?
对于这“三连问”,极少有同学能通关,甚至有同学连主从复制原理都不清楚 。
【如何解决 MySQL 主从延时问题?】这个并不是纯粹的八股文,因为在实际工作场景中,很多同学都遇到过 。
不多说,上文章目录 。
如何解决 MySQL 主从延时问题?

文章插图
一、什么是主从延时?
有时候我们遇到从数据库中获取不到信息的诡异问题时,会纠结于代码中是否有一些逻辑会把之前写入的内容删除,但是你又会发现,过了一段时间再去查询时又可以读到数据了 , 这基本上就是主从延迟在作怪 。
主从延迟 , 其实就是“从库回放” 完成的时间,与 “主库写 binlog” 完成时间的差值,会导致从库查询的数据,和主库的不一致 。
二、为什么会主从延时?
探讨这个问题前,我们需要知道主从复制的原理 。
1.主从复制原理
MySQL 的主从复制是依赖于 binlog,也就是记录 MySQL 上的所有变化并以二进制形式保存在磁盘上二进制日志文件 。
主从复制就是将 binlog 中的数据从主库传输到从库上,一般这个过程是异步的,即主库上的操作不会等待 binlog 同步地完成 。
如何解决 MySQL 主从延时问题?

文章插图
详细流程如下:
  • 主库写 binlog:主库的更新 SQL(update、insert、delete) 被写到 binlog;
  • 主库发送 binlog:主库创建一个 log dump 线程来发送 binlog 给从库;
  • 从库写 relay log:从库在连接到主节点时会创建一个 IO 线程,以请求主库更新的 binlog,并且把接收到的 binlog 信息写入一个叫做 relay log 的日志文件;
  • 从库回放:从库还会创建一个 SQL 线程读取 relay log 中的内容,并且在从库中做回放,最终实现主从的一致性 。
2.主从延时原因
我们分析一下主从复制的过程 。
MySQL 的主从复制都是单线程的操作,主库对所有 DDL 和 DML 产生 binlog,binlog 是顺序写,所以效率很高 。
Slave 的 Slave_IO_Running 线程会到主库取日志 , 放入 relay log,效率会比较高 。
Slave 的 Slave_SQL_Running 线程将主库的 DDL 和 DML 操作都在 Slave 实施,DML 和 DDL 的 IO 操作是随机的,不是顺序的,因此成本会很高 。
还可能是 Slave 上的其他查询产生 lock 争用,由于 Slave_SQL_Running 也是单线程的,所以一个 DDL 卡住了,需要执行 10 分钟,那么所有之后的 DDL 会等待这个 DDL 执行完才会继续执行,这就导致了延时 。
总结一下主从延迟的主要原因:主从延迟主要是出现在 “relay log 回放” 这一步,当主库的 TPS 并发较高,产生的 DDL 数量超过从库一个 SQL 线程所能承受的范围,那么延时就产生了,当然还有就是可能与从库的大型 query 语句产生了锁等待 。
三、如何解决主从延时?
1.主从延迟情况
我们先看看,哪些情况会导致主从延时:
  • 从库机器性能:从库机器比主库的机器性能差,只需选择主从库一样规格的机器就好 。
  • 从库压力大:可以搞了一主多从的架构,还可以把 binlog 接入到 Hadoop 这类系统,让它们提供查询的能力 。
  • 从库过多:要避免复制的从节点数量过多,从库数据一般以3-5个为宜 。
  • 大事务:如果一个事务执行就要 10 分钟,那么主库执行完后 , 给到从库执行 , 最后这个事务可能就会导致从库延迟 10 分钟啦 。日常开发中,不要一次性 delete 太多 SQL,需要分批进行,另外大表的 DDL 语句,也会导致大事务 。
  • 网络延迟:优化网络,比如带宽 20M 升级到 100M 。
  • MySQL 版本低:低版本的 MySQL 只支持单线程复制,如果主库并发高,来不及传送到从库 , 就会导致延迟,可以换用更高版本的 MySQL,支持多线程复制 。
2.主从延时解决方案
面试时 , 有些同学能回答出使用缓存、查询主库、提升机器配置等,仅仅这些么?
最容易想到的方法,缩短主从同步时间: