Skip to content

pt-diskstats

GNU/Linux 上的交互式磁盘 I/O 监控工具,类似 iostat 但更详细、可交互。

语法

bash
pt-diskstats [OPTIONS] [FILES]

打印 GNU/Linux 的磁盘 I/O 统计。与 iostat 相比的优势:读写统计分开打印、列更多、 菜单驱动可交互、支持多种数据聚合方式、与 pt-stalk 集成良好、默认就"做对的事"(如隐藏空闲磁盘)。 非常适合快速下钻 I/O 性能问题、检查磁盘行为。

用法示例

pt-diskstats 是纯本机磁盘监控工具(读 /proc/diskstats),不连接数据库,命令可直接复制运行。它以交互方式循环刷新,按 q 退出;用 --iterations 可让它跑固定次数后自动结束、适合放进脚本。

场景:实时监控磁盘 I/O

排查磁盘瓶颈时,直接看实时读写、响应时间与排队情况(默认聚合所有磁盘与样本):

bash
pt-diskstats

场景:只看指定磁盘

只盯 sda 这一块盘,过滤掉其他设备:

bash
pt-diskstats --devices-regex sda

场景:加大采样间隔并带时间戳

录屏或记录排障过程时,每 5 秒刷新一次并显示 HH:MM:SS 时间戳:

bash
pt-diskstats --interval 5 --show-timestamps

场景:批处理采集固定次数

不想一直守着屏幕,让它采样 10 次(每次间隔 2 秒)后自动退出,输出可重定向存档:

bash
pt-diskstats --iterations 10 --interval 2

场景:只关注关键列

列太多看不过来时,用正则只保留设备名、繁忙度、读写响应时间与服务时间:

bash
pt-diskstats --columns-regex 'device|busy|rd_rt|wr_rt|qtime|stime'

场景:保存样本后期回放分析

先把采样落盘,之后用文件模式离线回放分析(也可把文件拷贝到别的机器上看):

bash
pt-diskstats --save-samples /data/diskstats.txt
pt-diskstats /data/diskstats.txt

功能说明

两种工作模式:

  • 默认模式:采集 /proc/diskstats 样本并按间隔打印格式化统计。
  • 文件模式:处理保存了 /proc/diskstats 样本的文件(可分析从其他机器采集的样本)。

两种模式都由按键交互控制,可以灵活地重新显示与切分数据。工具循环运行直到按 q 退出; 按 ? 弹出交互帮助菜单。程序不会打印所有块设备——从未观察到活动的设备会被隐藏(按 i 键切换)。

输出

输出列(读写各一组,另有汇总列):

说明
#ts依聚合模式而异:默认 disk 模式显示聚合进该行的样本数({6});all 模式显示时间戳偏移;sample 模式显示每组样本的时间跨度。--show-timestamps 时改为显示采样时刻的 HH:MM:SS
device设备名;多设备聚合时显示设备数({n}
rd_s / wr_s每秒读/写次数(发送到物理设备的 I/O 请求数)
rd_avkb / wr_avkb读/写平均大小(KB)
rd_mb_s / wr_mb_s每秒读/写 MB 数
rd_mrg / wr_mrg在队列调度器中被合并的读/写请求百分比
rd_cnc / wr_cnc读/写操作的平均并发度(Little 定律;块设备端到端,含排队时间)
rd_rt / wr_rt读/写平均响应时间(ms,端到端含排队,即应用程序看到的响应时间)
busy设备至少有一个请求在处理中的时间占比(即 iostat 的 %util)。注意:设备一直 busy 不等于饱和;并发度可以无上限增长,是更可靠的负载指标
in_prg正在处理中的请求数(瞬时采样值;数值大说明设备负载很重)
io_s物理设备吞吐量(IOPS,= rd_s + wr_s)
qtime平均排队时间(请求在调度队列中等待的时间,读写平均;由响应时间 R = W + S 反解 W = R − S)
stime平均服务时间(物理设备处理请求的时间,读写平均;由利用率公式 U = SX 反解 S)。某些内核 bug 会使 field 9/10 出错,此时 stime 不完全可信

对比 qtime 与 stime 可判断读写的响应时间花在队列还是物理设备上;更换块设备调度算法可能显著改善排队时间 (默认的 cfq 对服务器很差,只适合笔记本/工作站)。

与 iostat 列的对应关系:rrqm/swrqm/srd_mrgwr_mrgavgrq-sz(扇区,读写合并)→ rd_avkb/wr_avkb(kB,读写分开,加权平均 ×2 得扇区);avgqu-szrd_cnc/wr_cncawait(未直接提供)→ rd_rt/wr_rt 与聚合的 qtime/stime;svctmstime%utilbusy

输出样例

下面逐字照抄官方文档中的一段真实输出:同一台机器、同一时刻针对 /dev/sda 的两组统计, 前三段是 pt-diskstats(因为太宽而按列拆成读、写、汇总三块),后两段是同期的 iostat:

text
  #ts dev rd_s rd_avkb rd_mb_s rd_mrg rd_cnc   rd_rt
08:50:10 sda  0.0     0.0     0.0     0%    0.0     0.0
08:50:20 sda  0.4     4.0     0.0     0%    0.0    15.5
08:50:30 sda  2.1     4.4     0.0     0%    0.0    21.1
08:50:40 sda  2.4     4.0     0.0     0%    0.0    15.4
08:50:50 sda  0.1     4.0     0.0     0%    0.0    33.0

  wr_s wr_avkb wr_mb_s wr_mrg wr_cnc   wr_rt
  7.7    25.5     0.2    84%    0.0     0.3
  49.6     6.8     0.3    41%    2.4    28.8
  210.1     5.6     1.1    28%    7.4    25.2
  297.1     5.4     1.6    26%   11.4    28.3
  11.9    11.7     0.1    66%    0.2     4.9

  busy  in_prg   io_s  qtime   stime
  1%       0    7.7    0.1     0.2
  6%       0   50.0   28.1     0.7
  12%       0  212.2   24.8     0.4
  16%       0  299.5   27.8     0.4
  1%       0   12.0    4.7     0.3

  Dev rrqm/s  wrqm/s   r/s    w/s  rMB/s  wMB/s
08:50:10 sda   0.00   41.40  0.00   7.70   0.00   0.19
08:50:20 sda   0.00   34.70  0.40  49.60   0.00   0.33
08:50:30 sda   0.00   83.30  2.10 210.10   0.01   1.15
08:50:40 sda   0.00  105.10  2.40 297.90   0.01   1.58
08:50:50 sda   0.00   22.50  0.10  11.10   0.00   0.13

  avgrq-sz avgqu-sz  await  svctm  %util
  51.01     0.02   2.04   1.25   0.96
  13.55     2.44  48.76   1.16   5.79
  11.15     7.45  35.10   0.55  11.76
  10.81    11.40  37.96   0.53  15.97
  24.07     0.17  15.60   0.87   0.97

(以上为节选,完整示例见官方文档)

  • 这里 #ts 列显示的是 HH:MM:SS(即 --show-timestamps 的效果),每行一个样本; 默认模式下该列则是 {n} 形式的样本数。
  • 以 08:50:40 那行为例:pt-diskstats 的 wr_s 297.1、wr_cnc 11.4、busy 16%, 对应 iostat 同一行的 w/s 297.90、avgqu-sz 11.40、%util 15.97——正是上文列对应关系的直观印证。
  • 该行 qtime 27.8 远大于 stime 0.4,说明响应时间几乎全部消耗在调度队列里,而不是物理设备上。
  • 这台机器读几乎为零而写很重,rd_*wr_* 分列打印的价值在此体现:iostat 的 avgrq-sz 把读写混在一起,看不出这种偏斜。

采集数据

样本文件格式:每个 /proc/diskstats 样本前有一行 TS <timestamp>。 最简单的采集方式是用本工具的 --save-samples;在其他工具中采集可用如下脚本:

bash
INTERVAL=1
while true; do
  sleep=$(date +%s.%N | awk "{print $INTERVAL - (\$1 % $INTERVAL)}")
  sleep $sleep
  date +"TS %s.%N %F %T" >> diskstats-samples.txt
  cat /proc/diskstats >> diskstats-samples.txt
done

/proc/diskstats 字段说明

8 1 sda1 426 243 3386 2056 3 0 18 87 0 2135 2142 的 11 个统计字段依次为:

  1. 已完成的读次数(底层磁盘完成的物理读,完成后才计数)。
  2. 因相邻而合并的读次数(上例逻辑读 869 次、物理读 426 次)。
  3. 成功读取的扇区数(每扇区 512 字节)。
  4. 花在读上的毫秒数——从请求入队到完成的总时间(应用程序看到的总响应时间,不是磁盘服务时间)。 5–8. 同 1–4,但针对写。
  5. 当前进行中的 I/O 数(已调度并提交到磁盘队列但未完成;某些内核此值会算错,进而影响 10、11)。
  6. 花在 I/O 上的总毫秒数——至少有一个 I/O 进行中的总时长(两个重叠 I/O 各计 1,不叠加)。
  7. 所有 I/O 的总响应时间——与 10 相反,重叠时累加(两个 I/O 重叠完成时增量是 3 不是 2)。

选项

选项说明
--[no]buffer-stdout默认开启 STDOUT 缓冲;使用 tee、kubectl logs 等后处理工具想看到实时进度时可关闭
--columns-regex类型:string;默认:.。只打印匹配该 Perl 正则的列
--config类型:Array。读取逗号分隔的配置文件列表;如指定必须放在命令行第一个选项的位置
--devices-regex类型:string。只打印匹配该 Perl 正则的设备
--group-by类型:string;默认:all。聚合模式:disk(每行一个磁盘,统计自启动以来)、sample(每行一个样本,所有磁盘平均)、all(每行一个样本+一个磁盘)
--headers类型:Hash;默认:group,scrollgroup 每个样本间空行分隔;scroll 在表头即将滚出屏幕时重打印(按空格/回车可随时重打印表头)
--help显示帮助并退出
--interval类型:int;默认:1。交互模式下打印间隔秒数,也是采样 /proc/diskstats 的频率。工具尽量在整点间隔采样;为避免过长等待,剩余时间不足间隔 20% 时立即采样(最多等 120% 间隔)
--iterations类型:int。交互模式下 N 个样本后停止;默认永远运行
--sample-time类型:int;默认:1。--group-by sample 模式下每组包含 N 秒样本
--save-samples类型:string。把 diskstats 样本保存到该文件,供以后分析
--show-inactive显示非活动设备
--show-timestamps#ts 列显示 HH:MM:SS 时间戳(多时间戳聚合时显示第一个)
--version显示版本并退出
--[no]version-check默认:yes。检查 Percona Toolkit、MySQL 等软件的最新版本与已知问题版本(详见版本检查

其他信息

  • 系统要求:需要 Perl v5.8.0+ 和 /proc 文件系统(读文件模式除外)。

  • 作者:Baron Schwartz, Brian Fraser, Daniel Nichter

  • 通用说明:已知问题的反馈方式、PTDEBUG 调试安全提示、系统要求基线,见 通用说明

更多细节请阅读 官方文档

Percona Toolkit 中文文档 · 社区维护的第三方学习站