実行中のクエリを確認する
PostgreSQLで現在実行中のクエリを確認するにはpg_stat_activityビューをSELECTする。
SELECT pid, usename, state, query, query_start FROM pg_stat_activity;
pid | usename | state | query | query_start
-----+----------+--------+---------------------------------------------------------------------------------------+-------------------------------
94 | postgres | active | BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 1; SELECT pg_sleep(30); | 2026-07-21 12:56:41.72517+00
pg_stat_activityには以下のような主要なカラムが含まれる。
pid: バックエンドプロセスIDusename: 接続ユーザー名state: セッションの状態(active、idle、idle in transactionなど)query: 直近に実行された、または実行中のクエリquery_start:queryが開始された時刻wait_event_type: 待機中のイベント種別(待機していない場合はNULL)wait_event: 待機中のイベント名
長時間実行されているクエリを特定するには、query_startから現在時刻までの経過時間で絞り込む。
SELECT pid, usename, now() - query_start AS duration, query
FROM pg_stat_activity
WHERE state = 'active'
ORDER BY duration DESC;
ロック待ちのクエリを確認する
ロック待ちが発生しているセッションはwait_event_typeがLockになる。
SELECT pid, usename, wait_event_type, wait_event, query
FROM pg_stat_activity
WHERE wait_event_type = 'Lock';
pid | usename | wait_event_type | wait_event | query
-----+----------+-----------------+---------------+-----------------------------------------------------------
101 | postgres | Lock | transactionid | UPDATE accounts SET balance = balance + 100 WHERE id = 1;
wait_eventにはロックの種類が表示される。transactionidは他のトランザクションの終了待ち、relationはテーブルロックの待ちを表す。
ロックをブロックしているセッションを特定する
pg_blocking_pids関数を使うと、指定したpidのセッションをブロックしているセッションのpidを配列で取得できる。
SELECT pid, wait_event_type, wait_event, pg_blocking_pids(pid) AS blocked_by, query
FROM pg_stat_activity
WHERE cardinality(pg_blocking_pids(pid)) > 0;
pid | wait_event_type | wait_event | blocked_by | query
-----+-----------------+---------------+------------+-----------------------------------------------------------
101 | Lock | transactionid | {94} | UPDATE accounts SET balance = balance + 100 WHERE id = 1;
上記の結果からpid 101のセッションがpid 94のセッションによってブロックされていると分かる。ブロックしている側のセッション(pid 94)をpg_stat_activityから確認すると、原因になっているクエリを特定できる。
SELECT pid, state, query, query_start FROM pg_stat_activity WHERE pid = 94;
pid | state | query | query_start
-----+--------+---------------------------------------------------------------------------------------+-------------------------------
94 | active | BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 1; SELECT pg_sleep(30); | 2026-07-21 12:56:41.72517+00
トランザクションをコミットせずに保持しているセッションが原因であると分かる。
\第一線のプログラマーの行動原理を学べる!/
