MySQL 主从延迟的常见原因及解决方法

news2025/1/11 23:56:01

主从延迟作为 MySQL 的痛点已经存在很多年了,以至于大家都有一种错觉:有 MySQL 复制的地方就有主从延迟。

对于主从延迟的原因,很多人将之归结为从库的单线程重放。

但实际上,这个说法比较片面,因为很多场景,并行复制方案也解决不了,譬如从库 SQL 线程被阻塞了,从库磁盘 IO 存在瓶颈等。

很多童鞋在分析此类问题时缺乏一个系统的方法论,以致无法准确地定位出主从延迟的根本原因。

下面就如何分析主从延迟做一个系统、全面的总结。

本文主要包括以下两方面的内容。

  1. 如何分析主从延迟。
  2. 主从延迟的常见原因及解决方法。

如何分析主从延迟

分析主从延迟一般会采集以下三类信息。

从库服务器的负载情况

为什么要首先查看服务器的负载情况呢?因为软件层面的所有操作都需要系统资源来支撑。

常见的系统资源有四类:CPU、内存、IO、网络。对于主从延迟,一般会重点关注 CPU 和 IO 。

分析 CPU 是否达到瓶颈,常用的命令是 top,通过 top 我们可以直观地看到主机的 CPU 使用情况。以下是 top 中 CPU 相关的输出。

Cpu(s):  0.2%us,  0.2%sy,  0.0%ni, 99.5%id,  0.0%wa,  0.0%hi,  0.2%si,  0.0%st

下面我们看看各个指标的具体含义。

  • us:处理用户态( user )任务的 CPU 时间占比。

  • sy:处理内核态( system )任务的 CPU 时间占比。

  • ni:处理低优先级进程用户态任务的 CPU 时间占比。

    进程的优先级由 nice 值决定,nine 的范围是 -20 ~ 19 ,值越大,优先级越低。其中,1 ~ 19 称之为低优先级。

  • id:处于空闲状态( idle )的 CPU 时间占比。

  • wa:等待 IO 的 CPU 时间占比。

  • hi:处理硬中断( irq )的 CPU 时间占比。

  • si:处理软中断( softirq )的 CPU 使用率。

  • st:当系统运行在虚拟机中的时候,被其它虚拟机占用( steal )的 CPU 时间占比。

一般来说,当 CPU 使用率 ( 1 - 处于空闲状态的 CPU 时间占比 )超过 90% 时,需引起足够关注。毕竟,对于数据库应用来说,CPU 很少是瓶颈,除非有大量的慢 SQL 。

接下来看看 IO。

查看磁盘 IO 负载情况,常用的命令是 iostat 。

# iostat -xm 1
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           4.21    0.00    1.77    0.35    0.00   93.67

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
sdb               0.00     0.00  841.00 3234.00    13.14    38.96    26.19     0.60    0.15    0.30    0.11   0.08  32.60

命令中指定了 3 个选项,其中,

  • -x:打印扩展信息。

  • -m:指定吞吐量的单位是 MB/s ,默认是 KB/s 。

  • 1:每隔 1s 打印一次。

下面看看输出中各指标的具体含义。

  • rrqm/s:每秒被合并的读请求的数量。

  • wrqm/s:每秒被合并的写请求的数量。

  • r/s:每秒发送给磁盘的读请求的数量。

  • w/s:每秒写入磁盘的写请求的数量。注意,这里的请求是合并后的请求。r/s + w/s 等于 IOPS 。

  • rMB/s:每秒从磁盘读取的数据量。

  • wMB/s:每秒写入磁盘的数据量。rMB/s + wMB/s 等于吞吐量。

  • avgrq-sz:I/O 请求的平均大小,单位是扇区,扇区的大小是 512 字节。一般而言,I/O 请求越大,耗时越长。

  • avgqu-sz:队列里的平均 I/O 请求数量。

  • await:I/O 请求的平均耗时,包括磁盘的实际处理时间及队列中的等待时间,单位 ms 。

    其中,r_await   是读请求的平均耗时,w_await 是写请求的平均耗时。

  • svctm:I/O 请求的平均服务时间,单位 ms 。注意,这个指标已弃用,在后续版本会移除。

  • %util:磁盘饱和度。反映了一个采样周期内,有多少时间在做 I/O 操作。

一般来说,我们会重点关注 await 和 %util。

对于只能串行处理 I/O 请求的设备来说,%util 接近 100% ,就意味着设备饱和。但对于 RAID、SSD 等设备,因为它能并行处理,故该值参考意义不大,即使达到了 100% ,也不意味着设备出现了饱和。至于是否达到了性能上限,需参考性能压测下的 IOPS 和吞吐量。

主从复制状态

对于主库,执行 SHOW MASTER STATUS 。

mysql> show master status;
+------------------+----------+--------------+------------------+---------------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                           |
+------------------+----------+--------------+------------------+---------------------------------------------+
| mysql-bin.000004 |  1631495 |              |                  | bd6b3216-04d6-11ec-b76f-000c292c1f7b:1-5588 |
+------------------+----------+--------------+------------------+---------------------------------------------+
1 row in set (0.00 sec)

SHOW MASTER STATUS 的输出中重点关注 File 和 Position 这两个指标的值。

对于从库,执行 SHOW SLAVE STATUS 。

mysql> show slave status\G
*************************** 1. row ***************************
              ...
              Master_Log_File: mysql-bin.000004
          Read_Master_Log_Pos: 1631495
          ...
        Relay_Master_Log_File: mysql-bin.000004
          ...
          Exec_Master_Log_Pos: 1631495
          ...

SHOW SLAVE STATUS 的输出中重点关注 Master_Log_File,Read_Master_Log_Pos,Relay_Master_Log_File,Exec_Master_Log_Pos 这四个指标的值。

接下来,重点比较以下两对值。

第一对:( File , Position )  &  ( Master_Log_File , Read_Master_Log_Pos )

这里面,

  • ( File , Position ) 记录了主库 binlog 的位置。
  • ( Master_Log_File , Read_Master_Log_Pos ) 记录了 IO 线程当前正在接收的二进制日志事件在主库 binlog 中的位置。

如果 ( File , Position ) 大于 ( Master_Log_File , Read_Master_Log_Pos ) ,则意味着 IO 线程存在延迟。

第二对:( Master_Log_File , Read_Master_Log_Pos ) & ( Relay_Master_Log_File , Exec_Master_Log_Pos )

这里面,( Relay_Master_Log_File, Exec_Master_Log_Pos ) 记录了 SQL 线程当前正在重放的二进制日志事件在主库 binlog 的位置。

如果 ( Relay_Master_Log_File, Exec_Master_Log_Pos ) <  ( Master_Log_File, Read_Master_Log_Pos ) ,则意味着 SQL 线程存在延迟。

主库 binlog 的写入量

主要是看主库 binlog 的生成速度,比如多少分钟生成一个。

主从延迟的常见原因及解决方法

下面分别从 IO 线程和 SQL 线程这两个方面展开介绍。

IO 线程存在延迟

下面看看 IO 线程出现延迟的常见原因及解决方法。

  1. 网络延迟。

    判断是否为网络带宽限制。如果是,可开启 slave_compressed_protocol 参数,启用 binlog 的压缩传输。或者从 MySQL 8.0.20 开始,通过 binlog_transaction_compression 参数开启 binlog 事务压缩。

  2. 磁盘 IO 存在瓶颈 。

    可调整从库的双一设置或关闭 binlog。

    注意,在 MySQL 5.6 中,如果开启了 GTID ,则会强制要求开启 binlog ,MySQL 5.7 无此限制。

  3. 网卡存在问题。

    这种情况不多见,但确实碰到过。当时是一主两从的架构,发现一台主机上的所有从库都延迟了,但这些从库对应集群的其它从库却没有延迟,后来通过 scp 远程拷贝文件进一步确认了该台主机的网络存在问题,最后经系统组确认,网卡存在问题。

一般情况下,IO 线程很少存在延迟。

SQL 线程存在延迟

下面看看 SQL 线程出现延迟的常见原因及解决方法。

主库写入量过大,SQL 线程单线程重放

具体体现如下:

  1. 从库磁盘 IO 无明显瓶颈。
  2. Relay_Master_Log_File , Exec_Master_Log_Pos 也在不断变化。
  3. 主库写入量过大。如果磁盘使用的是 SATA SSD,当 binlog 的生成速度快于 5 分钟一个时,从库重放就会有瓶颈。

这个是 MySQL 软件层面的硬伤。要解决该问题,可开启 MySQL 5.7 引入的基于 LOGICAL_CLOCK 的并行复制。

关于 MySQL 并行复制方案,可参考:MySQL 并行复制方案演进历史及原理分析

STATEMENT 格式下的慢 SQL

具体体现,在一段时间内 Relay_Master_Log_File , Exec_Master_Log_Pos 没有变化。

看下面这个示例,对 1 张千万数据的表进行 DELETE 操作,表上没有任何索引,在主库上执行用了 7.52s,观察从库的 Seconds_Behind_Master,发现它最大达到了 7s 。

mysql> show variables like 'binlog_format';
+---------------+-----------+
| Variable_name | Value     |
+---------------+-----------+
| binlog_format | STATEMENT |
+---------------+-----------+
1 row in set (0.00 sec)

mysql> select count(*) from sbtest.sbtest1;
+----------+
| count(*) |
+----------+
| 10000000 |
+----------+
1 row in set (1.41 sec)

mysql> show create table sbtest.sbtest1\G
*************************** 1. row ***************************
       Table: sbtest1
Create Table: CREATE TABLE `sbtest1` (
  `id` int NOT NULL,
  `k` int NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

mysql> delete from sbtest.sbtest1 where id <= 100;
Query OK, 100 rows affected (7.52 sec)

对于这种执行较慢的 SQL ,并行复制实际上也是无能为力的, 此时只能优化 SQL。

在 MySQL 5.6.11 中,引入了参数 log_slow_slave_statements ,可将 SQL 重放过程中执行时长超过 long_query_time 的操作记录在慢日志中。

表上没有任何索引,且二进制日志格式为 ROW

同样,在一段时间内,Relay_Master_Log_File , Exec_Master_Log_Pos 不会变化。

如果表上没有任何索引,对它进行操作,在主库上只是一次全表扫描。但在从库重放时,因为是 ROW 格式,对于每条记录的操作都会进行一次全表扫描。

还是上面的表,同样的操作,只不过二进制日志格式为 ROW ,在主库上执行用了 7.53s ,但 Seconds_Behind_Master 最大却达到了 723s ,是 STATEMENT 格式下的 100 倍。

mysql> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+
1 row in set (0.00 sec)

mysql> delete from sbtest.sbtest1 where id <= 100;
Query OK, 100 rows affected (7.53 sec)

如果因为表上没有任何索引,导致主从延迟过大,常见的优化方案如下:

  1. 在从库上临时创建个索引,加快记录的重放。注意,尽量选择一个区分度高的列添加索引,列的区分度越高,重放的速度就越快。

  2. 将参数 slave_rows_search_algorithms 设置为 INDEX_SCAN,HASH_SCAN 。

    设置后,对于同样的操作,Seconds_Behind_Master 最大只有 53s 。

大事务

这里的大事务,指的是二进制日志格式为 ROW 的情况下,操作涉及的记录数较多。

还是上面的测试表,只不过这次 id 列是自增主键,执行批量更新操作。更新操作如下,其中,N 是记录数,M 是一个随机字符,每次操作的字符均不一样。

update sbtest.sbtest1 set c=repeat(M,120) where id<=N

接下来我们看看不同记录数下对应 Seconds_Behind_Master 的最大值。

记录数主库执行时长(s)Seconds_Behind_Master最大值(s)
500000.761
2000003.108
50000017.3239
100000063.47122

可见,随着记录数的增加,Seconds_Behind_Master 也是不断增加的。

所以对于大事务操作,建议分而治之,每次小批量执行。

判断一个 binlog 是否存在大事务,可通过我之前写的一个 binlog_summary.py 的工具来分析,该工具的具体用法可参考:Binlog分析利器-binlog_summary.py

从库上有查询操作

从库上有查询操作,通常会有两方面的影响:

1. 消耗系统资源。

2. 锁等待。

常见的是从库的查询操作堵塞了主库的 DDL 操作。看下面这个示例。

mysql> show processlist;
+----+-----------------+-----------------+------+---------+------+----------------------------------+----------------------------------------+
| Id | User            | Host            | db   | Command | Time | State                            | Info                                   |
+----+-----------------+-----------------+------+---------+------+----------------------------------+----------------------------------------+
|  5 | event_scheduler | localhost       | NULL | Daemon  | 2239 | Waiting on empty queue           | NULL                                   |
| 17 | root            | localhost       | NULL | Query   |    0 | init                             | show processlist                       |
| 18 | root            | localhost       | NULL | Query   |   19 | User sleep                       | select id,sleep(1) from sbtest.sbtest1 |
| 19 | system user     | connecting host | NULL | Connect |  243 | Waiting for source to send event | NULL                                   |
| 20 | system user     |                 |      | Query   |   13 | Waiting for table metadata lock  | alter table sbtest.sbtest1 add c2 int  |
+----+-----------------+-----------------+------+---------+------+----------------------------------+----------------------------------------+
5 rows in set (0.00 sec)

从库上存在备份

常见的是备份的全局读锁阻塞了 SQL 线程的重放。看下面这个示例。

mysql> show processlist;
+----+-----------------+-----------------+------+---------+------+----------------------------------+----------------------------------------+
| Id | User            | Host            | db   | Command | Time | State                            | Info                                   |
+----+-----------------+-----------------+------+---------+------+----------------------------------+----------------------------------------+
|  5 | event_scheduler | localhost       | NULL | Daemon  | 4177 | Waiting on empty queue           | NULL                                   |
| 17 | root            | localhost       | NULL | Query   |    0 | init                             | show processlist                       |
| 18 | root            | localhost       | NULL | Query   |   36 | User sleep                       | select id,sleep(1) from sbtest.sbtest2 |
| 19 | system user     | connecting host | NULL | Connect | 2181 | Waiting for source to send event | NULL                                   |
| 20 | system user     |                 |      | Query   |    2 | Waiting for global read lock     | alter table sbtest.sbtest1 add c1 int  |
| 28 | root            | localhost       | NULL | Query   |   17 | Waiting for table flush          | flush tables with read lock            |
+----+-----------------+-----------------+------+---------+------+----------------------------------+----------------------------------------+
6 rows in set (0.00 sec)

磁盘 IO 存在瓶颈

这个时候可调整从库的双一设置或关闭 binlog。

总结

综合上面的分析,主从延迟的常见原因及解决方法如下图所示。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/751671.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

我司的短信接口被刷了

如何发现的 成本分摊系统&#xff0c;将成本分摊给业务部门时&#xff0c;业务部门对账&#xff0c;发现某一类型的短信用量上涨了100多倍 排查调用来源时&#xff0c;发现来源为C端用户&#xff0c;由于调用量异常高&#xff0c;业务反馈近期无活动&#xff0c;因此怀疑被刷…

GAMES101 作业0

Visual Studio 2019下环境配置 课上提供的环境是Linux, 还需要安装Vitrual Box和创建虚拟机&#xff0c;省事就直接在Windows系统下Visual Studio下操作了。 简单的环境配置&#xff1a; 下载Eigen 的库在工程属性中添加目录&#xff1a; 2处地方 注意&#xff1a; 刚添加完…

CONTAINER = ALL是ALTER USER语句的默认值

连接到root时查看有关root&#xff0c;CDB和PDB的数据 当公用用户执行查询时&#xff0c;可以限制X $表和V $&#xff0c;GV $和CDB_ *视图的视图信息。X$表和这些视图包含有关应用程序root及其关联应用程序PDB的信息&#xff0c;或者如果连接到CDB root&#xff0c;则是整个C…

基于非支配排序遗传算法NSGAII的综合能源优化调度(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

松鼠回家(最短路+二分)

D-松鼠回家_2023河南萌新联赛第&#xff08;一&#xff09;场&#xff1a;河南农业大学 (nowcoder.com) #include<bits/stdc.h> using namespace std; #define int long long const int N2e510; map<int,int>a; int n,m,st,ed,h; struct node{int x,y; }; vector&l…

解密Prompt系列4. 升级Instruction Tuning:Flan/T0/InstructGPT/TKInstruct

这一章我们聊聊指令微调&#xff0c;指令微调和前3章介绍的prompt有什么关系呢&#xff1f;哈哈只要你细品&#xff0c;你就会发现大家对prompt和instruction的定义存在些出入&#xff0c;部分认为instruction是prompt的子集&#xff0c;部分认为instruction是句子类型的prompt…

wangEditor富文本编辑器的调用开发实录2(V5版本自定义粘贴,去除复制word或网页html冗余样式代码的解决方案)

wangEditor富文本编辑器&#xff1a;自定义粘贴&#xff0c;去除复制word或网页html冗余样式代码的解决方案 1.环境说明2.解决方案3.完整代码总结 在使用wangEditor富文本编辑器时&#xff0c;当从word文档或者其他网页复制文本内容粘贴到编辑器中&#xff0c;如果不过滤掉复制…

4. CSS用户界面样式

4.1什么是界面样式 所谓的界面样式,就是更改一些用户操作样式,以便提高更好的用户体验。 ●更改用户的鼠标样式 ●表单轮廓 ●防止表单域拖拽 4.2鼠标样式cursor li {cursor: pointer; }设置或检索在对象上移动的鼠标指针采用何种系统预定义的光标形状。 4.3轮廓线outline…

汽配企业实施MES管理系统前有哪些注意事项

随着汽车行业的快速发展&#xff0c;汽配企业面临着越来越激烈的市场竞争。为了提高生产效率、降低成本、提升产品质量。实施MES管理系统成为了许多汽配企业的选择。但在实施MES生产管理系统之前&#xff0c;汽配企业需要注意以下几个方面&#xff0c;以确保项目的成功实施。 一…

GaussDB火焰图分析

目录 问题描述问题现象告警业务影响原因分析处理方法 问题描述 CPU利用率是衡量系统负载和健康度的重要指标之一&#xff0c;系统在运行过程中时常发生CPU利用率高的情况。在分析性能问题时&#xff0c;可通过火焰图查看CPU耗时&#xff0c;了解瓶颈在哪里。 问题现象 部分s…

6.溢出的文字省略号显示

6.1单行文本溢出显示省略号 必须满足三个条件 /*1. 先强制一行内显示文本*/ white-space: nowrap; &#xff08; 默认 normal 自动换行&#xff09; /*2. 超出的部分隐藏*/ overflow: hidden; /*3. 文字用省略号替代超出的部分*/ text-overflow: ellipsis;【示例代码】 <…

在Excel电子表格中用公式实现最最简易的标签套打

每月要为单位新入职员工打印标签贴纸&#xff0c;贴于档案之上&#xff0c;之前是用Excel建立一张表&#xff0c;通过拖动单元格大小&#xff0c;调整文本位置&#xff0c;实现标签贴纸的打印功能。 后来&#xff0c;公司每月都会新招入一批员工&#xff0c;每次打印贴纸时&…

Linux学习之变量引用和作用范围

使用${变量名}或者$变量名就可以引用变量&#xff0c;$变量名其实是${变量名}的省略写法。 要是变量名后边还有其他字符就需要加上{}&#xff0c;比如helloToBash这个变量的值是Hello Bash&#xff0c;而需要输出的字符串是“Hello Bashing”&#xff0c;这样就需要加上{}&…

青岛大学_王卓老师【数据结构与算法】Week05_07_顺序栈的操作1_学习笔记

本文是个人学习笔记&#xff0c;素材来自青岛大学王卓老师的教学视频。 一方面用于学习记录与分享&#xff0c; 另一方面是想让更多的人看到这么好的《数据结构与算法》的学习视频。 如有侵权&#xff0c;请留言作删文处理。 课程视频链接&#xff1a; 数据结构与算法基础…

Config分布式配置中心(在Spring Cloud整合Config(idea19版本))

应用场景 1.集中配置管理(一处修改,处处生效) 2.不同环境不同配置(开发dev,测试test,生产prod) 3.运行期间可动态调整 4.如果配置内容发生变化,微服务可以自动更新配置 分布式配置管理 Server:提供配置文件的存储、以接口的形式将配置文件的内容提供出去&a…

如何将 OpenTelemetry 检测与 Elastic APM Agent 功能相结合

作者&#xff1a;Greg Kalapos Elastic APM 在多个级别支持 OpenTelemetry。 我们之前在博客中介绍过的一种易于理解的场景是 APM 服务器中的直接开放遥测协议 (OTLP) 支持。 这意味着你可以将任何 OpenTelemetry 代理连接到 Elastic APM 服务器&#xff0c;APM 服务器会很乐意…

模拟高清1路RX—XS9950,可替代TP9950

1通道模拟高清复合视频解码芯片可替代TP9950&#xff0c;兼容CVI、AHD、TVI和CVBS&#xff0c;最高支持 1 路1080p30fps&#xff0c;同时支持音频接入&#xff1b;支持BT656和MIPI输出&#xff0c;包含 AFE、EQ 和 ADC&#xff0c;AFE支持通道带宽、输入信号增益可调节&#xf…

二维码生成器简单使用

生成器工具类 以下是一个简单的 QRCodeUtil 示例&#xff0c;这个工具类使用了 zxing 库来生成二维码图片&#xff1a; import com.google.zxing.BarcodeFormat; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.QRCodeWriter;import javax.image…

数据可视化分析,2023结婚全品类消费趋势洞察报告

结婚消费与人们的关系密切相关。结婚是一个重要的人生事件&#xff0c;往往伴随着大量的消费。人们倾向于在婚礼仪式、婚纱摄影、宴会等方面进行豪华的投资&#xff0c;以展示社会地位和个人品味。此外&#xff0c;结婚还涉及到婚戒、婚庆、蜜月旅行等费用。然而&#xff0c;随…

基于 NNCF 和 Optimum 面向 Intel CPU 对 Stable Diffusion 优化

&#x1f917; 宝子们可以戳 阅读原文 查看文中所有的外部链接哟&#xff01; 基于隐空间的扩散模型 (Latent Diffusion Model)&#xff0c;是解决文本到图片生成问题上的颠覆者。Stable Diffusion 是最著名的一例&#xff0c;广泛应用在商业和工业。Stable Diffusion 的想法简…