pt-stalk
在问题发生时自动收集 MySQL 取证数据,用于诊断无法直接观察到的间歇性问题。
语法
pt-stalk [OPTIONS]安全提示
不要在命令行用 --password 提供 MySQL 密码:命令行密码对系统上所有用户可见, 且会存入 ps 命令的采集输出。请使用 MySQL 选项文件或 --ask-pass。
用法示例
以下命令假定已通过 /etc/my.cnf、~/.my.cnf 或本机 socket 配置好 MySQL 连接;需显式指定连接时加 -h主机 -P端口 -u用户 --ask-pass 或 --defaults-file=/path/my.cnf(切勿在命令行用 --password 明文传密码,见上方安全提示)。命令可直接复制,替换其中的阈值、目录与邮箱即可。
场景:常驻监控并发尖峰
把 pt-stalk 作为守护进程长期运行,当并发运行查询数(Threads_running)连续 5 次超过 20 时自动抓取现场,适合生产环境抓取偶发卡顿:
pt-stalk --daemonize --threshold 20 --cycles 5场景:按 processlist 状态触发
怀疑大量连接卡在 statistics 状态时,按该状态进程数触发(超过 10 个就收集):
pt-stalk --function processlist --variable State --match statistics --threshold 10场景:按需立即收集 1 分钟
不想等触发、临时抓一次现场后退出(如刚发生抖动想立刻留证):
pt-stalk --no-stalk --run-time 60 --iterations 1场景:每小时各自采 1 分钟
排查周期性问题时,每分钟采样、连续采一小时,用 --sleep-collect 控制采样间隔:
pt-stalk --no-stalk --run-time 3600 --sleep-collect 60场景:守护进程+邮件告警+自定义目录
以守护进程常驻,收集数据存到独立目录、记独立日志,触发时发邮件通知:
pt-stalk --daemonize \
--threshold 20 \
--dest /data/pt-stalk \
--log /var/log/pt-stalk.log \
--pid /var/run/pt-stalk.pid \
--notify-by-email oncall@example.com场景:顺带抓取查询流量
除了常规诊断数据,再抓 MySQL 端口流量,事后用 pt-query-digest 解码成查询日志:
pt-stalk --collect-tcpdump --threshold 20场景:非 root 用户运行
非 root 运行时必须显式指定 --pid、--log、--dest,否则可能无法启动:
pt-stalk --threshold 20 \
--pid /tmp/pt-stalk.pid \
--log /tmp/pt-stalk.log \
--dest /data/pt-stalk场景:RDS 实例只采集 MySQL
在 RDS 等无 OS 权限的实例上,只做 MySQL 相关采集(仅保留磁盘空间检查以计算可写空间):
pt-stalk --mysql-only --threshold 20功能说明
pt-stalk 做两件事:监视 MySQL 服务器并等待触发条件出现;触发时收集诊断数据。 设计为以 root 权限作为守护进程运行,用于诊断无法直接观察的间歇性问题; 也可以执行自定义命令,或不等触发而按需收集数据。
MySQL 锁死、活跃尖峰等问题通常不留任何可用于根因分析的现场证据, 因此即使"觉得没问题"也建议常驻运行 pt-stalk。
为避免短暂抖动造成误报,触发条件必须连续 --cycles 次为真才触发 --collect。
定义好的触发条件
好触发应足够灵敏(出问题时可靠触发)又不误报(正常时不动)。对 MySQL 最可靠的触发 往往是服务器连接数与并发运行查询数,对应 SHOW GLOBAL STATUS 中的 Threads_connected 与 Threads_running(后者通常更可靠)。 通过 --function、--variable、--threshold、--cycles 定义触发条件。
默认流程:永远监视 → 触发后收集一段时间 → 休眠以防反复收集。 诊断数据写入以时间戳命名的文件;pt-sift 用于浏览分析这些样本。
配置示例
可以用标准 Percona Toolkit 配置文件设置选项。"同时运行查询超过 20 就触发"的守护进程配置:
daemonize
threshold=20非 root 运行时需要指定 --pid、--log、--dest 等选项,否则可能无法启动。
运行流程与用法示例
pt-stalk 把诊断数据写成以时间戳开头的文件,本身不打印报告,官方源文档中也没有"收集了哪些文件" 的清单或成段的输出样例。因此这里照抄官方文档中最有代表性的两段内容——是流程伪代码与用法示例, 不是真实输出。第一段是工具运行时的总体操作顺序:
while true; do
if --variable from --function > --threshold; then
cycles_true++
if cycles_true >= --cycles; then
--notify-by-email
if --collect; then
if --disk-bytes-free and --disk-pct-free ok; then
(--collect for --run-time seconds) &
fi
rm files in --dest older than --retention-time
fi
iter++
cycles_true=0
fi
if iter < --iterations; then
sleep --sleep seconds
else
break
fi
else
if iter < --iterations; then
sleep --interval seconds
else
break
fi
fi
done
rm old --dest files older than --retention-time
if --collect process are still running; then
wait up to --run-time * 3 seconds
kill any remaining --collect processes
fi第二段是官方给出的按需收集用法:立即收集 1 分钟数据然后退出。
--no-stalk --run-time 60 --iterations 1- 伪代码把本页选项串成了一条线:
--function取到的--variable超过--threshold且连续累计到--cycles次才触发--collect;触发前先发--notify-by-email, 收集前先校验--disk-bytes-free与--disk-pct-free。 - 收集以后台子进程运行
--run-time秒,然后 sleep--sleep秒;未触发时只 sleep--interval秒。 每轮结束都会按--retention-time清理--dest中的旧文件。 - 退出时如果
--collect子进程还没结束,最多再等--run-time × 3秒,之后强制结束, 与选项表中--run-time的说明一致。 - 收集出的样本文件用 pt-sift 浏览分析。
选项
| 选项 | 说明 |
|---|---|
--ask-pass | 连接 MySQL 时交互式询问密码 |
--collect | 默认:yes;可取反。触发时收集诊断数据(--no-collect 只监视不收集) |
--collect-gdb | 收集 GDB 堆栈:附加 MySQL 打印所有线程堆栈,会冻结服务器一段时间(繁忙/大内存/多线程时更久),故默认关闭;诊断服务器卡死/锁死时冻结无害且堆栈至关重要。GDB 分离后仍有崩溃或性能变差的风险 |
--collect-oprofile | 收集 oprofile 数据:启动 oprofile 会话,运行收集时长后停止并保存到系统默认位置 |
--collect-strace | 收集 strace 数据:附加 strace(分离前服务器很慢),注意事项同 --collect-gdb;不可与 --collect-gdb 同时启用(GDB 与 strace 不能同时附加) |
--collect-tcpdump | 收集 tcpdump 数据:抓取 MySQL 监听端口在所有接口上的全部流量;之后可用 pt-query-digest 解码 MySQL 协议提取查询流量日志 |
--config | 类型:string。读取逗号分隔的配置文件列表;如指定必须放在命令行第一个选项的位置 |
--cycles | 类型:int;默认:5。--variable 超过 --threshold 的次数达到该值才触发 --collect,防误报 |
--daemonize | fork 到后台,输出按 --log 记录 |
-F, --defaults-file | 类型:string。只从给定文件读取 mysql 选项,必须给绝对路径 |
--dest | 类型:string;默认:/var/lib/pt-stalk。诊断数据保存目录;每次收集写一组以系统时间戳命名的新文件 |
--disk-bytes-free | 类型:size;默认:100M。磁盘空闲小于该值时不收集,防止写满磁盘。若 dest 目录有上次样本,会把其大小作为预估、更悲观地判断(要求空闲 ≥ 预估值 + 该值)。后缀 k/M/G/T |
--disk-pct-free | 类型:int;默认:5。磁盘空闲百分比小于该值时不收集;与 --disk-bytes-free 同时满足才收集 |
--function | 类型:string;默认:status。触发源:status(监视 SHOW GLOBAL STATUS,--variable 指定状态计数器)、processlist(监视 SHOW FULL PROCESSLIST,触发值为 --variable 列匹配 --match 的进程数)、或包含自定义触发函数的 shell 脚本文件(须定义 trg_plugin 函数并输出数字,与 --threshold 比较;文件优先于内建值;勿改动工具全局变量,私有变量加 PLUGIN_ 前缀或用局部变量) |
--help | 显示帮助并退出 |
-h, --host | 类型:string。要连接的主机 |
--interval | 类型:int;默认:1。检查触发条件是否为真的间隔秒数 |
--iterations | 类型:int。收集诊断数据的次数;默认永远运行。配合 --no-stalk 可"收集一次就退出" |
--log | 类型:string;默认:/var/log/pt-stalk.log。daemonize 时输出到该文件 |
--match | 类型:string。监视 SHOW PROCESSLIST 时使用的匹配模式(见 --function) |
--notify-by-email | 类型:string。每次 --collect 时向这些邮箱发邮件 |
-p, --password | 类型:string。连接密码(含逗号需转义)。命令行传密码不安全,请用选项文件或 --ask-pass |
--pid | 类型:string;默认:/var/run/pt-stalk.pid。创建 PID 文件;冲突规则与自动清理见官方文档 |
--plugin | 类型:string。加载插件文件(不需可执行权限)扩展功能,可定义钩子函数:before_stalk、before_collect、after_collect、after_collect_sleep、after_interval_sleep、after_stalk。插件整体被 source 进工具命名空间,勿重定义已有函数/全局变量;选项对应全局变量 $OPT_XXX;设 OKTORUN=1 可停止工具(同时设 EXIT_REASON);当前样本文件前缀用 $prefix 变量访问 |
--mysql-only | 只触发 MySQL 相关采集(仅保留磁盘空间检查以计算可写空间);对 RDS 实例有用 |
-P, --port | 类型:int。连接端口 |
--prefix | 类型:string。诊断样本文件名前缀;默认为当前本地时间戳(如 2011_12_06_14_02_02) |
--retention-count | 类型:int;默认:0。保留最近 N 次运行的数据,更旧的删除 |
--retention-size | 类型:int;默认:0。最多保留该 MB 数的数据(即使超限也至少保留 1 次运行) |
--retention-time | 类型:int;默认:30。样本保留天数,过期清除 |
--run-time | 类型:int;默认:30。触发后收集诊断数据的秒数,不应长于 --sleep。一般无需调整:默认 30 秒不够时延长也无济于事(系统/服务器多半忙到无法响应),很多时候更短才合适。收集子进程之后还会再等一个 run-time 让命令写完数据;工具退出前如有子进程未结束,最多再等 3 × run-time |
--sleep | 类型:int;默认:300。--collect 之后的睡眠秒数,防止连续触发、写满磁盘或收集过量数据 |
--sleep-collect | 类型:int;默认:1。收集循环每轮之间的睡眠秒数;配合 --no-stalk 做长收集(如每分钟采一次、采一小时:--no-stalk --run-time 3600 --sleep-collect 60) |
--skip-collection | 类型:array。跳过的采集类型列表:ps-locks-transactions、thread-variables、innodbstatus、lock-waits、mysqladmin、processlist、rocksdbstatus、transactions |
-S, --socket | 类型:string。连接使用的 socket 文件 |
--stalk | 默认:yes;可取反。监视服务器等待触发;--no-stalk 立即收集(不等触发),通常配合 --interval、--iterations、--sleep,如 --no-stalk --run-time 60 --iterations 1 即采 1 分钟就退出。--cycles、--daemonize、--log、--pid 在 --no-stalk 下无效;磁盘保护选项仍生效 |
--system-only | 只触发操作系统相关采集 |
--threshold | 类型:int;默认:25。--variable 可接受的最大值:超过该值持续 --cycles 次即触发 --collect(目前无法定义"过低"阈值) |
-u, --user | 类型:string。登录用户(若非当前用户) |
--variable | 类型:string;默认:Threads_running。与 --threshold 比较的变量 |
--verbose | 类型:int;默认:2。运行时输出详细程度:0=错误、1=警告、2=匹配的触发与收集信息、3=未匹配的触发 |
--version | 显示版本并退出 |
环境变量
本工具不要求配置环境变量,但可通过以下 CMD_* 变量覆盖内部命令(专家选项): CMD_GDB、CMD_IOSTAT、CMD_MPSTAT、CMD_MYSQL、CMD_MYSQLADMIN、CMD_OPCONTROL、 CMD_OPREPORT、CMD_PMAP、CMD_STRACE、CMD_SYSCTL、CMD_TCPDUMP、CMD_VMSTAT。 例如 NFS 分区上需要给 iostat 加 -n:CMD_IOSTAT="iostat -n" pt-stalk ...。 还可以 CMD_MYSQLADMIN='mysqladmin debug' pt-stalk ... 启用 mysqladmin 调试。
系统要求
需要 Bash v3 或更新版本。特定选项需要:--collect-gdb → gdb; --collect-oprofile → opcontrol 与 opreport;--collect-strace → strace; --collect-tcpdump → tcpdump。
其他信息
作者:Baron Schwartz, Justin Swanhart, Fernando Ipar, Daniel Nichter, Brian Fraser
通用说明:已知问题的反馈方式、PTDEBUG 调试安全提示、系统要求基线,见 通用说明。
更多细节请阅读 官方文档。