MySQL高阶讲座之:`MySQL`的`IO`瓶颈:如何通过`iostat`和`vmstat`定位`IO`热点。

各位老铁,晚上好!我是你们的老朋友,今天咱们聊聊MySQL的IO瓶颈,以及如何用iostatvmstat这两个神器来揪出IO热点。这玩意儿听起来高大上,其实就是看看你的硬盘是不是被MySQL榨干了。来,咱们开始!

开场白:IO,MySQL的命门

MySQL再牛逼,数据最终还是得落到硬盘上。就像人一样,大脑再聪明,也得吃饭拉屎。IO就是MySQL的“吃饭拉屎”,IO慢了,整个MySQL就便秘了。所以,搞清楚IO瓶颈,是每一个MySQL DBA的必修课。

第一部分:IO瓶颈的症状

IO瓶颈有哪些症状呢?别慌,我给你总结了几条:

  1. 查询慢如蜗牛: 以前嗖嗖快的查询,现在半天出不来结果。
  2. CPU利用率不高: CPU没怎么干活,MySQL服务器就卡在那儿了。这说明CPU在等IO。
  3. 磁盘灯狂闪: 硬盘像迪斯科灯一样闪个不停,说明它很忙。
  4. SHOW PROCESSLIST中大量Sending data状态: 这意味着MySQL正在努力地把数据从硬盘读出来,然后发送给客户端。
  5. 慢查询日志里出现大量执行时间长的查询: 如果你的慢查询日志里堆满了慢查询,而且这些查询都在访问大量数据,那很可能就是IO瓶颈。
  6. 监控指标异常: 如果你使用了监控工具(比如Prometheus + Grafana),你会发现磁盘I/O相关的指标(如磁盘读写延迟、IOPS等)明显升高。

第二部分:iostat:磁盘活动的透视镜

iostat 是一个用于报告CPU统计信息和整个系统、物理驱动器或分区的磁盘I/O统计信息的小工具。 简单来说,它能告诉你硬盘在干什么,有多忙。

2.1 iostat的安装

一般情况下,iostat 包含在 sysstat 包里。如果没有安装,可以用以下命令安装:

  • CentOS/RHEL: sudo yum install sysstat
  • Ubuntu/Debian: sudo apt-get install sysstat

2.2 iostat的基本用法

最简单的用法是:

iostat

这会显示自系统启动以来的统计信息,以及当前时刻的统计信息。 但这通常没什么用,我们需要指定报告间隔和报告次数:

iostat 2 5  # 每隔2秒报告一次,报告5次

2.3 iostat的重要指标

iostat 的输出有很多列,但我们最关心的是以下几个:

指标 含义 重要性
device 设备名称(例如 sda, sdb, nvme0n1 等)
%util 设备的繁忙百分比。 越高越好,接近100%说明磁盘很忙,可能存在瓶颈。 非常高
rrqm/s 每秒进行合并读取请求的数量。 这些是操作系统试图合并的请求,以优化效率。
wrqm/s 每秒进行合并写入请求的数量。
r/s 每秒完成的读取请求数。 越高越好,反映了磁盘的读取负载。
w/s 每秒完成的写入请求数。 越高越好,反映了磁盘的写入负载。
rkB/s 每秒读取的千字节数。 越高越好,反映了磁盘的读取吞吐量。
wkB/s 每秒写入的千字节数。 越高越好,反映了磁盘的写入吞吐量。
await 平均每次I/O操作的等待时间(毫秒)。 越高越好,如果长时间超过20ms,说明IO压力很大。 非常高
svctm 平均每次I/O操作的服务时间(毫秒)。 这个指标在现代磁盘上不太可靠,因为硬件通常会隐藏实际的服务时间。
%iowait CPU等待IO完成的时间百分比。 这个指标由 vmstat 提供,但与磁盘性能密切相关。 参考

2.4 iostat 实战案例

假设我们运行 iostat 2 5 得到如下结果:

Linux 3.10.0-957.el7.x86_64 (localhost.localdomain)     08/22/2024 21:30:32     x86_64  (1 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.11    0.00    0.14    0.04    0.00   99.71

Device:            tps    rkB/s    wkB/s   rrqm/s   wrqm/s  %util
sda              15.00     1.00    14.00     0.00     0.00   1.00
sdb             300.00   200.00   100.00     0.00     0.00  99.00

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.11    0.00    0.14    0.04    0.00   99.71

Device:            tps    rkB/s    wkB/s   rrqm/s   wrqm/s  %util
sda              15.00     1.00    14.00     0.00     0.00   1.00
sdb             300.00   200.00   100.00     0.00     0.00  99.00

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.11    0.00    0.14    0.04    0.00   99.71

Device:            tps    rkB/s    wkB/s   rrqm/s   wrqm/s  %util
sda              15.00     1.00    14.00     0.00     0.00   1.00
sdb             300.00   200.00   100.00     0.00     0.00  99.00

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.11    0.00    0.14    0.04    0.00   99.71

Device:            tps    rkB/s    wkB/s   rrqm/s   wrqm/s  %util
sda              15.00     1.00    14.00     0.00     0.00   1.00
sdb             300.00   200.00   100.00     0.00     0.00  99.00

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.11    0.00    0.14    0.04    0.00   99.71

Device:            tps    rkB/s    wkB/s   rrqm/s   wrqm/s  %util
sda              15.00     1.00    14.00     0.00     0.00   1.00
sdb             300.00   200.00   100.00     0.00     0.00  99.00

从这个结果可以看出:

  • sdb%util 接近 100%,说明 sdb 盘非常繁忙,很可能是IO瓶颈所在。
  • sdbr/sw/s 都很高,说明读写操作非常频繁。
  • sda%util 很低,说明它比较空闲。

结论:sdb 很可能就是你的MySQL数据库所在的分区。

2.5 进阶用法:指定设备

如果你只想看某个特定设备的IO情况,可以这样:

iostat -d sdb 2 5  # 只看 sdb 盘

2.6 结合其他工具:pidstat

有时候,光知道是哪个硬盘慢还不够,你还得知道是哪个进程在狂读狂写。 这时候,pidstat 就派上用场了。

pidstat -d 2 5  # 每隔2秒报告一次,报告5次,显示IO统计信息

pidstat 会显示每个进程的IO统计信息,包括读取和写入的字节数。 结合 iostatpidstat,你就能揪出那个榨干硬盘的罪魁祸首。

第三部分:vmstat:系统资源的全局视角

vmstat 是一个用于报告虚拟内存统计信息的工具,但它也能提供一些有用的IO信息。虽然它的重点不是磁盘I/O,但是它能够补充 iostat 的信息,提供更全面的系统状态。

3.1 vmstat 的安装

iostat 一样,vmstat 通常也包含在 sysstat 包里。

3.2 vmstat 的基本用法

vmstat 2 5  # 每隔2秒报告一次,报告5次

3.3 vmstat 的重要指标

指标 含义 重要性
r 运行队列中的进程数。 如果这个值很高,说明CPU很忙,或者有很多进程在等待IO。
b 处于不可中断睡眠状态的进程数。 这些进程通常在等待IO。 如果这个值很高,说明IO压力很大。
swpd 使用的虚拟内存量(KB)。 如果这个值很高,说明系统在频繁地使用交换空间,这会严重影响性能。 参考
free 空闲内存量(KB)。 参考
buff 用作缓冲区的内存量(KB)。 参考
cache 用作缓存的内存量(KB)。 参考
si 每秒从磁盘交换到内存的数据量(KB)。 如果这个值很高,说明系统在频繁地使用交换空间,这会严重影响性能。
so 每秒从内存交换到磁盘的数据量(KB)。 如果这个值很高,说明系统在频繁地使用交换空间,这会严重影响性能。
bi 每秒从块设备接收的数据量(块)。 这个值越高,说明磁盘读取越频繁。
bo 每秒发送到块设备的数据量(块)。 这个值越高,说明磁盘写入越频繁。
in 每秒中断数。 参考
cs 每秒上下文切换数。 参考
us 用户进程消耗的CPU时间百分比。 参考
sy 系统进程消耗的CPU时间百分比。 参考
id 空闲CPU时间百分比。 参考
wa CPU等待IO完成的时间百分比。 这个值越高,说明IO压力越大。 非常高
st 被虚拟机偷走的CPU时间百分比。 参考

3.4 vmstat 实战案例

假设我们运行 vmstat 2 5 得到如下结果:

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  1      0 107952   2480 190232    0    0    16    16   14   16  0  0 99  1  0
 0  1      0 107952   2480 190232    0    0     0     0   17   15  0  0 100  0  0
 0  1      0 107952   2480 190232    0    0     0     0   14   15  0  0 100  0  0
 0  1      0 107952   2480 190232    0    0     0     0   15   15  0  0 100  0  0
 0  1      0 107952   2480 190232    0    0     0     0   15   15  0  0 100  0  0

从这个结果可以看出:

  • b 列的值为 1,说明有一个进程在等待IO。
  • wa 列的值为 1%,说明CPU有1%的时间在等待IO。 虽然不高,但是结合 iostat 的结果,可以确认存在IO瓶颈。
  • siso 的值都为 0,说明系统没有频繁地使用交换空间。

3.5 vmstatiostat 的配合

vmstatiostat 可以互相补充。 iostat 告诉你哪个硬盘慢,vmstat 告诉你整个系统的IO压力。 结合两者,可以更全面地了解IO瓶颈。

第四部分:定位IO热点:抽丝剥茧

好了,现在我们已经知道怎么用 iostatvmstat 来观察IO了。 接下来,我们要把IO热点揪出来。

4.1 确定瓶颈类型

首先,我们要确定是哪种类型的IO瓶颈:

  • 读取瓶颈: 大量读取操作导致IO饱和。
  • 写入瓶颈: 大量写入操作导致IO饱和。
  • 混合瓶颈: 读写操作都很频繁,导致IO饱和。

可以通过观察 iostatr/sw/s 来判断。

4.2 定位罪魁祸首

确定瓶颈类型后,我们要找出是哪个进程在狂读狂写。 可以使用 pidstat 来查看每个进程的IO统计信息。

pidstat -d 2 5  # 每隔2秒报告一次,报告5次,显示IO统计信息

找到IO最高的进程,记下它的PID。

4.3 分析进程行为

有了PID,我们就可以进一步分析这个进程的行为。

  • 如果是MySQL进程: 可能是某个查询在访问大量数据,导致IO瓶颈。 可以通过慢查询日志来分析。
  • 如果是其他进程: 可能是备份进程、日志进程或其他IO密集型进程。

4.4 优化方案

找到IO热点后,就可以采取相应的优化方案:

  • 优化SQL查询: 使用索引、减少数据量、避免全表扫描。
  • 调整MySQL配置: 调整 innodb_buffer_pool_sizeinnodb_log_file_size 等参数。
  • 升级硬件: 更换更快的硬盘(SSD)、增加内存。
  • 优化操作系统: 调整IO调度算法、使用RAID。
  • 分离IO密集型任务: 将备份、日志等任务转移到其他服务器。

第五部分:优化案例

举个例子,假设我们发现MySQL的IO瓶颈是由于一个全表扫描的查询导致的。

5.1 问题分析

我们通过 iostatvmstat 发现IO很高,然后通过 pidstat 找到MySQL进程,最后通过慢查询日志发现一个全表扫描的查询。

5.2 优化方案

  1. 添加索引: 在查询的字段上添加索引,避免全表扫描。
  2. 重写SQL: 优化SQL语句,减少数据量。
  3. 调整MySQL配置: 增加 innodb_buffer_pool_size,尽量将数据缓存到内存中。

5.3 效果评估

优化后,再次使用 iostatvmstat 观察IO,发现IO明显降低,查询速度也提高了。

第六部分:总结与展望

今天我们聊了MySQL的IO瓶颈,以及如何用 iostatvmstat 来定位IO热点。 这两个工具是每一个MySQL DBA的必备技能。

当然,IO优化是一个复杂的问题,需要根据实际情况进行分析和调整。 没有一劳永逸的解决方案。

希望今天的分享能帮助大家更好地理解MySQL的IO瓶颈,并能运用 iostatvmstat 来解决实际问题。

最后,记住:IO优化,永无止境!

各位,今天的讲座就到这里,咱们下期再见! 感谢大家!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注