本文將為您介紹如何對實例中的Query進行診斷和管理。
Query管理概述
Hologres兼容PostgreSQL,可以通過查詢hg_stat_activity(pg_stat_activity)視圖信息來查看實例Query的運行信息,以達到分析和診斷運行SQL的目的。具體涉及的操作內容如下所示:
使用SQL查看活躍Query:查看SQL運行信息,更好的管理SQL語句。
HoloWeb可視化活躍Query管理:通過HoloWeb可視化查看和管理活躍Query。
排查鎖:通過活躍Query排查當前SQL是否有鎖或者被鎖。
終止Query:使用命令語句終止不符合預期的Query。
修改活躍Query超時時間:修改活躍Query運行超時時間,防止引發死鎖。
修改空閑Query超時時間:修改空閑Query運行超時時間,防止引發死鎖。
查詢慢Query日志:通過慢Query的查詢可以對慢Query或失敗Query進行診斷、分析和采取優化措施。
常見問題:出現
ERROR: canceling statement due to statement timeout
報錯的原因和解決方法。
查詢hg_stat_activity(pg_stat_activity)視圖信息
從Hologres V2.0版本開始,pg_stat_activity升級為hg_stat_activity視圖。hg_stat_activity是pg_stat_activity視圖的擴展,可以通過hg_stat_activity查詢到活躍SQL更詳細的運行信息,包括query id
、query engine
以及資源消耗等信息,從而幫助更進一步診斷活躍Query。您可以執行如下命令查看Query的運行信息。其他Postgres兼容管理工具,依舊可以查詢pg_stat_activity獲取SQL運行態信息。
--2.0及以上推薦語法
SELECT * FROM hg_stat_activity;
--1.3及以下版本語法
SELECT * FROM pg_stat_activity;
hg_stat_activity視圖的字段說明如下所示:
字段 | 描述 | hg_stat_activity視圖支持情況 | pg_stat_activity視圖支持情況 |
datid | Hologres后端連接到的數據庫的OID。 | 支持 | 支持 |
datname | Hologres后端連接到的數據庫的名稱。 | 支持 | 支持 |
pid | Hologres后端的進程ID。 | 支持 | 支持 |
query_id | 當前執行SQL的ID,一個SQL對應一個query_id。 | 支持 | 不支持 |
transaction_id | 當前SQL所屬的事務ID,一個事務中可能有多個SQL。 | 支持 | 不支持 |
usesysid | 當前活躍會話用戶的系統標識符。 | 支持 | 支持 |
usename | 當前連接的用戶名。 | 支持 | 支持 |
application_name | 客戶端的應用類型。 其中常見的應用類型如下:
其余應用建議業務上在連接Hologres時連接串上顯式指定 | 支持 | 支持 |
running_info | 包含SQL執行過程各種狀態信息,格式為JSON格式。其子字段包括:
| 支持 | 不支持 |
extend_info | 包含SQL執行過程資源消耗等的擴展信息,為JSON格式。其子字段包括:
說明 be_lock_waiters和be_lock_converting_waiters采集的都是backend的鎖,而不是frontend的鎖,排查鎖請參見鎖以及排查鎖。 | 支持 | 不支持 |
state | 表示連接的狀態。常見的狀態如下:
| 支持 | 支持 |
query_start | Query開始執行的時間,如果active不是active,取值為上一個查詢開始的時間。 | 支持 | 支持 |
client_addr | 客戶端的IP地址。 顯示的IP地址可能是被解析過的,不保證一定是源端IP。 | 支持 | 支持 |
client_hostname | 客戶端的主機名。 | 支持 | 支持 |
client_port | 客戶端的端口。 | 支持 | 支持 |
backend_start | 后臺進程開始的時間。 在Hologres中無需過多關注。 | 支持 | 支持 |
xact_start | 該進程的當前事務被啟動的時間。
在Hologres中無需過多關注。 | 支持 | 支持 |
state_change | 連接的狀態(state)上一次被改變的時間。 在Hologres中無需過多關注。 | 支持 | 支持 |
wait_event_type | 后端正在等待的事件類型,如果不存在則為NULL。可能的取值有:
| 支持 | 支持 |
wait_event | 如果后端當前正在等待,則是等待事件的名稱,否則為 NULL。 | 支持 | 支持 |
backend_xid | Hologres后端的頂層事務標識符。 | 支持 | 支持 |
backend_xmin | 當前后端的xmin范圍。 | 支持 | 支持 |
query | 后端最近執行的查詢。如果state為 | 支持 | 支持 |
backend_type | 當前后端的類型。可能的類型為autovacuum launcher、autovacuum worker、logical replication launcher、logical replication worker、parallel worker、background writer、client backend、checkpointer、startup、walreceiver、walsender以及 walwriter。除此之外還包括后端的執行組件,例如PQE等。 說明 需要關注 | 支持 | 支持 |
使用SQL查看活躍Query
若您更傾向于使用SQL方式查詢活躍Query,可以使用以下SQL進行操作:
查看當前活躍Query以及對應的執行階段和資源消耗:
說明Superuser可以查看所有用戶的SQL運行信息,RAM用戶只能查看自己的SQL運行信息。
--2.0及以上版本語法 SELECT query,state,query_id,transaction_id,running_info, extend_info FROM hg_stat_activity WHERE state = 'active' AND backend_type = 'client backend' AND application_name != 'hologres' --1.3及以下版本語法 SELECT query,state,pid FROM pg_stat_activity WHERE state = 'active' AND backend_type = 'client backend' AND application_name != 'hologres'
示例返回結果:
------------------------------------------------------------------------------- query | insert into test_hg_stat_activity select i, (i % 7) :: text, (i % 1007) from generate_series(1, 10000000)i; state | active query_id | 100713xxxx transaction_id | 100713xxxx running_info | {"current_stage" : {"stage_duration_ms" :5994, "stage_name" :"EXECUTE" }, "engine_type" :"{HQE,PQE}", "fe_id" :1, "warehouse_id" :0 } extend_info | {"affected_rows" :9510912, "scanned_rows" :9527296 }
當前運行的Query按照CPU消耗排序:
--2.0及以上語法 SELECT query,((extend_info::json)->'total_cpu_max_time_ms')::text::bigint AS cpu_cost,state,query_id,transaction_id FROM hg_stat_activity WHERE state = 'active' ORDER BY 2 DESC;
示例返回結果:
--------------------------------------------------------------------------------- query | select xxxxx cpu_cost | 523461 state | active query_id | 10053xxxx transaction_id | 10053xxxx --------------------------------------------------------------------------------- query | insert xxxx cpu_cost | 4817 state | active query_id | 1008305xxx transaction_id | 1008305xxx
當前運行的Query按照內存消耗排序:
--2.0及以上語法 SELECT query,((extend_info::json)->'total_mem_max_bytes')::text::bigint AS mem_max_cost,state,query_id,transaction_id FROM hg_stat_activity WHERE state = 'active' ORDER BY 2 DESC;
示例返回結果:
--------------------------------------------------------------------------------- query | update xxxx; mem_max_cost | 5727634542 state | active query_id | 10053302784827629 transaction_id | 10053302784827629 --------------------------------------------------------------------------------- query | select xxxx; mem_max_cost | 19535640 state | active query_id | 10083259096119559 transaction_id | 10083259096119559
查看當前實例正在運行且耗時較長的Query:
--2.0及以上語法 SELECT current_timestamp - query_start AS runtime, datname::text, usename, query, query_id FROM hg_stat_activity WHERE state != 'idle' AND backend_type = 'client backend' AND application_name != 'hologres' ORDER BY 1 DESC; --1.3及以下語法 SELECT current_timestamp - query_start AS runtime, datname::text, usename, query, pid FROM pg_stat_activity WHERE state != 'idle' AND backend_type = 'client backend' AND application_name != 'hologres' ORDER BY 1 DESC;
示例返回結果:
runtime | datname | usename | query_id | current_query -----------------+----------------+----------+------------------------------------ 00:00:24.258388 | holotest | 123xxx | 1267xx | UPDATE xxx; 00:00:1.186394 | testdb | 156xx | 1783xx | select xxxx;
可以看到update耗時較久,已經運行了24s還沒有結束。
HoloWeb可視化活躍Query管理
您可以通過HoloWeb可視化查看活躍Query,并進行管理。
登錄HoloWeb控制臺,詳情請參見連接HoloWeb并執行查詢。
單擊頂部導航欄的診斷與優化。
在左側導航欄選擇活躍信息管理 > 活躍Query。
進入活躍Query頁面,單擊查詢,查看當前實例的活躍Query及對活躍Query進行管理。
查詢結果列表包含如下信息:
參數
說明
Query Start
查詢開始時間。
Runtime
查詢運行時間。
PID
查詢服務進程ID。
Query
查詢執行的SQL語句。
State
當前連接的狀態。常見的狀態如下:
active:活躍。
idle:空閑。
idle in transaction:長事務中的空閑狀態。
idle in transaction(Aborted):已失敗事務中的空閑狀態。
\N: 狀態為空,表示非用戶連接的進程,一般屬于系統后臺的維護進程,可以忽略。
User Name
當前連接的用戶名。
Application
查詢應用類型。
Client Address
查詢客戶端的IP地址。
如果Query長時間運行不結束,您可以單擊對應Query操作列的取消,終結Query。也可以多選Query,執行批量取消操作。
(可選)單擊目標查詢操作列的詳情,查看當前查詢的詳細信息。
您可在詳情頁面,執行如下操作:
復制:復制當前查詢執行的SQL語句。
格式化:格式化當前查詢執行的SQL語句。
排查鎖
可以通過活躍Query排查當前SQL是否有鎖或者被鎖,詳情請參見鎖以及排查鎖。
終止Query
不符合預期的Query需要終止,可以通過以下命令語句操作。
終止單個Query:
SELECT pg_cancel_backend(<pid>);
批量終止Query:
SELECT pg_cancel_backend(pid) ,query ,datname ,usename ,application_name ,client_addr ,client_port ,backend_start ,state FROM pg_stat_activity WHERE length(query) > 0 AND pid != pg_backend_pid() AND backend_type = 'client backend' AND application_name != 'hologres'
修改活躍Query超時時間
Hologres支持您通過如下方式修改活躍Query運行超時時間。
語法示例
SET statement_timeout = <time>;
參數說明
time:超時時間取值范圍為0~2147483647ms,單位默認為ms(當time后加單位時需要使用單引號,否則會報錯)。當前默認超時時間為8小時,該設置針對session級別生效。
說明SET statement_timeout = <time> 和要修改超時時間的SQL語句一起執行方可生效。
使用示例
設置超時時間為5000min,其中具體時間帶單位,5000min需要整體添加單引號。
SET statement_timeout = '5000min' ; SELECT * FROM tablename;
設置超時時間為5000ms。
SET statement_timeout = 5000 ; SELECT * FROM tablename;
修改空閑Query超時時間
參數idle_in_transaction_session_timeout描述了事務進入idle狀態后的超時行為,如果不設置參數值,默認不會做事務超時的釋放,容易發生事務不釋放,導致查詢被鎖死的情況。Hologres支持您通過如下方式修改空閑Query運行超時時間。
應用場景
當Query執行產生死鎖時,需要設置超時時間。例如如下代碼,未執行
commit
,開啟了一個事務,但是沒有提交,會造成事務泄漏,進而引發數據庫級別的死鎖,影響服務正常使用。BEGIN; SELECT * FROM t;
當出現這種死鎖場景時,可以通過設置idle_in_transaction_session_timeout超時時間來解決。當一個帶事務的空閑連接超過idle_in_transaction_session_timeout設置的時間還未提交或者回滾事務,系統將自動根據超時時間回滾事務,并關閉連接。
語法示例
--session修改空閑事務超時時間 SET idle_in_transaction_session_timeout=<time>; --DB級別修改空閑事務超時時間 ALTER database db_name SET idle_in_transaction_session_timeout=<time>;
參數說明
time:超時時間取值范圍為0~2147483647ms,單位默認為ms(當time后加單位時需要使用單引號,否則會報錯)。在Hologres V0.10及以下版本,默認值為0,即不會自動清理;在Hologres V1.1版本,默認值為10分鐘,超過10分鐘后將會回滾事務。
說明不建議超時時間設置過短,如果過短容易錯誤回滾正在使用中的事務。
使用示例
設置超時時間為300000ms。
--session修改空閑事務超時時間 SET idle_in_transaction_session_timeout=300000; --DB級別修改空閑事務超時時間 ALTER database db_name SET idle_in_transaction_session_timeout=300000;
查詢慢Query日志
從Hologres V0.10版本開始,支持進行慢query日志查詢,詳情請參見慢Query日志查看與分析。
常見問題
問題現象
執行SQL后出現報錯:
ERROR: canceling statement due to statement timeout
。問題原因及解決方法
原因1:客戶端或Hologres實例設置了超時時間,常見的超時時間如下。
通過數據服務生成API,數據服務的超時時間為
10s
,不可以修改,建議優化SQL以降低執行時間。HoloWeb或DataWorks的Hologres SQL模塊執行的Query,超時時間為
1h
,不可以修改,建議優化SQL以降低執行時間。為Hologres實例設置的超時時間,可以通過以下SQL查看設置的實例超時時間,如果是實例超時時間導致,可以根據業務情況重新設置合理的超時時間。
SHOW statement_timeout;
客戶端或應用設置的超時時間,需要業務排查客戶端的設置。如果是客戶端設置的超時時間導致,可以根據業務情況重新設置合理的超時時間。
原因2:執行DML SQL時對表執行了DROP或者Truncate操作導致超時。
Truncate的原理是
drop+create
即先刪除表再創建表。當執行DML SQL時,會獲取行鎖或表鎖,鎖相關內容請參見鎖以及排查鎖。此時再對這個表同時執行DROP或者Truncate,DROP或者Truncate操作會搶DML的鎖,然后系統會將DML SQL取消,即出現statement timeout
的報錯。解決方法:通過慢Query日志排查是否同一時間對該表執行
drop
或truncate
操作,示例如下,需避免此類操作。--示例查詢過去一天某張表執行的drop/truncate記錄 SELECT * FROM hologres.hg_query_log WHERE command_tag IN ('DROP TABLE','TRUNCATE TABLE') AND query LIKE '%xxx%' AND query_start >= now() - interval '1 day';