分析正在执行的SQL以处理GaussDB(DWS)业务阻塞
在开发过程中,开发者常遇到SQL连接数超限、SQL查询时间过长、SQL查询阻塞等问题,您可以通过PG_STAT_ACTIVITY和PGXC_THREAD_WAIT_STATUS视图来分析和定位SQL问题,以下通过PG_STAT_ACTIVITY视图展示常用的一些定位思路。
名称 |
类型 |
描述 |
---|---|---|
usename |
name |
登录该后端的用户名。 |
client_addr |
inet |
连接到该后端的客户端的IP地址。 如果此字段是null,则表示通过服务器机器上UNIX套接字连接客户端或者这是内部进程,如autovacuum。 |
application_name |
text |
连接到该后端的应用名。 |
state |
text |
后端当前总体状态。取值如下:
说明:
普通用户只能查看到自己账户所对应的会话状态,即其他账户的state信息为空。 |
waiting |
boolean |
如果后端当前正等待锁则为t,否则为f。
|
enqueue |
text |
语句当前排队状态。可能值是:
|
pid |
bigint |
后端线程ID。 |
查看连接信息
- 设置参数track_activities为on:
SET track_activities = on;
当此参数为on时,数据库系统才会收集当前活动查询的运行信息。
- 通过以下SQL就能确认当前的连接用户、连接地址、连接应用、状态、是否等待锁、排队状态以及线程id。
1
SELECT usename,client_addr,application_name,state,waiting,enqueue,pid FROM PG_STAT_ACTIVITY WHERE DATNAME='数据库名称';
回显如下:
1 2 3 4 5 6
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)
- 中止某个会话连接(仅系统管理员有权限):
1
SELECT PG_TERMINATE_BACKEND(pid);
查看SQL运行信息
- 获取当前用户有权限查看的所有的SQL信息(若有管理员权限或预置角色权限可以显示和所有用户查询相关的信息):
1
SELECT usename,state,query FROM PG_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 PG_STAT_ACTIVITY WHERE DATNAME='gaussdb'; joe | idle | GRANT SELECT ON TABLE mytable to leo; (3 rows)
- 查看当前正在运行(非idle)的SQL信息:
1
SELECT datname,usename,query FROM PG_STAT_ACTIVITY WHERE state != 'idle' ;
查看耗时较长的语句
- 查看当前运行中的耗时较长的SQL语句:
1
SELECT current_timestamp - query_start as runtime, datname, usename, query FROM PG_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 PG_STAT_ACTIVITY WHERE state != 'idle' order by 1 desc; (2 rows)
- 若当前系统较为繁忙,可以通过限制current_timestamp - query_start大于某一阈值来查看执行时间超过此阈值的查询语句。
1
SELECT query from PG_STAT_ACTIVITY WHERE current_timestamp - query_start > interval '2 days';
查看处于阻塞状态的语句
- 查看当前处于阻塞状态的查询语句:
1
SELECT pid, datname, usename, state, query FROM PG_STAT_ACTIVITY WHERE state <> 'idle' and waiting=true;
执行以下语句结束到阻塞的SQL会话:1
SELECT PG_TERMINATE_BACKEND(pid);
- 大部分场景下,阻塞是因为系统内部锁而导致的,waiting字段才显示为true,此阻塞可在视图pg_stat_activity中体现。
- 在一些少数场景下,例如写文件、定时器等情况的查询阻塞,不会在视图pg_stat_activity中体现。
- 查看阻塞的查询语句及阻塞查询的表、模式信息
1 2 3 4 5 6 7 8 9 10 11
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结束会话。
1
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函数终止本会话后台线程时,客户端不会退出而是自动重连。