Skip to content

pt-stalk

在问题发生时自动收集 MySQL 取证数据,用于诊断无法直接观察到的间歇性问题。

语法

bash
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 时自动抓取现场,适合生产环境抓取偶发卡顿:

bash
pt-stalk --daemonize --threshold 20 --cycles 5

场景:按 processlist 状态触发

怀疑大量连接卡在 statistics 状态时,按该状态进程数触发(超过 10 个就收集):

bash
pt-stalk --function processlist --variable State --match statistics --threshold 10

场景:按需立即收集 1 分钟

不想等触发、临时抓一次现场后退出(如刚发生抖动想立刻留证):

bash
pt-stalk --no-stalk --run-time 60 --iterations 1

场景:每小时各自采 1 分钟

排查周期性问题时,每分钟采样、连续采一小时,用 --sleep-collect 控制采样间隔:

bash
pt-stalk --no-stalk --run-time 3600 --sleep-collect 60

场景:守护进程+邮件告警+自定义目录

以守护进程常驻,收集数据存到独立目录、记独立日志,触发时发邮件通知:

bash
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 解码成查询日志:

bash
pt-stalk --collect-tcpdump --threshold 20

场景:非 root 用户运行

非 root 运行时必须显式指定 --pid--log--dest,否则可能无法启动:

bash
pt-stalk --threshold 20 \
  --pid /tmp/pt-stalk.pid \
  --log /tmp/pt-stalk.log \
  --dest /data/pt-stalk

场景:RDS 实例只采集 MySQL

在 RDS 等无 OS 权限的实例上,只做 MySQL 相关采集(仅保留磁盘空间检查以计算可写空间):

bash
pt-stalk --mysql-only --threshold 20

功能说明

pt-stalk 做两件事:监视 MySQL 服务器并等待触发条件出现;触发时收集诊断数据。 设计为以 root 权限作为守护进程运行,用于诊断无法直接观察的间歇性问题; 也可以执行自定义命令,或不等触发而按需收集数据。

MySQL 锁死、活跃尖峰等问题通常不留任何可用于根因分析的现场证据, 因此即使"觉得没问题"也建议常驻运行 pt-stalk。

为避免短暂抖动造成误报,触发条件必须连续 --cycles 次为真才触发 --collect

定义好的触发条件

好触发应足够灵敏(出问题时可靠触发)又不误报(正常时不动)。对 MySQL 最可靠的触发 往往是服务器连接数与并发运行查询数,对应 SHOW GLOBAL STATUS 中的 Threads_connectedThreads_running(后者通常更可靠)。 通过 --function--variable--threshold--cycles 定义触发条件。

默认流程:永远监视 → 触发后收集一段时间 → 休眠以防反复收集。 诊断数据写入以时间戳命名的文件;pt-sift 用于浏览分析这些样本。

配置示例

可以用标准 Percona Toolkit 配置文件设置选项。"同时运行查询超过 20 就触发"的守护进程配置:

daemonize
threshold=20

非 root 运行时需要指定 --pid--log--dest 等选项,否则可能无法启动。

运行流程与用法示例

pt-stalk 把诊断数据写成以时间戳开头的文件,本身不打印报告,官方源文档中也没有"收集了哪些文件" 的清单或成段的输出样例。因此这里照抄官方文档中最有代表性的两段内容——是流程伪代码与用法示例, 不是真实输出。第一段是工具运行时的总体操作顺序:

bash
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 分钟数据然后退出。

bash
--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,防误报
--daemonizefork 到后台,输出按 --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_stalkbefore_collectafter_collectafter_collect_sleepafter_interval_sleepafter_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-transactionsthread-variablesinnodbstatuslock-waitsmysqladminprocesslistrocksdbstatustransactions
-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_GDBCMD_IOSTATCMD_MPSTATCMD_MYSQLCMD_MYSQLADMINCMD_OPCONTROLCMD_OPREPORTCMD_PMAPCMD_STRACECMD_SYSCTLCMD_TCPDUMPCMD_VMSTAT。 例如 NFS 分区上需要给 iostat 加 -nCMD_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 调试安全提示、系统要求基线,见 通用说明

更多细节请阅读 官方文档

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