从一次数据库卡顿排查说起:手把手教你用sysstat的iostat定位MySQL慢查询背后的磁盘IO问题
2026/6/5 5:01:01 网站建设 项目流程

从数据库卡顿到磁盘IO瓶颈:一次完整的MySQL性能排查实战

凌晨三点,手机突然响起刺耳的警报声——生产环境的MySQL数据库响应时间突破了5秒阈值。作为值班工程师,我揉了揉惺忪的睡眼,迅速连上服务器。慢查询监控显示,原本毫秒级完成的订单查询操作,现在平均需要3.8秒才能返回结果。这不是简单的查询优化问题,而是一场需要深入系统底层的性能排查战役。

1. 问题现象与初步诊断

当数据库突然变慢时,大多数工程师的第一反应是检查慢查询日志。但这次的情况有些特殊:慢查询日志中出现的SQL都是经过充分优化的简单查询,且过去三个月从未出现过性能问题。更奇怪的是,数据库服务器的CPU和内存使用率都处于正常水平。

此时需要关注几个关键指标:

  • 系统负载uptime显示1分钟负载达到8.3(4核CPU)
  • CPU使用分布top命令中%wa(IO等待)持续在25%以上
  • 磁盘空间df -h显示数据分区仍有30%剩余空间

这些信号都指向同一个方向:磁盘IO可能成为瓶颈。但究竟是因为读写量突然增大,还是磁盘本身出现问题?我们需要更精确的工具来定位。

提示:当CPU的%wa指标持续高于5%时,通常意味着存储子系统存在性能问题

2. 部署sysstat工具集

在Linux系统中,iostat是分析磁盘IO问题的瑞士军刀。但很多生产环境默认并未安装这个工具,它属于sysstat工具包的一部分。以下是不同Linux发行版的安装方式:

# Ubuntu/Debian sudo apt update && sudo apt install -y sysstat # CentOS/RHEL sudo yum install -y sysstat # 验证安装 iostat -V

安装后需要确认数据收集服务已启用(特别是查看历史数据时):

# 检查服务状态 sudo systemctl status sysstat # 如果未运行,启用并启动服务 sudo systemctl enable --now sysstat

sysstat套装还包含其他实用工具:

  • sar:系统活动报告
  • mpstat:CPU统计
  • pidstat:进程级统计

3. 深入理解iostat输出

执行以下命令获取扩展IO统计信息:

iostat -xhd 1 3

这个命令的参数含义:

  • -x:显示扩展统计
  • -h:人类可读格式
  • -d:仅显示设备统计
  • 1 3:每秒刷新一次,共输出3次

典型输出示例(针对MySQL数据磁盘/dev/sdb):

Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz aqu-sz %util sdb 85.2 1363.5 12.1 12.4 8.32 16.0 24.3 310.4 18.7 43.5 3.21 12.8 1.02 78.3

关键指标解析:

指标组指标正常范围异常表现MySQL关联
读取rkB/s<500MB/s持续高位全表扫描或索引失效
写入wkB/s<200MB/s突发增长批量写入或日志刷新
延迟r_await<10ms>20ms查询响应变慢
队列aqu-sz<1>5IO堆积
利用率%util<70%>90%磁盘饱和

4. 关联MySQL诊断

有了磁盘IO的基础数据后,需要与MySQL内部状态进行交叉验证。以下是关键操作序列:

-- 查看当前运行中的查询 SHOW PROCESSLIST; -- 检查InnoDB状态 SHOW ENGINE INNODB STATUS\G -- 查看打开的表和文件 SHOW OPEN TABLES WHERE In_use > 0;

同时检查MySQL的慢查询日志配置:

# 确认慢查询日志是否开启 mysql -e "SHOW VARIABLES LIKE 'slow_query_log%'" # 查看当前慢查询阈值(秒) mysql -e "SHOW VARIABLES LIKE 'long_query_time'"

将iostat数据与MySQL诊断结果关联分析:

  1. 如果rkB/s高但w/s低:
    • 可能发生全表扫描
    • 检查Handler_read%状态变量
  2. 如果wkB/s突然增长:
    • 可能在进行大事务提交
    • 检查Innodb_os_log_written变化
  3. 如果%util持续100%:
    • 磁盘可能成为瓶颈
    • 考虑升级存储或优化IO调度

5. 实战案例:订单查询变慢分析

回到开头的报警案例,通过以下步骤最终定位问题:

  1. iostat监控发现

    • rkB/s从平时的200kB/s升至1.3MB/s
    • r_await达到15ms(正常应<5ms)
  2. MySQL诊断显示

    • 大量SELECT * FROM orders WHERE user_id=?查询
    • Handler_read_next异常增高
  3. 联合分析

    • 检查发现user_id字段的索引因夜间维护任务意外删除
    • 所有用户查询都转为全表扫描
  4. 解决方案

    • 立即重建索引:ALTER TABLE orders ADD INDEX (user_id)
    • 优化维护脚本的锁策略
-- 重建索引前后性能对比 -- 重建前:0.5MB/s rkB/s, 15ms r_await -- 重建后: EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id=1000;

6. 高级技巧与长期监控

对于生产环境,建议建立系统化的监控方案:

实时监控脚本示例

#!/bin/bash # 每5秒记录一次IO和MySQL状态 while true; do timestamp=$(date +"%Y-%m-%d %H:%M:%S") iostat -xhd 1 1 | grep -A1 Device >> io.log mysql -e "SHOW GLOBAL STATUS LIKE 'Handler_read%'" >> mysql_stats.log echo "$timestamp" >> timestamp.log sleep 5 done

关键性能基线表

指标预警阈值紧急阈值相关MySQL变量
rkB/s>500kB/s>1MB/sHandler_read_next
wkB/s>300kB/s>600kB/sInnodb_data_writes
%util>70%>90%Innodb_buffer_pool_wait_free
aqu-sz>2>5Innodb_log_waits

对于长期优化,考虑以下方向:

  • 升级SSD存储
  • 调整InnoDB缓冲池大小
  • 优化LinuxIO调度器(如改为deadline)
  • 分离数据和日志到不同物理磁盘

7. 避坑指南:常见误判场景

在实际排查中,有几个容易忽视的陷阱:

  1. RAID卡的缓存效应

    • 硬件RAID卡可能掩盖真实的磁盘延迟
    • 解决方法:直接监控物理磁盘/dev/sdX而非逻辑卷
  2. SSD的特殊表现

    • %util可能不准确(并行IO)
    • 更应关注r_await/w_await
  3. 文件系统缓存干扰

    • 高频读取可能被缓存满足
    • 使用-p参数查看具体分区
  4. 云环境的限制

    • 云磁盘可能有突发性能限制
    • 需要检查云监控中的IOPS配额
# 查看块设备真实类型(识别SSD) lsblk -d -o name,rota

在一次金融系统的性能危机中,我们发现虽然iostat显示磁盘利用率只有60%,但实际业务已经出现严重延迟。最终定位到是RAID卡电池故障导致回写缓存被禁用,使得写入性能骤降。这个案例告诉我们:工具数据需要结合硬件状态综合判断

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询