pt-diskstats
GNU/Linux 上的交互式磁盘 I/O 监控工具,类似 iostat 但更详细、可交互。
语法
pt-diskstats [OPTIONS] [FILES]打印 GNU/Linux 的磁盘 I/O 统计。与 iostat 相比的优势:读写统计分开打印、列更多、 菜单驱动可交互、支持多种数据聚合方式、与 pt-stalk 集成良好、默认就"做对的事"(如隐藏空闲磁盘)。 非常适合快速下钻 I/O 性能问题、检查磁盘行为。
用法示例
pt-diskstats 是纯本机磁盘监控工具(读 /proc/diskstats),不连接数据库,命令可直接复制运行。它以交互方式循环刷新,按 q 退出;用 --iterations 可让它跑固定次数后自动结束、适合放进脚本。
场景:实时监控磁盘 I/O
排查磁盘瓶颈时,直接看实时读写、响应时间与排队情况(默认聚合所有磁盘与样本):
pt-diskstats场景:只看指定磁盘
只盯 sda 这一块盘,过滤掉其他设备:
pt-diskstats --devices-regex sda场景:加大采样间隔并带时间戳
录屏或记录排障过程时,每 5 秒刷新一次并显示 HH:MM:SS 时间戳:
pt-diskstats --interval 5 --show-timestamps场景:批处理采集固定次数
不想一直守着屏幕,让它采样 10 次(每次间隔 2 秒)后自动退出,输出可重定向存档:
pt-diskstats --iterations 10 --interval 2场景:只关注关键列
列太多看不过来时,用正则只保留设备名、繁忙度、读写响应时间与服务时间:
pt-diskstats --columns-regex 'device|busy|rd_rt|wr_rt|qtime|stime'场景:保存样本后期回放分析
先把采样落盘,之后用文件模式离线回放分析(也可把文件拷贝到别的机器上看):
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/s、wrqm/s → rd_mrg、wr_mrg;avgrq-sz(扇区,读写合并)→ rd_avkb/wr_avkb(kB,读写分开,加权平均 ×2 得扇区);avgqu-sz → rd_cnc/wr_cnc; await(未直接提供)→ rd_rt/wr_rt 与聚合的 qtime/stime;svctm → stime;%util → busy。
输出样例
下面逐字照抄官方文档中的一段真实输出:同一台机器、同一时刻针对 /dev/sda 的两组统计, 前三段是 pt-diskstats(因为太宽而按列拆成读、写、汇总三块),后两段是同期的 iostat:
#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_s297.1、wr_cnc11.4、busy16%, 对应 iostat 同一行的w/s297.90、avgqu-sz11.40、%util15.97——正是上文列对应关系的直观印证。 - 该行
qtime27.8 远大于stime0.4,说明响应时间几乎全部消耗在调度队列里,而不是物理设备上。 - 这台机器读几乎为零而写很重,
rd_*与wr_*分列打印的价值在此体现:iostat 的avgrq-sz把读写混在一起,看不出这种偏斜。
采集数据
样本文件格式:每个 /proc/diskstats 样本前有一行 TS <timestamp>。 最简单的采集方式是用本工具的 --save-samples;在其他工具中采集可用如下脚本:
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 个统计字段依次为:
- 已完成的读次数(底层磁盘完成的物理读,完成后才计数)。
- 因相邻而合并的读次数(上例逻辑读 869 次、物理读 426 次)。
- 成功读取的扇区数(每扇区 512 字节)。
- 花在读上的毫秒数——从请求入队到完成的总时间(应用程序看到的总响应时间,不是磁盘服务时间)。 5–8. 同 1–4,但针对写。
- 当前进行中的 I/O 数(已调度并提交到磁盘队列但未完成;某些内核此值会算错,进而影响 10、11)。
- 花在 I/O 上的总毫秒数——至少有一个 I/O 进行中的总时长(两个重叠 I/O 各计 1,不叠加)。
- 所有 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,scroll。group 每个样本间空行分隔;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 调试安全提示、系统要求基线,见 通用说明。
更多细节请阅读 官方文档。