PostgreSQL 活跃会话诊断(Active Sessions)
适用:PG 9.6+(
pg_stat_activity的wait_event_type/wait_event列自 9.6 起,query_id列自 14 起,backend_type列自 14 起)。
「PG 卡了 / CPU 高」时第一步永远是看当前会话在干什么。核心工具是 pg_stat_activity 视图。
查看当前活跃 Session
SELECT pid,
usename,
application_name,
client_addr,
state,
wait_event_type,
wait_event,
now() - query_start AS query_age,
left(query, 200) AS query
FROM pg_stat_activity
WHERE state = 'active'
ORDER BY query_start;
关键列含义
| 列 | 含义 |
|---|---|
pid | 后端进程 ID,可配合 pg_terminate_backend(pid) 终止 |
state | active 正在执行 / idle 空闲 / idle in transaction 事务内空闲 / idle in transaction (aborted) 事务已失败未回滚 |
wait_event_type | 等待类别:Lock 锁等待、LWLock 轻量锁、IO 磁盘 IO、CPU 正在 CPU 上执行、Client 等客户端 |
wait_event | 具体等待点(如 tuple、relation、WALWrite 等) |
query_age | 当前查询已执行时长,从 query_start 计算 |
query_id | PG 14+ 的查询指纹,可与 pg_stat_statements 关联(PG 15+ 默认开启计算) |
backend_type | PG 14+ 的后端类型(client backend / autovacuum worker 等) |
state = 'idle in transaction'是常见的「卡住」元凶:事务开着没提交, 占着连接和锁;idle in transaction (aborted)说明事务已报错但没回滚, 同样要处理。
CPU 高占用定位流程
- 先看有没有进程在 CPU 上跑(PG 13+ 才有
wait_event_type = 'CPU'):
SELECT pid, now() - query_start AS age, left(query, 150) AS query
FROM pg_stat_activity
WHERE state = 'active'
AND wait_event_type = 'CPU'
ORDER BY query_start;
- 看谁的查询跑了最久:
SELECT pid, usename, now() - query_start AS age,
wait_event_type, wait_event, left(query, 200) AS query
FROM pg_stat_activity
WHERE state = 'active' AND pid <> pg_backend_pid()
ORDER BY query_start
LIMIT 20;
- 如果是反复出现的同一条 SQL,用
pg_stat_statements按累计 CPU / 执行时间排名(需先CREATE EXTENSION pg_stat_statements,PG 13+ 才有total_exec_time/mean_exec_time,9.x–12 为total_time/mean_time):
SELECT calls,
round(total_exec_time / 1000) AS total_ms,
round(mean_exec_time / 1000) AS mean_ms,
left(query, 200) AS query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
- 对嫌疑 SQL 做
EXPLAIN (ANALYZE, BUFFERS),看计划是否合理、是否 触发大量 Buffer/排序/嵌套循环。
终止 / 取消会话
-- 取消当前正在执行的查询(进程保留,适合误跑的大查询)
SELECT pg_cancel_backend(pid);
-- 强制终止整个后端进程(会断开连接,事务回滚;慎用)
SELECT pg_terminate_backend(pid);
相关排查点
- 锁等待:
wait_event_type = 'Lock'+pg_locks/pg_blocking_pids(pid)查是谁堵住了谁。 - autovacuum / 后台进程占资源:过滤
backend_type(PG 14+)或backend_start很久的autovacuum worker。 - 连接数打满:
SELECT count(*) FROM pg_stat_activityvsSHOW max_connections;, 配合pg_stat_activity看是否大量idle连接占坑。
Backlinks (2)
flowchart LR
n0["Database"]
n1["PostgreSQL 活跃会话诊断(Active Sessions)"]
n2["PostgreSQL 磁盘占用查看(Table Size / Datafile)"]
n3["PostgreSQL"]
n4["PostgreSQL 查看慢查询(Slow Query)"]
n5["PostgreSQL WAL 与 LSN"]
n6["Knowledge"]
n7["Cloud"]
n8["Infrastructure"]
n0 --> n3
n3 --> n1
n3 --> n2
n3 --> n4
n3 --> n5
n4 --> n1
n6 --> n0
n6 --> n8
n8 --> n7
click n0 "../../" "Database"
click n1 "./" "PostgreSQL 活跃会话诊断(Active Sessions)"
click n2 "../disk-usage/" "PostgreSQL 磁盘占用查看(Table Size / Datafile)"
click n3 "../" "PostgreSQL"
click n4 "../slow-queries/" "PostgreSQL 查看慢查询(Slow Query)"
click n5 "../wal-lsn/" "PostgreSQL WAL 与 LSN"
click n6 "../../../" "Knowledge"
click n7 "../../../infrastructure/cloud/" "Cloud"
click n8 "../../../infrastructure/" "Infrastructure"