【云小课】EI第34课 运筹帷幄-GaussDB(DWS)教你分析阻塞SQL的几个妙招
在开发过程中,开发者常遇到SQL连接数超限、SQL查询时间过长、SQL查询阻塞等问题,您可以通过PG_STAT_ACTIVITY视图来分析和定位SQL问题,以下展示常用的一些定位思路。
表1 部分PG_STAT_ACTIVITY字段
名称 | 类型 | 描述 |
usename | name |
登录该后端的用户名。 |
client_addr | inet | 连接到该后端的客户端的IP地址。 如果此字段是null,则表示通过服务器机器上UNIX套接字连接客户端或者这是内部进程,如autovacuum。 |
application_name | text | 连接到该后端的应用名。 |
state | text |
后端当前总体状态。可能值是:
普通用户只能查看到自己帐户所对应的会话状态。即其他帐户的state信息为空。 |
waiting | boolean |
如果后端当前正等待锁则为true。 |
enqueue | text |
语句当前排队状态。可能值是:
|
pid |
bigint |
后端线程ID。 |
查看连接信息
-
通过以下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语句,其他情况则表示为上一个查询语句。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);
-
大部分场景下,阻塞是因为系统内部锁而导致的,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);
想要了解更多华为云数据仓库GaussDB(DWS),请猛戳!!!
- 点赞
- 收藏
- 关注作者
评论(0)