興味のある方のために、Craig Ringerのコメントから着想を得て、私が思いついた解決策を以下に示します。
(...)cronジョブを使用して、接続が最後にアクティブになった日時を確認し(pg_stat_activityを参照)、pg_terminate_backendを使用して古い接続を強制終了します。(...)
選択したソリューションは次のようになります:
- まず、Postgresql9.2にアップグレードします。
- 次に、スレッドを1秒ごとに実行するようにスケジュールします。
- スレッドが実行されると、古い非アクティブな接続があれば検索されます。
- 接続は非アクティブと見なされます 状態の場合
idle
のいずれかです 、idle in transaction
、idle in transaction (aborted)
またはdisabled
。 - 接続は古いと見なされます 状態の場合 5分以上同じままでした。
- 接続は非アクティブと見なされます 状態の場合
- 上記と同じことを行う追加のスレッドがあります。ただし、これらのスレッドは異なるユーザーでデータベースに接続します。
- データベースに接続されているアプリケーションに対して、少なくとも1つの接続を開いたままにします。 (
rank()
機能)
これは、スレッドによって実行されるSQLクエリです:
WITH inactive_connections AS (
SELECT
pid,
rank() over (partition by client_addr order by backend_start ASC) as rank
FROM
pg_stat_activity
WHERE
-- Exclude the thread owned connection (ie no auto-kill)
pid <> pg_backend_pid( )
AND
-- Exclude known applications connections
application_name !~ '(?:psql)|(?:pgAdmin.+)'
AND
-- Include connections to the same database the thread is connected to
datname = current_database()
AND
-- Include connections using the same thread username connection
usename = current_user
AND
-- Include inactive connections only
state in ('idle', 'idle in transaction', 'idle in transaction (aborted)', 'disabled')
AND
-- Include old connections (found with the state_change field)
current_timestamp - state_change > interval '5 minutes'
)
SELECT
pg_terminate_backend(pid)
FROM
inactive_connections
WHERE
rank > 1 -- Leave one connection for each application connected to the database