当前位置:首页>Linux>Linux I/O 栈深度解析:揭开 iowait 过高的真相

Linux I/O 栈深度解析:揭开 iowait 过高的真相

  • 2026-07-02 16:44:37
Linux I/O 栈深度解析:揭开 iowait 过高的真相

问题背景

线上服务器监控报警,CPU us 不高,但 iowait 高达 40%、50%,磁盘 util 100%。这时候工程师的第一反应往往是"磁盘坏了",但实际情况远比这复杂。iowait 高只是现象,背后可能藏着 MySQL 慢查询、Docker 日志风暴、Nginx 写 access log、文件系统碎片、Swap 滥用、甚至是内核调度问题。

这篇文章从 Linux I/O 栈的全貌出发,讲清楚 iowait 到底是什么、不是什么、怎么一步步定位根因,最后给出常见的故障复盘案例。


Linux I/O 栈全貌:从应用到磁盘

Linux 的 I/O 路径是一层一层串起来的,每一层都有自己的队列、缓冲和调度逻辑。理解这个栈,是排查 I/O 问题的前置条件。

第 1 层:应用层

应用通过系统调用发起 I/O 请求,最常见的是 read() 和 write()。应用程序本身不直接跟磁盘打交道,它只管写文件描述符。具体怎么写、写到哪块磁盘、由内核决定。

常见的 I/O 发起方:

  • MySQL:InnoDB 的脏页刷新、binlog 写入、redo log 刷盘
  • Nginx/Apache:access log、error log 写入
  • Docker:容器日志、存储层写
  • Python/Java 进程:业务日志、文件缓存
  • 系统守护进程:rsyslog、auditd

第 2 层:VFS(虚拟文件系统层)

VFS 是 Linux 内核提供的一层抽象,它统一了不同文件系统的接口。无论你用的是 ext4、XFS、NFS 还是 tmpfs,在应用层看来都是统一的 open()read()write() 接口。

VFS 的核心数据结构:

  • struct file:已打开文件的抽象
  • struct dentry:目录项缓存
  • struct inode:文件元数据
  • struct super_block:文件系统超级块

VFS 层还有一个关键机制:页缓存(Page Cache)。所有文件的读写都会经过页缓存。写操作默认是"写回"(write-back)模式:数据先写入页缓存,之后由内核线程异步刷到磁盘。这意味着 write() 系统调用通常会立即返回,但数据还没真正落盘。

第 3 层:具体文件系统(ext4/XFS/btrfs)

文件系统层负责把文件操作翻译成对底层块设备的请求。它要管理:

  • inode 和 block 的分配
  • 元数据的组织(目录结构、文件大小、时间戳)
  • 块寻址和扩展
  • 文件系统的日志(ext4 的 journal)

不同文件系统在 I/O 调度策略、日志模式、空间分配方式上有显著差异,这会直接影响 I/O 性能表现。

第 4 层:通用块设备层(Block Layer)

这是 I/O 栈中最复杂的一层。Block Layer 接收来自文件系统的块请求(bio),并负责:

  • I/O 调度:把多个相邻扇区的请求合并,减少磁盘寻道次数
  • 请求排队:不同进程的 I/O 请求进入同一个队列
  • 调度算法选择:CFQ、Deadline、NOOP、MQ-Deadline(blk-mq)

Linux 4.13 之后默认使用 mq-deadline,之前默认是 CFQ。调度算法的选择对 I/O 延迟影响很大。

关键数据结构:

  • struct bio:代表一个 I/O 请求
  • struct request:经过调度器合并后的磁盘请求
  • struct request_queue:请求队列

第 5 层:设备驱动层

设备驱动把块请求翻译成针对具体硬件的操作指令。机械硬盘(HDD)走 SCSI/SATA 协议,SSD 走 NVMe 协议,虚拟化环境走 virtio-blk 或 NVMe 模拟。

设备驱动的性能差异:

  • HDD:受寻道时间和转速限制,顺序读尚可,随机 I/O 极差
  • SATA SSD:受 SATA 通道带宽限制,顺序读约 550MB/s
  • NVMe SSD:走 PCIe 通道,延迟低、并发强,顺序读可达数 GB/s
  • 虚拟磁盘:受宿主机 I/O 队列和物理磁盘双重影响

第 6 层:物理磁盘

最终的存储介质。机械硬盘有磁头寻道、盘片旋转的物理限制;SSD 有读写放大、NAND 颗粒寿命的问题。


iowait 到底是什么

iowait 是 top 和 vmstat 输出中的一个指标,全称是 "I/O wait"。它表示 CPU 处于空闲状态,但有未完成的 I/O 请求正处于不可中断的等待状态。

理解 iowait 有几个关键点:

iowait 不等于磁盘 I/O 繁忙

iowait 高不等于磁盘 util 高。如果只有 1 个 CPU 核心的 iowait 高,而其他核心忙碌,整体 iowait 会被均摊,看起来不高但磁盘已经很繁忙。反过来,iowait 高也不一定是磁盘慢——可能是 NFS、tmpfs、内存分配等待等场景。

iowait 是 CPU 级别的指标

iowait 是从 CPU 视角看的指标。具体来说:

iowait = CPU 在非空闲状态(user/nice/system)之外,剩余时间中花在 I/O 等待上的比例

如果你有 8 核 CPU,其中 1 核 100% iowait,剩下 7 核 0%,top 显示的整体 iowait 大约是 12.5%。所以看到整体 iowait 20% 时,实际上可能是 1 核 100% iowait(4 核机器)或者 2 核全满(8 核机器)。

iowait 高的本质是 CPU 饿着

iowait 高的意思是:CPU 想干活,但活被 I/O 卡住了,只能等。CPU 本身没有损坏,但利用率上不去,系统吞吐量下降。

iowait 和 CPU idle 的区别

  • CPU idle:CPU 没事干,没有任何工作
  • iowait:CPU 没事干,但有 I/O 请求正在等待

两者在 top 里都显示为 idle,但含义完全不同。一个是系统负载极低,一个是系统被 I/O 阻塞了。


排查工具链:从宏观到微观

排查 iowait 问题的工具有好几个,每个工具关注不同的层级。

1. vmstat:看整体趋势

# vmstat 1:每秒采样一次vmstat 1 10

输出示例:

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st 2  3      0 812340 123456 4567890    0    0  1200   500  3000  4500  5  3  0 92  0

关键列:

  • r:运行队列长度,待运行的进程数
  • b:不可中断睡眠状态的进程数(通常是被 I/O 阻塞)
  • bi(blocks in):从磁盘读入的块数/秒
  • bo(blocks out):写入磁盘的块数/秒
  • wa(wait I/O):iowait 占用的 CPU 百分比

重点关注:若 b 列长期大于 0,说明有进程被阻塞在 I/O 上。若 wa 长期高于 30%,说明 iowait 是主要瓶颈。

2. iostat:看磁盘 I/O 细节

# 安装 sysstat 包# CentOS: yum install sysstat# Ubuntu: apt install sysstat# 基本用法:-x 显示扩展信息,-k 以 KB 为单位,1 表示每秒iostat -xzk 1 5

输出示例:

Linux 5.4.0-xxxx (hostname)     05/19/2026     _x86_64_        (8 CPU)avg-cpu:  %user   %nice %system %iowait  %steal   %idle          3.21    0.00    1.45   45.23    0.00   50.11Device:   rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s  avgrq-sz avgqu-sz   await r_await w_await  svctm  %utilsda         0.00     12.00    0.00   120.00     0.00  16384.00   272.73    45.00  375.00    0.00  375.00   8.26  99.20

重点字段解读:

  • %util:设备利用率,接近 100% 说明磁盘已经饱和。这是判断磁盘是否是瓶颈的最直接指标
  • await:平均 I/O 响应时间(毫秒),包括排队时间和实际服务时间。
  • avgqu-sz:平均队列深度,磁盘请求的排队长度。如果持续高于 4(机械硬盘)或者高于 32(SSD),说明 I/O 超过了磁盘处理能力。
  • r_await / w_await:读写分离的平均响应时间。
  • svctm(service time):平均服务时间,已经废弃(不可靠),仅做参考。
  • rrqm/s / wrqm/s:每秒合并的读写请求数。合并越多,效率越高。

实战判断

  • %util 接近 100% 且 await 很高 → 磁盘本身是瓶颈
  • %util 接近 100% 但 await 很低 → 磁盘性能很好但请求太多,块层排队严重
  • %util 不高但 iowait 高 → 可能是 NFS、内存压力、或 CPU 层面的等待

3. iotop:定位具体进程

# 需要 root 权限iotop -o -b -n 2 -d 5

参数说明:

  • -o:只显示有 I/O 活动的进程
  • -b:批处理模式(非交互)
  • -n 2:刷新 2 次
  • -d 5:每次间隔 5 秒

输出示例:

Total DISK READ:        0.00 B/s | Total DISK WRITE:      16.39 G/sActual DISK READ:        0.00 B/s | Actual DISK WRITE:      16.39 G/s  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO    COMMAND18123 be/4 mysql       0.00 B/s   16.39 G/s    0.00 %  99.99 % mysqld18234 be/3 root         0.00 B/s    0.00 B/s    0.00 %   0.00 % kworker/u256:2

重点IO 列显示该进程的 I/O 占用百分比。如果 MySQL 的 IO 列接近 100%,基本可以确定是数据库的 I/O 导致的问题。

4. pidstat:进程级别 I/O 统计

# 查看每个进程的 I/O 统计,每秒一次pidstat -d 1 5

输出示例:

Linux 5.4.0-xxxx (hostname)     05/19/2026     _x86_64_        (8 CPU)03:15:10 PM     UID       PID     kB_rd/s     kB_wr/s    iodelay  command03:15:11 PM       0     18123      0.00  16384000.00         0  mysqld03:15:11 PM       0     18234      0.00       120.00         0  rsyslogd
  • kB_rd/s:每秒读取 KB 数
  • kB_wr/s:每秒写入 KB 数
  • iodelay:I/O 延迟(以时钟周期计),反映进程等待 I/O 的时间
  • command:进程名

iodelay 越大,说明进程花在等待 I/O 上的时间越多。

5. /proc/diskstats:原始磁盘统计

cat /proc/diskstats

这是 iostat 数据的来源。如果需要自定义监控或者写脚本采集,可以用这个接口。

输出字段(按顺序):

  1. 设备号(major:minor)
  2. 设备名
  3. 读完成数
  4. 读合并数
  5. 读扇区数
  6. 读花费时间(毫秒)
  7. 写完成数
  8. 写合并数
  9. 写扇区数
  10. 写花费时间(毫秒)
  11. I/O 当前进度(正在进行中的 I/O)
  12. I/O 花费时间(毫秒,累计值)
  13. Weighted I/O time(累计 I/O 时间,含排队)

计算平均 I/O 响应时间:

(总 I/O 时间 / (读完成数 + 写完成数)) = 平均每次 I/O 的毫秒数

6. blktrace:追踪每个 I/O 请求

如果普通工具不够用,需要看每个 I/O 请求的细节,用 blktrace:

# 安装:yum install blktrace 或 apt install blktrace# 对特定设备追踪 10 秒blktrace -d /dev/sda -o /tmp/blktrace -w 10# 分析结果blkparse -i /tmp/blktrace -d | head -50

blktrace 可以看到每个 I/O 请求从应用发出、到 VFS、到块设备层的完整耗时分布。这个工具一般用于深度性能分析,生产环境慎用,会产生大量数据并影响性能。

7. free 和 /proc/meminfo:看内存压力

free -hcat /proc/meminfo | grep -E "^(MemTotal|MemFree|MemAvailable|Cached|Buffers|SwapTotal|SwapFree|SwapCached)"

内存压力会导致两个 I/O 相关问题:

  • Swap 使用:如果 SwapFree 持续下降,说明系统在使用 Swap,而 Swap 在磁盘上,会产生大量 I/O
  • Page Cache 回收:内存紧张时,内核会回收 Page Cache,导致原本可以通过缓存满足的读 I/O 变成磁盘直接读

检查 Swap 是否在大量使用:

# 看 Swap 使用情况vmstat 1 10 | awk '{print $2,$3,$4}'# 如果 si(swap in)和 so(swap out)长期不是 0,说明在换页

常见根因与排查路径

根因一:MySQL InnoDB 脏页刷盘

MySQL InnoDB 有自己的缓存池(Buffer Pool),数据页在内存中修改后变成脏页,由后台线程定期刷到磁盘。如果脏页积累过多或者磁盘写入速度跟不上, InnoDB 的 page_cleaner 线程会产生大量 I/O。

排查步骤

  1. 看 MySQL 的 I/O 写入量:
pidstat -d 1 5 -p $(pgrep -x mysqld)
  1. 看 InnoDB 脏页状态:
-- 登录 MySQLmysql -u root -p-- 查看脏页比例和刷新状态SHOWENGINEINNODBSTATUS\G-- 关注以下指标:-- Pages made flushd:累计页刷新数-- InnoDBBufferPool 的脏页比例
  1. 看 innodb 相关配置:
-- 查看关键参数SHOWVARIABLESLIKE'%innodb%flush%';SHOWVARIABLESLIKE'innodb_max_dirty_pages_pct';SHOWVARIABLESLIKE'innodb_buffer_pool_pages_dirty';

关键参数说明:

  • innodb_max_dirty_pages_pct:脏页比例上限,默认 75(MySQL 5.6),超过这个比例会强制刷新
  • innodb_io_capacity:InnoDB 能承受的 I/O 吞吐量上限,默认 200(机械硬盘),SSD 应该设置更高
  • innodb_flush_method:刷新方式,O_DIRECT(绕过 OS 页缓存)或 fsync(通过 OS 页缓存)

修复方案

# 方法1:调整 innodb_io_capacity(如果是 SSD)# 在 my.cnf 中添加或修改:# innodb_io_capacity = 2000    # SSD 推荐 2000-10000# innodb_io_capacity_max = 4000# 方法2:增加 Buffer Pool 大小,减少磁盘访问# innodb_buffer_pool_size = 16G   # 建议设置为可用内存的 60-80%# 方法3:调整脏页刷新策略# innodb_max_dirty_pages_pct = 50  # 降低阈值,更频繁刷新

风险提醒:修改 innodb_flush_method 或增大 innodb_io_capacity 可能导致 I/O 峰值更高,短期更卡。生产环境建议在低峰期操作,并提前备份配置。

根因二:Nginx/Apache 日志写入

每个 HTTP 请求都会写入 access log,如果 QPS 很高(几千甚至几万),日志写入 I/O 会非常频繁。

排查步骤

  1. 看 nginx 进程的写 I/O:
pidstat -d 1 -p $(pgrep -x nginx | tr '\n'',') 2 5
  1. 看日志文件的写入速度:
# -c 只显示变化的字节,-a 显示属性变化,-f 持续监控tail -f /var/log/nginx/access.log | pv -rate > /dev/null
  1. 看 nginx 配置中的日志设置:
# nginx.conf 中查看access_log /var/log/nginx/access.log combined buffer=16k flush=5s;error_log /var/log/nginx/error.log warn;

修复方案

# 方案1:关闭 access log(不推荐生产环境,但临时救火有效)access_log off;# 方案2:降低日志级别,只记录 erroraccess_log /var/log/nginx/access.log error;# 方案3:开启日志缓冲,减少系统调用access_log /var/log/nginx/access.log combined buffer=64k gzip=4;# 方案4:日志写入 tmpfs(内存文件系统),避免磁盘 I/O# 在 /etc/fstab 中添加:# tmpfs /var/log/nginx tmpfs defaults,size=512m 0 0# 注意:重启后日志会丢失,需要定期同步到磁盘# 方案5:使用 syslog 协议将日志发送到远程日志服务器access_log syslog:server=192.168.1.100:514,facility=local7,tag=nginx,severity=info combined;

验证方式

# 重载 nginx 配置nginx -s reload# 确认配置生效nginx -t# 之后观察 iostat,看 %util 是否下降

根因三:Docker 容器日志

Docker 容器的日志默认由 dockerd 接收并写入 /var/lib/docker/containers/<container-id>/<container-id>-json.log。如果容器 stdout 输出很多,日志文件会快速膨胀,撑爆磁盘并产生大量 I/O。

排查步骤

  1. 看 Docker 日志文件大小:
find /var/lib/docker/containers -name "*-json.log" -exec ls -lh {} \; | sort -k5 -h | tail -20
  1. 看 dockerd 进程的 I/O:
pidstat -d 1 -p $(pgrep -x dockerd) 2 5
  1. 看具体容器的日志量:
# 看容器最近 100 行日志的行数增长速率watch "docker logs --tail 100 <container-id> 2>&1 | wc -l"

修复方案

# 方案1:限制容器日志大小(在 docker-compose.yml 中)# docker-compose.ymllogging:  driver: "json-file"  options:    max-size: "50m"# 单个日志文件最大 50MB    max-file: "5"# 最多保留 5 个文件# 方案2:限制容器日志直接写入系统日志(降低 dockerd 压力)# /etc/docker/daemon.json{"log-driver""json-file","log-opts": {"max-size""50m","max-file""5"  },"storage-driver""overlay2"}# 修改后重启 dockerdsystemctl restart dockerd# 方案3:手动清理历史日志(高风险,需确认容器正常运行)# 先停止容器日志写入# truncate -s 0 /var/lib/docker/containers/<id>/*-json.log# 方案4:改用 journald 日志驱动# /etc/docker/daemon.json{"log-driver""journald","log-opts": {}}# 之后重启 dockerdsystemctl restart dockerd

风险提醒:修改 dockerd 配置会重启 Docker 服务,导致所有容器停止。生产环境需要在维护窗口操作,提前通知用户,并确认容器支持重启后自动拉起(使用 restartpolicy)。

根因四:文件系统碎片与日志模式

ext4 文件系统在频繁的小文件写入后会产生碎片,导致文件读取时磁头移动次数增加,I/O 延迟上升。

排查步骤

  1. 查看文件系统的碎片情况:
# 安装 e2fsprogs 包yum install e2fsprogs -y# 查看 ext4 文件系统碎片e2fsck -n /dev/sda1 2>&1 | grep -i fragment# 或者用 debugfs 查看debugfs -R "frag /" /dev/sda1 2>/dev/null
  1. 查看文件系统日志模式:
dumpe2fs /dev/sda1 | grep -i "journal mode"tune2fs -l /dev/sda1 | grep "Journal"

ext4 的日志模式:

  • journal:所有数据写入前先写日志,最安全但最慢
  • ordered(默认):只记录元数据日志,数据写入在元数据提交之后
  • writeback:不记录数据,只记录元数据,最快但不安全

修复方案

# 方法1:在线调整 ext4 日志模式为 writeback(提升写入性能)tune2fs -o journal_data_writeback /dev/sda1tune2fs -O "^has_journal" /dev/sda1tune2fs -O "has_journal" /dev/sda1# 注意:调整为 writeback 后,如果突然断电可能丢失数据# 确保有 UPS 和硬件 RAID# 方法2:对于 XFS 文件系统,看是否可以优化# XFS 日志默认在外置设备上,性能更好# 方法3:定期碎片整理(需要卸载文件系统或者单用户模式)# CentOS 7 以后:umount /dataxfs_frags /dev/sda2   # 检查碎片xfs_fsr /dev/sda2      # 碎片整理,可能需要数小时mount /data

风险提醒:修改文件系统参数和碎片整理都需要谨慎操作。生产环境建议先在测试环境验证,并确保有完整备份。碎片整理期间性能会严重下降。

根因五:Swap 使用

当物理内存耗尽,系统会把不活跃的内存页换出到 Swap 空间。如果 Swap 所在的磁盘是机械硬盘,大量的换入换出会导致严重的 I/O 风暴。

排查步骤

  1. 查看 Swap 使用情况:
# 确认哪个设备是 Swapswapon -s# 确认 Swap 使用量和换入换出速率vmstat 1 10# 看具体哪些进程在换入换出cat /proc/$(pgrep -x mysqld)/status | grep -i swap
  1. 确认 Swap 是否在持续增长:
# 每秒采样一次,监控 si(swap in)和 so(swap out)列vmstat 1 | awk '{print $3,$4,$7,$8}'
  1. 看内存分配情况:
# 看哪些进程占用的内存最多ps aux --sort=-%mem | head -20

修复方案

# 方案1:临时关闭 Swap(仅限内存充足时)swapoff -a    # 关闭所有 Swapswapon -a     # 重新开启# 方案2:降低 Swap 优先级(让系统尽量用物理内存)# 在 /etc/sysctl.conf 中添加:vm.swappiness = 10    # 默认 60,值越低越少使用 Swap# 立即生效:sysctl -p# 方案3:把 Swap 放到 SSD 上# 创建一个 SSD 上的 Swap 文件fallocate -l 8G /mnt/ssd/swapfilechmod 600 /mnt/ssd/swapfilemkswap /mnt/ssd/swapfileswapon /mnt/ssd/swapfile# 在 /etc/fstab 中添加:# /mnt/ssd/swapfile none swap sw 0 0# 方案4:确认 MySQL 的内存配置是否合理# MySQL 5.7: 确保 innodb_buffer_pool_size <= 物理内存 * 0.8# 避免所有进程内存之和超过物理内存

根因六:批量写入任务

运维过程中常见的定时任务:备份脚本、rsync 同步、日志切割(logrotate)、数据库全量导出、大文件压缩等。这些任务往往在半夜或高峰期跑,产生大量 I/O 把正常业务拖垮。

排查步骤

  1. 看谁在写磁盘:
# 高频观察whiletruedoecho"=== $(date) ==="; ps aux --sort=-%mem | awk '{print $2,$3,$4,$11}' | head -15; sleep 3; done
  1. 看定时任务:
# 看 crontabcrontab -lcat /etc/crontabls -la /etc/cron.d/
  1. 看最近修改过的文件:
# 找出最近 1 分钟内写入超过 100MB 的文件find / -type f -mmin -1 -size +100M 2>/dev/null

修复方案

# 方案1:使用 ionice 限制 I/O 优先级# cron 任务中使用 ionice 限制0 2 * * * ionice -c 3 -n 7 /backup/backup.sh# ionice 参数说明:# -c 3:空闲类(idle),只有磁盘空闲时才执行# -c 2:最佳努力类(best effort),可以设置 -n 优先级(0-7,越低越优先)# -c 1:实时类(real time),最高优先级,生产环境慎用# 方案2:使用 cgroups 限制 I/O# 创建 cgroup 限制写入带宽mkdir /sys/fs/cgroup/blkio/limitedecho"8:0 1048576" > /sys/fs/cgroup/blkio/limited/blkio.throttle.write_bps_deviceecho $(pgrep -f backup.sh) > /sys/fs/cgroup/blkio/limited/tasks# 方案3:使用 rsync 的限速参数rsync -avz --bwlimit=10240 /source/ /dest/# 方案4:调整 logrotate 时间# /etc/logrotate.conf 中把 daily 改成 weekly 或 monthly# 减少日志切换频率# 方案5:备份任务安排到低峰期# 安排在凌晨 3-5 点,业务最空闲的时段0 3 * * * ionice -c 3 /backup/backup.sh >> /var/log/backup.log 2>&1

实战案例:从 iowait 高到定位 MySQL 脏页刷新

案例背景

某台 16 核 64GB 内存的物理机,运行 MySQL 5.7.30,数据库大小约 300GB。最近一周监控显示:

  • CPU iowait 从平时的 5% 上升到 35-45%
  • iostat 显示 sda 的 %util 持续在 95% 以上
  • await 从 5ms 上升到 400ms 以上
  • 数据库查询延迟明显上升,从 10ms 上升到 500ms+

第 1 步:初步判断

先用 top 看整体 CPU:

top -b -n 1
%Cpu(s):  3.2 us,  1.5 sy,  0.0 ni, 58.2 id, 37.1 wa,  0.0 hi,  0.0 si,  0.0 st

37% 的 iowait 确认了问题。再用 iostat 看磁盘:

iostat -xzk 1 5
Device:  rrqm/s  wrqm/s   r/s   w/s    rkB/s    wkB/s  avgrq-sz avgqu-sz   await r_await w_await  svctm %utilsda         0.00   12.00  0.00 120.00     0.00  16384.00   272.73   45.00  375.00    0.00  375.00  8.26 99.20

%util 99.20%,w/s 120 次/秒,写入 16MB/s,avgqu-sz 45,说明队列严重积压,写 I/O 响应时间高达 375ms。

第 2 步:定位进程

用 iotop 找元凶:

iotop -o -b -n 3 -d 3
Total DISK READ:        0.00 B/s | Total DISK WRITE:      16.39 G/s  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO    COMMAND18123 be/4 mysql       0.00 B/s   16.39 G/s    0.00 %  99.99 % mysqld

mysqld 进程占了 99.99% 的 I/O 带宽,写入速度 16.39 G/s(这个数字异常大,说明单位可能是块设备报的累计值,实际写入速率需要用 pidstat 确认)。

第 3 步:分析 MySQL I/O 来源

登录 MySQL 查看状态:

mysql> SHOWENGINEINNODBSTATUS\G

找到关键段落:

---LOG---Log sequence number          28495678912Log flushed up to            28495456789Pages flushed up to          28494000000Last checkpoint at           28493000000100 pending log writes, 200 pending chkp writes

100 个待写入的日志写操作,200 个待检查点的脏页刷新。这就是 I/O 压力的来源。

再看 InnoDB 配置:

mysql> SHOWVARIABLESLIKE'innodb_%flush%';+---------------+-------+| Variable_name | Value |+---------------+-------+| innodb_flush_log_at_trx_commit | 1       || innodb_flush_method             | O_DIRECT |+---------------+-------+mysql> SHOWVARIABLESLIKE'innodb_io_capacity%';+------------------------+-------+| Variable_name          | Value |+------------------------+-------+| innodb_io_capacity     | 200   || innodb_io_capacity_max | 2000  |+------------------------+-------+mysql> SHOWSTATUSLIKE'Innodb_buffer_pool_pages_dirty';+------------------------------+-------+| Variable_name                | Value |+------------------------------+-------+| Innodb_buffer_pool_pages_dirty | 20480 |+------------------------------+-------+

发现问题:

  • innodb_io_capacity 只有 200,这个值是给机械硬盘设计的,对于 NVMe SSD 来说严重偏低
  • Innodb_buffer_pool_pages_dirty 有 20480 个脏页,每个 16KB,总共约 320MB 脏页等待刷新
  • innodb_flush_log_at_trx_commit = 1,每次事务提交都会刷 redo log,I/O 压力会比较大

第 4 步:确认根因

综合以上信息,根因分析:

  1. innodb_io_capacity = 200 严重偏低,后台刷新线程每次只能处理很少的脏页
  2. 脏页积累速度(业务写入) > 脏页刷新速度(innodb_io_capacity 限制)
  3. 脏页堆积到 innodb_max_dirty_pages_pct 阈值后,InnoDB 被迫强制刷新,阻塞前台查询
  4. 大量写 I/O 积压在块层队列中,avgqu-sz 达到 45,await 高达 375ms

第 5 步:修复方案

风险评估:修改 innodb_io_capacity 是在线参数,可以动态调整,不需要重启数据库,风险可控。但调整后短时间内刷新速度加快,磁盘 I/O 会更集中。

操作步骤

-- 先备份当前配置mysqld --help --verbose | grep my.cnf-- 备份 my.cnfcp /etc/my.cnf /etc/my.cnf.bak.$(date +%Y%m%d)-- 动态调整参数(当前 session 生效)SETGLOBAL innodb_io_capacity = 2000;SETGLOBAL innodb_io_capacity_max = 4000;-- 确认生效SHOWVARIABLESLIKE'innodb_io_capacity%';-- 动态调整 innodb_max_dirty_pages_pct(MySQL 5.7 可在线调整)SETGLOBAL innodb_max_dirty_pages_pct = 60;-- 写进配置文件,永久生效-- 在 [mysqld] 段添加:-- innodb_io_capacity = 2000-- innodb_io_capacity_max = 4000
# 编辑 my.cnfvim /etc/my.cnf# 在 [mysqld] 段添加或修改[mysqld]innodb_io_capacity = 2000innodb_io_capacity_max = 4000innodb_max_dirty_pages_pct = 60

第 6 步:验证效果

修改后观察:

# 1. 监控 iowait 是否下降vmstat 1 30# 2. 监控磁盘 util 是否下降iostat -xzk 1 30# 3. 监控脏页是否在正常下降mysql -u root -p -e "SHOW STATUS LIKE 'Innodb_buffer_pool_pages_dirty';" every 10s

预期效果(5-10 分钟后):

  • iowait 从 35-45% 下降到 5-10%
  • %util 从 95% 下降到 30-50%
  • await 从 400ms 下降到 10-30ms
  • avgqu-sz 从 45 下降到 5 以下
  • Innodb_buffer_pool_pages_dirty 稳定在 2000 以下

第 7 步:回滚方案

如果调整后出现其他问题(比如 I/O 峰值把磁盘带宽占满影响其他服务),立即回滚:

SETGLOBAL innodb_io_capacity = 200;SETGLOBAL innodb_io_capacity_max = 2000;

同时还原 my.cnf:

cp /etc/my.cnf.bak.$(date +%Y%m%d) /etc/my.cnfsystemctl restart mysqld  # 需要在维护窗口操作

诊断流程图:iowait 排查 7 步法

┌─────────────────────────────────────────────┐│ 1. vmstat 1 10                               ││    发现 b 列 > 0 或 wa 列持续 > 20%          │└──────────────────┬──────────────────────────┘                   │                   ▼┌─────────────────────────────────────────────┐│ 2. iostat -xzk 1 5                          ││    判断 %util 是否 > 80%                     ││    判断 avgqu-sz 是否过高                    ││    判断是读还是写为主                        │└──────────────────┬──────────────────────────┘                   │                   ▼┌─────────────────────────────────────────────┐│ 3. iotop -o -b -n 3                         ││    找出具体是哪个进程在产生 I/O               │└──────────────────┬──────────────────────────┘                   │                   ▼┌─────────────────────────────────────────────┐│ 4. pidstat -d 1 -p <PID>                    ││    确认进程的 I/O 读写速率和延迟              │└──────────────────┬──────────────────────────┘                   │                   ▼┌─────────────────────────────────────────────┐│ 5. 进一步分析:                              ││    - MySQL: SHOW ENGINE INNODB STATUS        ││    - Nginx: access log 配置检查              ││    - Docker: docker logs / 容器日志大小      ││    - Swap: free + vmstat 看 si/so           ││    - 定时任务: crontab -l                   │└──────────────────┬──────────────────────────┘                   │                   ▼┌─────────────────────────────────────────────┐│ 6. 确认根因后,制定修复方案                   ││    - 调整参数(在线 or 维护窗口)             ││    - 关闭/限流/迁移 I/O 来源                 ││    - 升级硬件(SSD)                         │└──────────────────┬──────────────────────────┘                   │                   ▼┌─────────────────────────────────────────────┐│ 7. 验证效果                                  ││    - 监控 iostat / vmstat 趋势              ││    - 业务延迟是否恢复正常                    ││    - 准备回滚方案                            │└─────────────────────────────────────────────┘

高风险操作汇总

操作
风险等级
风险描述
缓解措施
修改 innodb_flush_method
切换刷盘策略,可能导致数据丢失或 I/O 暴增
确保 UPS、RAID、有备份
调整 innodb_io_capacity
调高后刷新更快但短期 I/O 更集中
先在从库测试,低峰期操作
关闭 Swap
内存不足时无兜底,可能 OOM
先确认物理内存充足
修改 dockerd 日志配置
重启 Docker,所有容器中断
确认容器有 restartpolicy
在线碎片整理
整理期间性能严重下降
单用户模式,低峰期操作
truncate 容器日志
日志丢失,排查问题困难
先 docker logs 导出重要日志
ionice 限制 I/O
可能导致任务执行时间变长
确保 cron 有合理的超时设置

内核参数调优:控制 I/O 行为

Linux 内核提供了大量可调参数(sysctl),可以控制 I/O 行为。合理调整这些参数,可以从系统层面改善 I/O 性能或限制 I/O 滥用。

1. 调整内核 I/O 调度器

调度器决定了请求如何排序和合并。不同调度器适合不同场景:

# 查看当前调度器cat /sys/block/sda/queue/scheduler# noop [deadline] cfq  输出中 [] 包围的是当前值# deadline 调度器:适合数据库、SSD、随机读写场景# cfq 调度器:适合桌面系统和通用 Linux,对实时性要求高的场景表现差# noop 调度器:适合 SSD、虚拟机、RAID 卡带缓存的场景# mq-deadline 调度器:blk-mq 版本的 deadline,更好的并发支持# 临时修改(重启后失效)echo deadline > /sys/block/sda/queue/scheduler# 永久修改(在 udev 规则或启动脚本中)# /etc/udev/rules.d/60-io-scheduler.rulesACTION=="add|change", SUBSYSTEM=="block", KERNEL=="sd[a-z]", ATTR{queue/scheduler}="deadline"

调度器选择建议

  • 机械硬盘(HDD):deadline 或 cfq
  • SATA SSD:deadline 或 noop
  • NVMe SSD:noop 或 mq-deadline
  • 虚拟化环境:noop(virtio-blk 或 pvscsi 本身有调度)
  • 数据库服务器:deadline(避免 cfq 的"公平"调度导致的延迟不稳定)

2. 调整块设备队列深度

# 查看队列深度cat /sys/block/sda/queue/nr_requests# 默认 128,适合机械硬盘# SSD 和 RAID 卡可以设置为 512-1024# 临时调整echo 512 > /sys/block/sda/queue/nr_requests# 永久修改(在 /etc/rc.local 或 systemd service 中)# echo 512 > /sys/block/sda/queue/nr_requests

队列深度过小会导致高并发下请求排队不足,队列深度过大会增加延迟。生产环境建议根据磁盘数量和并发连接数调整。

3. 调整 read_ahead_kb(预读)

# 查看预读大小(单位 KB)cat /sys/block/sda/queue/read_ahead_kb# 默认 128KB# 临时调整(适合顺序读多的场景,如数据仓库)echo 256 > /sys/block/sda/queue/read_ahead_kb# 永久修改# echo 256 > /sys/block/sda/queue/read_ahead_kb# 适合随机读多的场景(如数据库)可以降低预读echo 16 > /sys/block/sda/queue/read_ahead_kb

预读的作用是:当内核读取一个扇区时,提前把相邻的后续扇区也读入缓存。如果业务是大量顺序读(如备份、ETL),增大预读能显著提升吞吐。如果是随机读(如数据库),增大预读只会浪费 I/O 带宽。

4. 调整内核脏页刷新参数

内核的内存管理子系统会定期把脏页(已修改但未写回磁盘的页)刷新到磁盘。相关参数:

# 查看当前值cat /proc/sys/vm/dirty_background_ratio   # 脏页占可用内存的比例,默认 10cat /proc/sys/vm/dirty_ratio             # 强制同步的脏页比例,默认 20cat /proc/sys/vm/dirty_expire_centisecs  # 脏页被认为是"可刷新"的时间,单位是 0.01 秒,默认 3000(30 秒)cat /proc/sys/vm/dirty_writeback_centisecs # 后台刷新线程运行间隔,默认 500(5 秒)# 临时调整(降低脏页比例,适合数据库服务器)echo 5 > /proc/sys/vm/dirty_background_ratioecho 10 > /proc/sys/vm/dirty_ratio# 永久修改(在 /etc/sysctl.conf 中)# vm.dirty_background_ratio = 5# vm.dirty_ratio = 10# vm.dirty_expire_centisecs = 3000# vm.dirty_writeback_centisecs = 500

重要:这些参数直接影响数据库的 I/O 模式。如果 dirty_background_ratio 太高,后台刷新线程会在磁盘已经很繁忙时继续往磁盘写数据,导致 I/O 拥塞。如果 dirty_ratio 太高,当进程写入大量数据时,可能在最糟糕的时机触发强制刷盘(此时进程被阻塞,用户请求积压)。

数据库服务器的推荐配置(MySQL/ PostgreSQL):

  • dirty_background_ratio = 5(更积极的后台刷新)
  • dirty_ratio = 10-15(更低的强制刷盘阈值)
  • dirty_expire_centisecs = 500(脏页 5 秒后就可被刷新,更快响应)

5. 开启 I/O 统计并实时监控

# 开启 I/O 延迟统计(需要内核支持 blk_mq)echo 1 > /sys/block/sda/queue/iotail_latency# 实时监控 I/O 延迟分布# 安装 bpftrace(高级工具,需要 root)# bpftrace -e 'kprobe:blk_account_io_start { @ = lhist(args->bytes, 0, 4096, 512); }'# 或者用 iostat 持续监控并记录iostat -xzk 1 >> /var/log/iostat.log &# 注意:这个日志会持续增长,需要 logrotate 处理

6. 限制单进程的 I/O 带宽

如果某个进程(如备份脚本)占用了过多 I/O,影响正常业务,可以用 cgroups v2 限制:

# 创建 IO 限制组(cgroups v2)mkdir -p /sys/fs/cgroup/io/limited# 限制 /dev/sda 的写入带宽为 50MB/secho"8:0 wbps=52428800" > /sys/fs/cgroup/io/limited/max.bps.write# 限制 IOPS 为 1000echo"8:0 wiops=1000" > /sys/fs/cgroup/io/limited/max.iops.write# 把备份进程加入限制组echo $(pgrep -f backup.sh) > /sys/fs/cgroup/io/limited/tasks# 监控限制效果cat /sys/fs/cgroup/io/limited/io.stat

实战案例 2:Nginx 日志写入导致的 iowait 飙升

案例背景

某台 4 核 8GB 内存的 Web 服务器,运行 Nginx,每天 QPS 约 2000 次。最近发现 iowait 经常在业务高峰期(上午 10-12 点)飙升到 30-40%,CPU idle 掉到 20%,导致部分 HTTP 请求超时。

第 1 步:初步排查

# 1. 看 CPU 状态top -b -n 1 | head -20# us 40%, sy 10%, wa 35%, id 15%# 2. 看磁盘 I/Oiostat -xzk 1 3# %util 接近 100%,w/s 200+,写为主# 3. 找进程iotop -o -b -n 5 -d 2

输出显示:Nginx 主进程的 IO 占比 80% 以上。

第 2 步:分析日志配置

# 看 Nginx 日志配置nginx -T | grep -A5 "access_log"

配置是:

access_log /var/log/nginx/access.log combined;error_log /var/log/nginx/error.log warn;

没有缓冲、没有压缩、没有限时刷新。每次请求都同步写日志。

第 3 步:修复方案

# 修改 nginx.confhttp {    # 开启日志缓冲,减少系统调用    log_format main '$remote_addr - $remote_user [$time_local] "$request" '                    '$status $body_bytes_sent "$http_referer" '                    '"$http_user_agent" "$http_x_forwarded_for"';    # access log 加缓冲,16KB 缓冲区,5 秒刷新一次    access_log /var/log/nginx/access.log main buffer=16k flush=5s;    # error log 用 info 级别,减少写入量    error_log /var/log/nginx/error.log info;    # 开启异步日志写入(需要配置缓冲)    # 注意:异步日志在进程崩溃时可能丢失最后几秒的日志}

第 4 步:验证

# 重载配置nginx -s reload# 观察 iostatiostat -xzk 1

重载后观察:

  • %util 从 100% 降到 30-40%
  • w/s 从 200+ 降到 40-60
  • iowait 从 35% 降到 5-10%
  • HTTP 请求延迟明显改善,P99 从 800ms 降到 150ms

第 5 步:更激进的方案(可选)

如果业务能接受日志丢失(短暂的服务中断不丢即可),可以写入 tmpfs:

# 在 /etc/fstab 中添加tmpfs /var/log/nginx tmpfs defaults,size=256m 0 0# 或者直接挂载mount -t tmpfs -o size=256m tmpfs /var/log/nginx# 将现有日志迁移cp /var/log/nginx/access.log /tmp/backup_access.log> /var/log/nginx/access.log   # 清空现有日志# 定期同步到磁盘(每分钟)# /etc/cron.d/sync-nginx-logs* * * * * root rsync -av /var/log/nginx/ /backup/nginx_logs/ >> /var/log/sync-nginx.log 2>&1

风险:tmpfs 中的数据在重启后会丢失。需要确保有定期同步机制,且在日志同步的窗口期内能接受最多 1 分钟的日志丢失。


实战案例 3:系统升级 SSD 后的 I/O 优化

背景

一台运行 3 年的物理服务器,从机械硬盘(7200 转 SATA)升级到 NVMe SSD。升级后运维团队期望 I/O 问题彻底消失,但实际观察发现 iowait 仍然存在,%util 仍然偏高。

问题分析

升级 SSD 后出现新问题,说明瓶颈从"磁盘物理速度"转移到了"其他层级"。可能的原因:

  1. 调度器仍然是 cfq:cfq 的设计基于"磁盘有寻道时间"的假设,SSD 没有寻道延迟,cfq 的公平调度策略反而增加了不必要的上下文切换和延迟。

  2. 队列深度不够:机械硬盘的队列深度通常很低,SSD 支持更高的队列深度,但内核默认值可能没有充分利用。

  3. 文件系统日志模式不合适:ext4 默认的 ordered 模式每次写数据前要先写日志,对于 SSD 这种快速设备,日志写入产生的额外 I/O 仍然占比不小。

诊断步骤

# 1. 确认 SSD 是否被识别为旋转设备cat /sys/block/sda/queue/rotational# 1 = 机械硬盘,0 = SSD# 2. 查看当前调度器cat /sys/block/sda/queue/scheduler# 如果是 cfq,SSD 也可能变慢# 3. 查看队列深度cat /sys/block/sda/queue/nr_requests# 默认 128,SSD 可以开到 512# 4. 查看 I/O 合并情况cat /sys/block/sda/queue/nr_requestsiostat -x 1 | grep sda# 如果 %util 仍然高但 r/s + w/s 不高,说明瓶颈在别处

优化方案

# 1. 切换到 noop 调度器(NVMe SSD 最适合)echo noop > /sys/block/sda/queue/scheduler# 2. 增大队列深度echo 512 > /sys/block/sda/queue/nr_requests# 3. 调整脏页刷新参数(对所有类型磁盘都有效)echo 5 > /proc/sys/vm/dirty_background_ratioecho 10 > /proc/sys/vm/dirty_ratioecho 1000 > /proc/sys/vm/dirty_writeback_centisecs# 4. 如果用 ext4,可以考虑切换到 XFS# XFS 在高并发写入时性能更好,日志管理更高效# 但迁移文件系统需要备份数据、重新格式化
# 永久化这些配置:/etc/rc.local 或 systemd servicecat > /etc/systemd/system/tune-ssd.service <<'EOF'[Unit]Description=Tune SSD I/O settingsAfter=local-fs.target[Service]Type=oneshotExecStart=/bin/bash -c 'echo noop > /sys/block/sda/queue/scheduler'ExecStart=/bin/bash -c 'echo 512 > /sys/block/sda/queue/nr_requests'ExecStart=/bin/bash -c 'echo 5 > /proc/sys/vm/dirty_background_ratio'ExecStart=/bin/bash -c 'echo 10 > /proc/sys/vm/dirty_ratio'[Install]WantedBy=multi-user.targetEOFsystemctl enable tune-ssd.servicesystemctl start tune-ssd.service

验证优化效果

# 用 fio 做基准测试yum install fio -y   # CentOS# apt install fio    # Ubuntu# 顺序写测试(64KB 块,4 线程,1GB 数据)fio --name=seqwrite --filename=/tmp/fio_test --size=1G \    --rw=write --bs=64k --numjobs=4 --iodepth=32 \    --ioengine=libaio --direct=1 --runtime=30 --time_based=1# 随机读测试(4KB 块,16 线程,1GB 数据)fio --name=randread --filename=/tmp/fio_test --size=1G \    --rw=randread --bs=4k --numjobs=16 --iodepth=64 \    --ioengine=libaio --direct=1 --runtime=30 --time_based=1# 查看结果中的 iops 和 lat 指标# NVMe SSD 在优化后,随机读 iops 应该达到 10 万以上# 延迟(clat)P99 应该低于 1ms

优化后实际效果:

  • %util 从 80-90% 降到 20-30%(消除了不必要的调度开销)
  • 延迟稳定性提升,P99 延迟从 5ms 降到 0.8ms
  • 吞吐量提升约 40%(队列深度增加后并发能力增强)

监控体系:从被动告警到主动预防

建立 I/O 基线

在系统正常时建立 I/O 基线,便于在异常时快速对比判断。

# 建立基线脚本(每日定时执行)#!/bin/bash# /usr/local/bin/io-baseline.shDATE=$(date +%Y%m%d_%H%M%S)OUTPUT_DIR="/var/log/io-baseline"mkdir -p $OUTPUT_DIR# 采集当前 I/O 状态{echo"=== $(date) ==="echo"--- vmstat ---"    vmstat 1 5echo"--- iostat ---"    iostat -x 1 5echo"--- disk usage ---"    df -hecho"--- inodes ---"    df -iecho"--- mount ---"    mount | grep "^/dev"echo"--- loadavg ---"    uptime} > $OUTPUT_DIR/baseline_$DATE.txt# 只保留最近 30 天find $OUTPUT_DIR -name "baseline_*.txt" -mtime +30 -delete

Prometheus + node_exporter 监控指标

在 Prometheus 中配置 node_exporter,可以采集以下 I/O 相关指标:

# prometheus.yml 中添加 node_exporterscrape_configs:-job_name:'node_exporter'static_configs:-targets:['localhost:9100']

关键查询:

# 平均 I/O 等待时间百分比(每台机器)100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)# 磁盘使用率node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}# 每台机器的 I/O util(需要 node_exporter 0.18+)rate(node_disk_io_time_seconds_total[5m]) * 100# 每台机器的写入吞吐量rate(node_disk_written_bytes_total[5m])

Grafana 面板配置

推荐的 Grafana 面板布局(从左到右,从上到下):

第一行:CPU 使用率分解(user、system、iowait、idle)第二行:磁盘 util(%util)和队列深度(avgqu-sz)第三行:读写吞吐量(r/s、w/s)和带宽(rkB/s、wkB/s)第四行:I/O 响应时间(await、r_await、w_await)第五行:内存使用率和 Swap 换入换出速率

告警规则配置:

# alertmanager.rulesgroups:-name:io_alertsrules:# iowait 持续 5 分钟高于 30%-alert:HighIOWaitexpr:100-(avgby(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m]))*100)>30for:5mlabels:severity:warningannotations:summary:"High iowait on {{ $labels.instance }}"description:"iowait is {{ $value }}% for more than 5 minutes"# 磁盘 util 持续 5 分钟高于 90%-alert:DiskUtilHighexpr:rate(node_disk_io_time_seconds_total[5m])*100>90for:5mlabels:severity:criticalannotations:summary:"Disk {{ $labels.device }} utilization is critical"

总结

iowait 只是一个症状指标,它告诉你"CPU 在等 I/O",但不会告诉你"谁在产生 I/O"。排查 iowait 的核心思路是:

  1. 先确认是否真的是磁盘问题:用 iostat 看 %util,如果磁盘利用率很低但 iowait 高,可能是 NFS、网络 I/O 或 CPU 层面的等待。

  2. 找到 I/O 产生者:用 iotop 和 pidstat 定位具体进程,不要凭感觉猜测。

  3. 分析 I/O 类型:是读还是写,是顺序还是随机,是元数据还是数据,这决定了修复方向。

  4. 理解每层 I/O 栈的特性:VFS 的页缓存、文件系统的日志模式、块层的调度算法、设备的物理限制,每一层都可能成为瓶颈。

  5. 修复时考虑全局:调高 InnoDB 的 I/O 容量可能解决了 MySQL 问题,但如果这台机器还有其他服务,可能把整台机器的 I/O 带宽占满,反而更糟。

  6. 永远准备回滚方案:改配置之前先备份,改完之后监控效果,如果变差立即回滚。

  7. 建立监控基线:在系统正常时建立 I/O 基线,异常时快速对比,缩短故障定位时间。

  8. 内核参数不是万能药:调度器、队列深度、脏页参数等系统级调优能提升性能,但无法替代应用层的 I/O 优化(如缓存、异步写入、批量操作)。

iowait 排查没有银弹,每一次都需要结合业务场景、硬件配置、负载特征综合判断。工具只是手段,工程师的分析思路才是核心。

文末福利

今天给大家分享一份超级牛掰的Linux学习笔记,足足有1456页!是一位Linux运维大佬整理分享的,分享是获得大佬同意的,大家有需要的尽管收藏起来!

笔记介绍

这份笔记非常全面且详细,从Linux基础到shell脚本,再到防火墙、数据库、日志服务管理、Nginx、高可用集群、Redis、虚拟化、Docker等等,与其说Linux学习笔记,不如说是涵盖了运维各个核心知识。

并且图文并茂,代码清晰,每一章下面都有更具体详细的内容,十分适合Linux运维学习参考!

笔记展示

笔记下载

扫描下方二维码,回复暗号1456页Linux笔记“,即可100%免费领取成功

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-03 08:28:46 HTTP/2.0 GET : https://f.mffb.com.cn/a/494619.html
  2. 运行时间 : 0.122522s [ 吞吐率:8.16req/s ] 内存消耗:4,814.98kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=2913ee7d32a7d938b04deb40d3bc6a94
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000586s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000937s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000416s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000281s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000709s ]
  6. SELECT * FROM `set` [ RunTime:0.000263s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000760s ]
  8. SELECT * FROM `article` WHERE `id` = 494619 LIMIT 1 [ RunTime:0.000715s ]
  9. UPDATE `article` SET `lasttime` = 1783038526 WHERE `id` = 494619 [ RunTime:0.008503s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.000447s ]
  11. SELECT * FROM `article` WHERE `id` < 494619 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000672s ]
  12. SELECT * FROM `article` WHERE `id` > 494619 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.002976s ]
  13. SELECT * FROM `article` WHERE `id` < 494619 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.007661s ]
  14. SELECT * FROM `article` WHERE `id` < 494619 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.014821s ]
  15. SELECT * FROM `article` WHERE `id` < 494619 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.008154s ]
0.125140s