在开发过程中,开发者常遇到SQL连接数超限、SQL查询时间过长、SQL查询阻塞等问 题,您可以通过PG_STAT_ACTIVITY视图来分析和定位SQL问题,以下展示常用的一 些定位思路。
表4-1 部分 PG_STAT_ACTIVITY 字段
名称 类型 描述
usename name 登录该后端的用户名。
client_addr inet 连接到该后端的客户端的 IP地址。 如果此字段是 null,则表示通过服务器 机器上UNIX套接字连接客 户端或者这是内部进程,
如autovacuum。
application_name text 连接到该后端的应用名。
名称 类型 描述
state text 后端当前总体状态。可能
值是:
● active:后台正在执行 查询。
● idle:后台正在等待新 的客户端命令。
● idle in transaction:后 端在事务中,但事务中 没有语句在执行。
● idle in transaction (aborted):后端在事 务中,但事务中有语句 执行失败。
● fastpath function call:后端正在执行一 个fast-path函数。
● disabled:如果后端禁 用track_activities,则 报告此状态。
说明
普通用户只能查看到自己帐 户所对应的会话状态。即其 他帐户的state信息为空。
waiting boolean 如果后端当前正等待锁则
为true。
enqueue text 语句当前排队状态。可能
值是:
● waiting in queue:表 示语句在排队中。
● waiting in global queue:表示语句在全 局排队中。
● waiting in respool queue:表示语句在资 源池排队中。
● waiting in ccn queue:表示作业在 CCN排队中。
● 空:表示语句正在运 行。
pid bigint 后端线程ID。
查看连接信息
SELECT usename,state,query FROM PG_STAT_ACTIVITY WHERE DATNAME='数据库名称';
回显如下,如果state为active,则query列表示当前执行的SQL语句,其他情况则 表示为上一个查询语句。
usename | state | query
leo | idle | select * from joe.mytable;
dbadmin | active | SELECT usename,state,query FROM PG_STAT_ACTIVITY WHERE DATNAME='gaussdb';
joe | idle | GRANT SELECT ON TABLE mytable to leo;
(3 rows)
● 查看当前正在运行(非idle)的SQL信息:
SELECT datname,usename,query FROM PG_STAT_ACTIVITY WHERE state != 'idle' ;
查看耗时较长的语句
● 查看当前运行中的耗时较长的SQL语句
SELECT current_timestamp - query_start as runtime, datname, usename, query FROM PG_STAT_ACTIVITY WHERE state != 'idle' order by 1 desc;
查询会返回按执行时间长短从大到小排列的查询语句列表。第一条结果就是当前
00:04:47.054958 | gaussdb | leo | insert into mytable1 select generate_series(1, 10000000);
00:00:01.72789 | gaussdb | dbadmin | SELECT current_timestamp - query_start as runtime, datname, usename, query FROM PG_STAT_ACTIVITY WHERE state != 'idle' order by 1 desc;
(2 rows)
● 若当前系统较为繁忙,可以通过限制current_timestamp - query_start大于某一阈 值来查看执行时间超过此阈值的查询语句。
SELECT query from PG_STAT_ACTIVITY WHERE current_timestamp - query_start > 2;
查看处于阻塞状态的语句
● 查看当前处于阻塞状态的查询语句:
SELECT pid, datname, usename, state, query FROM PG_STAT_ACTIVITY WHERE state <> 'idle' and waiting=true;
执行以下语句结束到阻塞的SQL会话。
SELECT PG_TERMINATE_BACKEND(pid);
说明
● 大部分场景下,阻塞是因为系统内部锁而导致的,waiting字段才显示为true,此阻塞 可在视图pg_stat_activity中体现。
● 在一些少数场景下,例如写文件、定时器等情况的查询阻塞,不会在视图 pg_stat_activity中体现。
● 查看阻塞的查询语句及阻塞查询的表、模式信息
SELECT w.query as waiting_query, w.pid as w_pid,
w.usename as w_user, l.query as locking_query, l.pid as l_pid,
l.usename as l_user,
t.schemaname || '.' || t.relname as tablename
from pg_stat_activity w join pg_locks l1 on w.pid = l1.pid and not l1.granted join pg_locks l2 on l1.relation = l2.relation
and l2.granted join pg_stat_activity l on l2.pid = l.pid join pg_stat_user_tables t on l1.relation = t.relid where w.waiting;
该查询返回会话ID、用户信息、查询状态,以及导致阻塞的表、模式信息。
查询到阻塞的表及模式信息后请根据会话ID结束会话。
SELECT PG_TERMINATE_BACKEND(pid);