在開發過程中,開發者常遇到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函數終止本會話后臺線程時,客戶端不會退出而是自動重連。