pg_stat_activity,本质上就是一个实时窗口,能帮你直接看到数据库现在到底在干嘛。上一讲我们讲了基础,这次我们深入聊聊怎么玩转这个强大的工具。
来个最基础的 pg_stat_activity 查询例子:
SELECT *
FROM pg_stat_activity;
这个查询会列出所有活跃连接和当前的 SQL。很棒吧!但数据会超级多,你可能会翻到天荒地老。所以我们最好只筛选最重要的信息。
pg_stat_activity 里的主要字段
来看看几个关键字段,除了你已经知道的那些。query_start 显示 SQL 开始执行的时间,这对找出慢操作特别关键。pid 是连接进程的 ID——用来管理(比如 kill)连接。state_change 是当前连接状态切换的时间,这对分析那些长期卡住的状态特别有用。
活跃进程的查询例子:
SELECT pid, usename, state, query, query_start
FROM pg_stat_activity
WHERE state = 'active';
怎么追踪慢 SQL?
想象你是数据库管理员,突然服务器压力爆表。咋办?先得搞清楚哪个 SQL 把资源都吃光了。用 pg_stat_activity 找出这些“吃货”SQL。
SELECT pid, usename, query, state, now() - query_start AS duration
FROM pg_stat_activity
WHERE state = 'active'
AND (now() - query_start) > interval '10 seconds';
这个查询会列出所有执行超过 10 秒的 SQL。你可以根据自己需求调整时间。
终止有问题的 SQL
来看看怎么干掉那些跑太久、影响数据库的 SQL。用 pg_terminate_backend() 这个函数可以强制终止进程。
终止指定 PID 进程的例子:
SELECT pg_terminate_backend(12345);
这里 12345 就是 pg_stat_activity 里的进程 ID(pid 字段)。
注意:终止进程可能会导致事务回滚(rollback),所以要小心点。
如果你想自动干掉所有“挂住”的进程,比如 idle 的事务,可以用下面这个 PL/pgSQL 块。你已经学过编程了,loop(循环)应该不陌生——就是重复执行某些操作直到满足条件或者数据处理完为止:
DO $$
DECLARE
r RECORD;
BEGIN
FOR r IN
SELECT pid
FROM pg_stat_activity
WHERE state = 'idle in transaction'
AND (now() - state_change) > interval '5 minutes'
LOOP
PERFORM pg_terminate_backend(r.pid);
END LOOP;
END $$;
这个动态方案可以帮你清理掉有问题的事务。FOR 循环会遍历查询结果里的每一条记录,然后对每个找到的 PID 执行终止操作。
很快我们就要开始学 PL/pgSQL 了,别急,马上就到 :P
按事务状态过滤
有时候你不只是想找活跃 SQL,还想知道哪些连接处于特殊状态,比如 idle 或 idle in transaction。这样可以提前发现潜在问题,防止它们变成大麻烦。
查找处于 idle in transaction 状态事务的例子:
SELECT pid, usename, query, state, state_change
FROM pg_stat_activity
WHERE state = 'idle in transaction';
state_change 字段显示这个状态是什么时候设定的。这样你就能找出那些啥也不干但还占着资源的“僵尸”事务。
实战应用
生产环境监控慢 SQL:你可以定期监控超过某个时长的 SQL,然后通过 Slack、Telegram 或其他通知工具提醒自己。这样能第一时间发现性能问题。
事故时分析 SQL:如果服务器开始卡,第一步就是看 pg_stat_activity,找出原因。这应该成为你排查性能问题的标准流程。
数据库维护:定期分析 pg_stat_activity,能帮你发现低效 SQL 并优化它们(比如加索引或者重写 SQL)。
监控时常见的坑有:过滤条件或者数据解读不对。比如你只筛 active 状态,可能会漏掉 idle in transaction 的 SQL,而这些也可能导致资源被锁。还有一种坑是太激进地终止进程,结果导致事务回滚、数据丢失。下手前一定要分析清楚上下文。
进阶监控技巧
想更高级点,可以写复杂点的查询,按用户、数据库或者 SQL 类型统计。比如可以查每个用户平均执行 SQL 的时间,或者找出活跃连接最多的数据库。
还可以配置 PostgreSQL 的 log_min_duration_statement 和 log_statement 参数,把慢 SQL 自动记录到日志文件里。这样你可以事后分析性能问题,找出应用的行为规律。
GO TO FULL VERSION