環境
PostgreSQL 11.4
ここ3日くらいPostgreSQLで意図しない「FATAL: terminating connection due to administrator command」が発生してpgpoolから切り離されて困っています。
PostgreSQLのログ
2019-07-19 07:50:01.632 JST [27138] FATAL: terminating connection due to administrator command
PostgreSQLの、ログの出力をdebug3、実行されたSQLをすべて出力している状態で現象が再現したのですが、ログを見ても原因が分かりません…
postgresql.conf
log_min_messages = debug3 log_statement = 'all'
「FATAL: terminating connection due to administrator command」となる直接の原因は、おそらく「SELECT pg_terminate_backend(pid)」が実行されていることです。
※とても参考にさせて頂いています。とてもすごい資料です。
2019-07-19 07:50:01.615 JST [10453] LOG: statement: SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE pid IN (
SELECT l.pid
FROM ( SELECT pid FROM pg_locks GROUP BY pid ) l
, pg_stat_activity a
WHERE l.pid = a.pid
AND now() - query_start > '5minutes'::INTERVAL
)
;
このクエリの結果、クエリが実行されてから5分を超えているプロセスにpg_terminate_backendしにいっています。「FATAL: terminating connection due to administrator command」を出力しているのは、プロセス番号7813なので、プロセス番号7813を抜き出すと以下の通りでした。
PostgreSQLのログ
2019-07-19 07:50:01.621 JST [7813] LOG: statement: BEGIN 2019-07-19 07:50:01.626 JST [7813] LOG: statement: SELECT tag , uid , game , comment FROM userreview_with_tag uwg WHERE EXISTS ( SELECT * FROM userreview_tag u WHERE u.uid = uwg.uid AND u.game = uwg.game AND timestamp >= ( SELECT timestamp FROM userreview_tag_last_check_timestamp ) ) ; 2019-07-19 07:50:01.630 JST [7813] LOG: statement: SELECT uid , game , tags FROM userreview_tag u WHERE timestamp >= ( SELECT timestamp FROM userreview_tag_last_check_timestamp ) 2019-07-19 07:50:01.632 JST [7813] FATAL: terminating connection due to administrator command
5minutesな設定でクエリを解放しそうなPostgreSQLの設定が「max_standby_streaming_delay」で、デフォルトは30秒なのですが、当時の自分がなんとなく300秒に設定していました。
userreview_tagテーブル/userreview_tag_last_check_timestampテーブルを長時間ロックしそうな処理はしていない…と思うのですが、してるのかな…
2019/07/19追記
pgpoolのログ
Jul 19 04:20:01 erogamescape13 pgpool[25274]: [2975989-1] 2019-07-19 04:20:01: pid 25274: LOG: reading and processing packets
Jul 19 04:20:01 erogamescape13 pgpool[25274]: [2975989-2] 2019-07-19 04:20:01: pid 25274: DETAIL: postmaster on DB node 1 was shutdown by administrative command
Jul 19 04:20:01 erogamescape13 pgpool[25274]: [2975990-1] 2019-07-19 04:20:01: pid 25274: LOG: received degenerate backend request for node_id: 1 from pid [25274]
Jul 19 04:20:01 erogamescape13 pgpool[10368]: [449-1] 2019-07-19 04:20:01: pid 10368: LOG: new IPC connection received
Jul 19 04:20:01 erogamescape13 pgpool[10368]: [450-1] 2019-07-19 04:20:01: pid 10368: LOG: watchdog received the failover command from local pgpool-II on IPC interface
Jul 19 04:20:01 erogamescape13 pgpool[10368]: [451-1] 2019-07-19 04:20:01: pid 10368: LOG: watchdog is processing the failover command [DEGENERATE_BACKEND_REQUEST] received from local pgpool-II on IPC interface
Jul 19 04:20:01 erogamescape13 pgpool[10368]: [452-1] 2019-07-19 04:20:01: pid 10368: LOG: we have got the consensus to perform the failover
Jul 19 04:20:01 erogamescape13 pgpool[10368]: [452-2] 2019-07-19 04:20:01: pid 10368: DETAIL: 1 node(s) voted in the favor
Jul 19 04:20:01 erogamescape13 pgpool[10367]: [2976456-1] 2019-07-19 04:20:01: pid 10367: LOG: Pgpool-II parent process has received failover request
Jul 19 04:20:01 erogamescape13 pgpool[10368]: [453-1] 2019-07-19 04:20:01: pid 10368: LOG: new IPC connection received
Jul 19 04:20:01 erogamescape13 pgpool[10368]: [454-1] 2019-07-19 04:20:01: pid 10368: LOG: received the failover indication from Pgpool-II on IPC interface
Jul 19 04:20:01 erogamescape13 pgpool[10368]: [455-1] 2019-07-19 04:20:01: pid 10368: LOG: watchdog is informed of failover start by the main process
Jul 19 04:20:01 erogamescape13 pgpool[10367]: [2976457-1] 2019-07-19 04:20:01: pid 10367: LOG: starting degeneration. shutdown host 192.168.0.13(5432)
2019/07/24追記
おそらく解決しました。
2013年9月9日から2013年9月15日に発生した障害について(続き)のときに対策として、以下のクエリをcronで5分おきに実行していました。
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE pid IN ( SELECT l.pid FROM ( SELECT pid FROM pg_locks GROUP BY pid ) l , pg_stat_activity a WHERE l.pid = a.pid AND now() - query_start > '5minutes'::INTERVAL ) ;
pg_locksテーブルに存在するクエリで、query_startから5分たったものはpg_terminate_backendで強制的にプロセスを落とすようにしていました。
pg_terminate_backendを実行すると、PostgreSQLのログに「FATAL: terminating connection due to administrator command」が記録されます。また、pg_terminate_backend()関数の値が定数ではない場合、pgpoolから切り離されます。
5分も実行しているクエリなんかあるのかな…と思っていたら
- BEGINではじまるトランザクションで5分以上かかる処理が存在する
- ユーザーさんが5分を超えるクエリを実行することがある。いまいちなSQLの場合は、いつまでも処理が終わらずにCPU使用率が100%にはりつく※ErogameScapeは誰でもクエリを実行できるようにしています。
ことがあることが分かったので、長い間実行しているクエリは殺す必要があります
twitterで「pg_terminate_backend」ではなく「pg_cancel_backend」を使用した方がよいと教わりましたので、「pg_cancel_backend」に置換しました。