使用PGXC_STAT_ACTIVITY视图分析正在执行的SQL以处理DWS业务阻塞
在开发过程中,开发者常遇到SQL连接数超限、SQL查询时间过长、SQL查询阻塞等问题,您可以通过PGXC_STAT_ACTIVITY和PGXC_THREAD_WAIT_STATUS视图来分析和定位SQL问题,以下通过PGXC_STAT_ACTIVITY视图展示常用的一些定位思路。
|
名称 |
类型 |
描述 |
|---|---|---|
|
coorname |
text |
当前集群下的CN名称。 |
|
datid |
oid |
用户会话在后端连接到的数据库OID。 |
|
datname |
name |
用户会话在后端连接到的数据库名称。 |
|
pid |
bigint |
后端线程ID。 |
|
lwtid |
integer |
后端线程的轻量级线程号。 |
|
usesysid |
oid |
登录此后端的用户OID。 |
|
usename |
name |
登录此后端的用户名。 |
|
application_name |
text |
连接到此后端的应用名。 |
|
client_addr |
inet |
连接到此后端的客户端的IP地址。 如果此字段是null,则表示通过服务器机器上UNIX套接字连接客户端或者这是内部进程,如autovacuum。 |
|
client_hostname |
text |
客户端的主机名,此字段是通过client_addr的反向DNS查找得到。仅在启动log_hostname且使用IP连接时才非空。 |
|
client_port |
integer |
客户端用于与后端通讯的TCP端口号,如果使用Unix套接字,则为-1。 |
|
backend_start |
timestamp with time zone |
后端进程启动时间,即客户端连接服务器的时间。 |
|
xact_start |
timestamp with time zone |
当前事务的启动时间,如果没有事务是活跃的,则为null。如果当前查询是首个事务,则这列等同于query_start列。 |
|
query_start |
timestamp with time zone |
开始当前活跃查询的时间, 如果state的值不是active,则这个值是上一个查询的开始时间。 |
|
state_change |
timestamp with time zone |
状态最后一次改变的时间。 |
|
waiting |
boolean |
如果后端当前正等待锁或者等待节点则为t,否则为f。 |
|
enqueue |
text |
语句当前排队状态。可能值是:
|
|
state |
text |
后端当前总体状态。可能值是:
说明:
只有系统管理员能查看到自己账户所对应的会话状态。其他账户的state信息为空。 |
|
resource_pool |
name |
用户使用的资源池。 |
|
stmt_type |
text |
用户语句的语句类型。 |
|
query_id |
bigint |
查询语句的ID。 |
|
query |
text |
此后端的最新查询。如果state状态是active(活跃的),此字段显示当前正在执行的查询。其他情况表示上一个查询。 |
|
connection_info |
text |
json格式字符串,记录当前连接数据库的驱动类型、驱动版本号、当前驱动的部署路径、进程属主用户等信息。 |
查看连接信息
- 设置参数track_activities为on:
SET track_activities = on;
当此参数为on时,数据库系统才会收集当前活动查询的运行信息。
- 通过以下SQL就能确认当前的连接用户、连接地址、连接应用、状态、是否等待锁、排队状态以及线程id。
1SELECT coorname, usename,client_addr,application_name,state,waiting,enqueue,pid FROM PGXC_STAT_ACTIVITY WHERE DATNAME='数据库名称';
回显如下:

1usename | client_addr | application_name | state | waiting | enqueue | pid
- 中止某个会话连接(仅系统管理员有权限),其中cn_name为上面回显的coorname,pid为对应的pid。
1EXECUTE DIRECT ON(cn_name) 'SELECT pg_terminate_backend(pid)';
查看SQL运行信息
- 获取当前用户有权限查看的所有的SQL信息(若有管理员权限或预置角色权限可以显示和所有用户查询相关的信息):
1SELECT usename,state,query FROM PGXC_STAT_ACTIVITY WHERE DATNAME='数据库名称';
如果state为active,则query列表示当前执行的SQL语句,其他情况则表示为上一个查询语句;如果state字段显示为idle,则表明此连接处于空闲,等待用户输入命令。回显如下:1 2 3 4 5 6
usename | state | query ---------+--------+--------------------------------------------------------------------------- leo | idle | select * from joe.mytable; dbadmin | active | SELECT usename,state,query FROM PGXC_STAT_ACTIVITY WHERE DATNAME='gaussdb'; joe | idle | GRANT SELECT ON TABLE mytable to leo; (3 rows)
- 查看当前正在运行(非idle)的SQL信息:
1SELECT datname,usename,query FROM PGXC_STAT_ACTIVITY WHERE state != 'idle' ;
查看耗时较长的语句
- 查看当前运行中的耗时较长的SQL语句:
1SELECT current_timestamp - query_start as runtime, datname, usename, query FROM PGXC_STAT_ACTIVITY WHERE state != 'idle' order by 1 desc;
查询会返回按执行时间长短从大到小排列的查询语句列表。第一条结果就是当前系统中执行时间最长的查询语句。
1 2 3 4 5
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 PGXC_STAT_ACTIVITY WHERE state != 'idle' order by 1 desc; (2 rows)
- 若当前系统较为繁忙,可以通过限制current_timestamp - query_start大于某一阈值来查看执行时间超过此阈值的查询语句。
1SELECT query from PGXC_STAT_ACTIVITY WHERE current_timestamp - query_start > interval '2 days';
查看处于阻塞状态的语句
- 查看当前处于阻塞状态的查询语句:
1SELECT coorname, pid, datname, usename, state, query FROM PGXC_STAT_ACTIVITY WHERE state <> 'idle' and waiting=true;
执行以下语句结束阻塞的SQL会话:1EXECUTE DIRECT ON(cn_name) 'SELECT pg_terminate_backend(pid)';
- 大部分场景下,阻塞是因为系统内部锁而导致的,waiting字段才显示为true,此阻塞可在视图pgxc_stat_activity中体现。
- 在一些少数场景下,例如写文件、定时器等情况的查询阻塞,不会在视图pgxc_stat_activity中体现。
- 查看阻塞的查询语句及阻塞查询的表、模式信息:
1 2 3 4 5 6 7 8 9 10 11 12
SELECT w.query as waiting_query, w.coorname as w_cn, 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 pgxc_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 pgxc_stat_activity l on l2.pid = l.pid join pg_stat_user_tables t on l1.relation = t.relid where w.waiting;
该查询返回会话ID、CN名称、用户信息、查询状态,以及导致阻塞的表、模式信息。
查询到阻塞的表及模式信息后,请根据实际会话ID结束会话。
1EXECUTE DIRECT ON(cn_name) 'SELECT pg_terminate_backend(pid)';
返回t或true,表示结束会话成功。
返回类似如下信息,表示用户正在尝试结束当前会话,此时仅会重连会话,而不是结束会话。
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函数终止本会话后台线程时,客户端不会退出而是自动重连。