Ubuntu服务器出现磁盘IO瓶颈时,最快最直接的诊断方法就是用iostat看整体IO吞吐和等待情况,再用iotop定位到底是哪个进程在疯狂读写。iostat能告诉你磁盘的利用率、每秒读写次数、平均等待时间,iotop则像top命令一样实时显示每个进程的IO占用。两个工具配合使用,基本上90%的磁盘IO问题都能在十分钟内定位到根因。下面我把完整的操作流程、参数解读、实战案例和优化建议一次性讲透。

一、先装工具,别到用时才发现没有

Ubuntu默认可能没装这两个工具。iostat属于sysstat包,iotop是Python写的独立工具。一条命令全部搞定:

sudo apt update && sudo apt install -y sysstat iotop

装完之后验证一下版本,确保能正常运行。sysstat包还自带了sar、mpstat等一系列性能监控工具,以后都用得上。

二、iostat核心参数解读与使用方法

直接在终端输入iostat,默认只显示一次快照,没什么参考价值。必须加参数-x和时间间隔来持续观察:

iostat -x 1

这里-x表示显示扩展信息,1表示每隔1秒刷新一次。输出结果里有几个关键指标必须看懂:

r/s和w/s:每秒读和写的次数(IOPS)。如果这个值持续很高,说明IO请求密集。

await:平均每次IO请求的等待时间,单位毫秒。这个值超过20ms就要警惕,超过100ms基本可以确认瓶颈了。

%util:磁盘利用率百分比。接近100%说明磁盘已经满负荷运转,这是最直观的瓶颈信号。

r_await和w_await:分别是读和写的平均等待时间。如果w_await远大于r_await,说明写操作是瓶颈来源。

avgqu-sz:平均队列长度。这个值持续大于1就说明IO请求在排队,磁盘处理不过来。

更实用的命令是指定设备名和次数:

iostat -x /dev/sda 5

每5秒刷新一次/dev/sda的数据,连续看几十秒就能判断趋势。如果你有多块盘,可以用iostat -x 1查看所有设备的汇总。

三、iotop实时定位问题进程

iostat告诉你"磁盘有问题",iotop告诉你"谁在搞事情"。直接运行:

sudo iotop -o

-o参数只显示正在产生IO的进程,过滤掉空闲进程,界面更清爽。你会看到类似top的界面,每行显示进程名、PID、IO使用百分比、读写速度。排在最前面的就是IO大户。

常用参数补充:

sudo iotop -aoP

-a累积显示IO总量而不是瞬时值,-o只显示活跃进程,-P显示进程而不是线程。在排查问题时-a特别有用,因为有些进程IO不是持续的而是突发的,累积值更容易捕捉到。

四、实战诊断流程:从发现到定位

第一步,发现系统变慢。用top或htop看load average,如果三个值都很高且主要是IO wait占比大,基本确认IO瓶颈。

第二步,用iostat -x 1观察。重点看%util是否接近100%,await是否超过20ms,avgqu-sz是否大于1。如果三个都中了,确认磁盘IO瓶颈无疑。

第三步,用iotop -oP找进程。找到IO占比最高的进程PID,记下来。

第四步,进一步分析这个进程在干什么。用lsof看它打开了哪些文件:

sudo lsof -p <PID>

或者用strace跟踪它的系统调用:

sudo strace -p <PID> -e trace=read,write,open,close -c

这样就能知道这个进程到底在读写什么文件、频率多高、是顺序IO还是随机IO。

五、常见场景与对应解决方案

场景一:数据库MySQL/PostgreSQL疯狂写盘。这通常是大量写入、缺少索引导致全表扫描、或者binlog/WAL刷盘太频繁。解决办法是优化慢查询、调整innodb_flush_log_at_trx_commit参数、把数据目录放到SSD上。

场景二:日志文件疯狂写入。比如应用程序开了DEBUG级别日志,或者日志轮转没配置好。用iotop找到进程后,调整日志级别或者配置logrotate定时清理。

场景三:备份任务占用全部IO。rsync、tar打包、dd镜像操作都是IO大户。解决办法是用ionice降低备份进程的IO优先级:

ionice -c 2 -n 7 rsync -av /data /backup/

-c 2表示最佳努力类(be),-n 7是最低优先级,这样备份不会影响正常业务。

场景四:Swap频繁使用导致IO飙升。当内存不够时系统会用磁盘当虚拟内存,随机IO会暴增。用free -h确认内存使用情况,如果swap占用很大,要么加内存要么优化应用内存使用。

场景五:RAID阵列降级或单盘故障。用smartctl检查硬盘健康状态:

sudo smartctl -a /dev/sda

看Reallocated_Sector_Ct、Current_Pending_Sector等指标,如果有预警说明硬盘快挂了,赶紧换。

六、进阶技巧与长期监控

iostat支持把数据记录到文件方便事后分析:

iostat -x 1 100 > /tmp/iostat_log.txt

记录100秒的数据到文件,之后用awk或Python分析峰值时段。

如果需要长期监控,可以用sysstat自带的sadc采集数据,配合sar回放:

sar -d -f /var/log/sysstat/sa$(date +%d)

查看历史某天的磁盘IO情况,方便做容量规划和趋势分析。

另外一个容易忽略的点是文件系统本身的IO调度器。Ubuntu默认用mq-deadline或none(取决于内核版本)。对于SSD推荐用none或noop,对于机械盘用bfq或mq-deadline。查看当前调度器:

cat /sys/block/sda/queue/scheduler

临时切换:

echo "none" | sudo tee /sys/block/sda/queue/scheduler

永久生效需要在grub里加内核参数。

七、几个容易踩的坑

第一,不要只看%util就下结论。有些情况下%util很高但await很低,说明磁盘虽然忙但处理得过来,不一定是瓶颈。要综合看await和avgqu-sz。

第二,iotop需要root权限,普通用户运行看不到真实数据。而且iotop本身也会产生少量IO,在极端情况下可能影响判断,但一般可以忽略。

第三,云服务器的IO性能受限于云平台的IO配额,不是你换SSD就能解决的。阿里云、腾讯云都有IOPS上限,需要在控制台查看和调整。

第四,NFS网络存储的IO瓶颈不能只看本地iostat,还要看网络延迟和NFS服务器端的负载。这时候需要在NFS服务端也跑iostat对比。

总结一下,Ubuntu磁盘IO诊断的核心就是"iostat看全局、iotop抓进程、lsof/strace追细节"这三板斧。工具不复杂,关键是要养成定期监控的习惯,别等系统卡死了才去排查。把iostat -x 1和iotop -o加入你的日常巡检脚本,问题早发现早解决,运维效率能提升一大截。