MySQL-如何解决主备延迟
主备延迟
如何查询主备延迟时间?
在备库上执行 show slave status 命令,它的返回结果里面会显示seconds_behind_master,用于表示当前备库延迟了多少秒。
seconds_behind_master 的计算方法是这样的:
- 每个事务的 binlog 里面都有一个时间字段,用于记录主库上写入的时间;
- 备库取出当前正在执行的事务的时间字段的值,计算它与当前系统时间的差值,得到seconds_behind_master。
如果主备库机器的系统时间设置不一致,会不会导致主备延迟的值不准?
其实不会的。因为,备库连接到主库的时候,会通过执行 SELECT UNIX_TIMESTAMP() 函数来获得当前主库的系统时间。如果这时候发现主库的系统时间与自己不一致,备库在执行seconds_behind_master 计算的时候会自动扣掉这个差值。
在网络正常的时候,日志从主库传给备库所需的时间是很短的。主备延迟最直接的表现是,备库消费中转日志(relay log)速度,比主库生产binlog 的速度要慢。
典型的主备延迟案例
产生主备延迟的根本原因是备库上消费 binlog 的速度赶不上主库产生 binlog 的速度。
- 备库所在机器的性能要比主库所在的机器性能差。
- 备库的压力大 例如有些像运维、订单等统计分析在备机上跑
- 即大事务
- 大表 DDL
- 备库的并行复制能力
主备延迟的排查之路
网络
网络可能导致主备延迟的问题,比如主库或者备库的带宽满负载、主备之间网络延迟很大,有可能会导致主库的 binlog 没有全量传输到备库,造成延迟。
备库机器性能
备库 使用了烂机器? 比如主库使用了 SSD,而备库使用的是 SATA。
备库 高负载? 可能在备库上做统计分析,导致备库的负载很高。可使用 top 命令进行排查。
备库 磁盘有问题? 磁盘、raid卡、调度策略有问题的情况下,有的时候会出现单个IO延迟很高的情况。可使用 iostat 查看 IO 运行情况。
大事务
因为主库上必须等事务执行完成才会写入 binlog,再传给备库。所以,如果一个主库上的语句执行 10 分钟,那这个事务很可能就会导致从库延迟 10 分钟。
可通过 processlist 命令查看相关信息,或者使用 mysqlbinlog 查看 binlog 中的 SQL 就能快速确认。
锁
锁冲突问题也可能导致备库的 SQL 线程执行慢。比如一些 select … for update 的 SQL。可通过 processlist 和 查看 information_schema 下面与锁和事务相关的表来查看分析。
主备切换策略
主备延迟时候可以使用可靠性优先策略和可用性策略
可靠性优先策略
- 把主库改成只读状态,即把 readonly 设置为 true。
- 判断备库的 seconds_behind_master 的值,直到这个值变成 0 为止;
- 把备库改成可读写状态,也就是把 readonly 设置为 false;
- 把业务请求切到备库。
缺点就是主备切换的过程,系统是不可用的,只能进行读操作。
系统的不可用时间,是由这个数据可靠性优先的策略决定的。你也可以选择可用性优先的策略,来把这个不可用时间几乎降为 0。
可用性优先策略
就是备库没有同步完主库数据,直接把业务切换到备库读写。那么系统几乎就没有不可用时间了。这个切换流程的代价,就是可能出现数据不一致的情况。
可用性优先策略,且 binlog_format=mixed会出现数据错误,但是不会报错。
可用性优先策略,但设置 binlog_format=row两边的主备同步的应用线程会报错 duplicate key error 并停止。