在开发过程中,开发者常遇到SQL连接数超限、SQL查询时间过长、SQL查询阻塞等问题,您可以通过PG_STAT_ACTIVITY和PGXC_THREAD_WAIT_STATUS视图来分析和定位SQL问题,以下通过PG_STAT_ACTIVITY视图展示常用的一些定位思路。
部分PG_STAT_ACTIVITY字段
名称 类型 描述 usename
name
登录该后端的用户名。
client_addr
inet
连接到该后端的客户端的IP地址。 如果此字段是null,则表示通过服务器机器上UNIX套接字连接客户端或者这是内部进程,如autovacuum。
application_name
text
连接到该后端的应用名。
state
text
后端当前总体状态。可能值是:
l active:后台正在执行查询。
l idle:后台正在等待新的客户端命令。
l idle in transaction:后端在事务中,但事务中没有语句在执行。
l idle in transaction (aborted):后端在事务中,但事务中有语句执行失败。
l fastpath function call:后端正在执行一个fast-path函数。
l disabled:如果后端禁用track_activities,则报告此状态。
说明
普通用户只能查看到自己帐户所对应的会话状态。即其他帐户的state信息为空。
waiting
boolean
如果后端当前正等待锁则为true。
enqueue
text
语句当前排队状态。可能值是:
l waiting in queue:表示语句在排队中。
l waiting in global queue:表示语句在全局排队中。
l waiting in respool queue:表示语句在资源池排队中。
l waiting in ccn queue:表示作业在CCN排队中。
l 空:表示语句正在运行。
pid
bigint
后端线程ID。
查看连接信息
- 设置参数track_activities为on。
SET track_activities = on;
当此参数为on时,数据库系统才会收集当前活动查询的运行信息。
- 通过以下SQL就能确认当前的连接用户、连接地址、连接应用、状态、是否等待锁、排队状态以及线程id。
SELECT usename,client_addr,application_name,state,waiting,enqueue,pid FROM PG_STAT_ACTIVITY WHERE DATNAME='数据库名称';
回显如下
usename | client_addr | application_name | state | waiting | enqueue | pid
---------+---------------+------------------+--------+---------+---------+-----------------
leo | 192.168.0.133 | gsql | idle | f | | 139666091022080
dbadmin | 192.168.0.133 | gsql | active | f | | 139666212681472
joe | 192.168.0.133 | | idle | f | | 139665671489280
(3 rows)
- 中止某个会话连接(仅系统管理员有权限)
SELECT PG_TERMINATE_BACKEND(pid);
查看SQL运行信息
- 获取当前用户执行SQL信息:
SELECT usename,state,query FROM PG_STAT_ACTIVITY WHERE DATNAME='数据库名称';
回显如下,如果state为active,则query列表示当前执行的SQL语句,其他情况则表示为上一个查询语句。
如果state字段显示为idle,则表明此连接处于空闲,等待用户输入命令。
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;
查询会返回按执行时间长短从大到小排列的查询语句列表。第一条结果就是当前系统中执行时间最长的查询语句。
runtime | datname | usename | query
-----------------+----------+---------+-----------------------------------------------------------------------------------------------------------------------------------------
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);
说明l 大部分场景下,阻塞是因为系统内部锁而导致的,waiting字段才显示为true,此阻塞可在视图pg_stat_activity中体现。
l 在一些少数场景下,例如写文件、定时器等情况的查询阻塞,不会在视图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);
显示类似如下信息,表示结束会话成功。
PG_TERMINATE_BACKEND
----------------------
t
(1 row)
显示类似如下信息,表示用户正在尝试结束当前会话,此时仅会重连会话,而不是结束会话。
FATAL: terminating connection due to administrator command
FATAL: terminating connection due to administrator command
The connection to the server was lost. Attempting reset: Succeeded.
说明gsql客户端使用PG_TERMINATE_BACKEND函数终止本会话后台线程时,客户端不会退出而是自动重连。