只有6.0版本支持query字段。
state
后端的当前状态,取值范围:active,idle,idle in transaction,idle in transaction (aborted),fastpath
function call,disabled。
说明
只有6.0版本支持state字段。
查看连接信息
通过下述SQL确认当前的连接用户和对应的连接机器。
SELECT datname,usename,client_addr,client_port FROM pg_stat_activity ;
datname | usename | client_addr | client_port
---------+----------+---------------+-------------
postgres | joe | xx.xx.xx.xx | 60621
postgres | gpmon | xx.xx.xx.xx | 60312
(9 rows)
查看SQL运行信息
获取当前用户执行SQL信息:
6.0版本:
SELECT datname,usename,query FROM pg_stat_activity ;
datname | usename | query
----------+---------+--------------------------------------------------------------
postgres | postgres | SELECT datname,usename,query FROM pg_stat_activity ;
postgres | joe |
(2 rows)
4.3版本:
SELECT datname,usename,current_query FROM pg_stat_activity ;
datname | usename | current_query
----------+---------+--------------------------------------------------------------
postgres | postgres | SELECT datname,usename,current_query FROM pg_stat_activity ;
postgres | joe | <IDLE>
(2 rows)
获取当前正在运行的SQL信息:
6.0版本:
SELECT datname,usename,query
FROM pg_stat_activity
WHERE state != 'idle' ;
4.3版本:
SELECT datname,usename,current_query
FROM pg_stat_activity
WHERE current_query != '<IDLE>' ;
查看耗时较长的查询
查看当前运行中的耗时较长的SQL语句:
6.0版本:
select current_timestamp - query_start as runtime, datname, usename, query
from pg_stat_activity
where state != 'idle'
order by 1 desc;
4.3版本:
select current_timestamp - query_start as runtime, datname, usename, current_query
from pg_stat_activity
where current_query != '<IDLE>'
order by 1 desc;
返回示例如下:
runtime | datname | usename | current_query
----------------+---------------+---------+------------------------------------------------------------------------------
00:00:34.248426 | tpch_1000x_col | postgres | select
: l_returnflag,
: l_linestatus,
: sum(l_quantity) as sum_qty,
: sum(l_extendedprice) as sum_base_price,
: sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
: sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge,
: avg(l_quantity) as avg_qty,
: avg(l_extendedprice) as avg_price,
: avg(l_discount) as avg_disc,
: count(*) as count_order
: from
: public.lineitem
: where
: l_shipdate <= date '1998-12-01' - interval '93' day
: group by
: l_returnflag,
: l_linestatus
: order by
: l_returnflag,
: l_linestatus;
00:00:00 | postgres | postgres | select
: current_timestamp - query_start as runtime,
: datname,
: usename,
: current_query
: from pg_stat_activity
: where current_query != '<IDLE>'
: order by 1 desc;
(2 rows)
可以看到第一个查询耗时较久,已经运行了34s还没有结束。
异常SQL诊断及修复
如果一个SQL运行很长时间没有返回结果,需要检查该SQL还在运行中还是已经被Block:
6.0版本:
SELECT datname,usename,query
FROM pg_stat_activity
WHERE waiting;
4.3版本:
SELECT datname,usename,current_query
FROM pg_stat_activity
WHERE waiting;
需要注意的是上述返回结果只能获取当前因为Lock而被Block的SQL,无法获取因为其他原因被Block的SQL。绝大多数情况下SQL都是因为Lock而被Block,但也会存在其他情况,例如等待I/O、定时器等。如果上述SQL有返回结果,说明有SQL被Lock阻塞,需要进一步明确相互Block的SQL信息:
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;
通过上述SQL的返回结果可以确认相互Block的SQL和对应的执行pid。在明确了SQL的阻塞信息后,可以通过Cancel或者Kill Query的方式进行恢复。通过Cancel取消一个正在运行的Query:
SELECT pg_cancel_backend(pid)
需要在一个运行Query的Session中执行,如果Session本身就是Idle的,执行不起作用。另外取消这个Query需要花费一定的时间来做清理和事务的回滚。使用pg_terminate_backend来清理Idle
Session,也可以用来终止Query:
SELECT pg_terminate_backend(pid);
该用户的连接会断开。尽量避免在正在运行Query的进程pid上执行。需要注意的是文中提到操作需要用户有superuser的权限。