各位老铁,晚上好!我是你们的老朋友,今天咱们聊聊MySQL的IO瓶颈,以及如何用iostat
和vmstat
这两个神器来揪出IO热点。这玩意儿听起来高大上,其实就是看看你的硬盘是不是被MySQL榨干了。来,咱们开始!
开场白:IO,MySQL的命门
MySQL再牛逼,数据最终还是得落到硬盘上。就像人一样,大脑再聪明,也得吃饭拉屎。IO就是MySQL的“吃饭拉屎”,IO慢了,整个MySQL就便秘了。所以,搞清楚IO瓶颈,是每一个MySQL DBA的必修课。
第一部分:IO瓶颈的症状
IO瓶颈有哪些症状呢?别慌,我给你总结了几条:
- 查询慢如蜗牛: 以前嗖嗖快的查询,现在半天出不来结果。
- CPU利用率不高: CPU没怎么干活,MySQL服务器就卡在那儿了。这说明CPU在等IO。
- 磁盘灯狂闪: 硬盘像迪斯科灯一样闪个不停,说明它很忙。
SHOW PROCESSLIST
中大量Sending data
状态: 这意味着MySQL正在努力地把数据从硬盘读出来,然后发送给客户端。- 慢查询日志里出现大量执行时间长的查询: 如果你的慢查询日志里堆满了慢查询,而且这些查询都在访问大量数据,那很可能就是IO瓶颈。
- 监控指标异常: 如果你使用了监控工具(比如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瓶颈所在。sdb
的r/s
和w/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统计信息,包括读取和写入的字节数。 结合 iostat
和 pidstat
,你就能揪出那个榨干硬盘的罪魁祸首。
第三部分: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瓶颈。si
和so
的值都为 0,说明系统没有频繁地使用交换空间。
3.5 vmstat
和 iostat
的配合
vmstat
和 iostat
可以互相补充。 iostat
告诉你哪个硬盘慢,vmstat
告诉你整个系统的IO压力。 结合两者,可以更全面地了解IO瓶颈。
第四部分:定位IO热点:抽丝剥茧
好了,现在我们已经知道怎么用 iostat
和 vmstat
来观察IO了。 接下来,我们要把IO热点揪出来。
4.1 确定瓶颈类型
首先,我们要确定是哪种类型的IO瓶颈:
- 读取瓶颈: 大量读取操作导致IO饱和。
- 写入瓶颈: 大量写入操作导致IO饱和。
- 混合瓶颈: 读写操作都很频繁,导致IO饱和。
可以通过观察 iostat
的 r/s
和 w/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_size
、innodb_log_file_size
等参数。 - 升级硬件: 更换更快的硬盘(SSD)、增加内存。
- 优化操作系统: 调整IO调度算法、使用RAID。
- 分离IO密集型任务: 将备份、日志等任务转移到其他服务器。
第五部分:优化案例
举个例子,假设我们发现MySQL的IO瓶颈是由于一个全表扫描的查询导致的。
5.1 问题分析
我们通过 iostat
和 vmstat
发现IO很高,然后通过 pidstat
找到MySQL进程,最后通过慢查询日志发现一个全表扫描的查询。
5.2 优化方案
- 添加索引: 在查询的字段上添加索引,避免全表扫描。
- 重写SQL: 优化SQL语句,减少数据量。
- 调整MySQL配置: 增加
innodb_buffer_pool_size
,尽量将数据缓存到内存中。
5.3 效果评估
优化后,再次使用 iostat
和 vmstat
观察IO,发现IO明显降低,查询速度也提高了。
第六部分:总结与展望
今天我们聊了MySQL的IO瓶颈,以及如何用 iostat
和 vmstat
来定位IO热点。 这两个工具是每一个MySQL DBA的必备技能。
当然,IO优化是一个复杂的问题,需要根据实际情况进行分析和调整。 没有一劳永逸的解决方案。
希望今天的分享能帮助大家更好地理解MySQL的IO瓶颈,并能运用 iostat
和 vmstat
来解决实际问题。
最后,记住:IO优化,永无止境!
各位,今天的讲座就到这里,咱们下期再见! 感谢大家!