web-dev-qa-db-ja.com

PostgreSQLのアイドル接続を自動的に閉じる方法は?

一部のクライアントはpostgresqlデータベースに接続しますが、接続は開いたままにします。一定量の非アクティブ後にPostgresqlにこれらの接続を閉じるように指示することは可能ですか?

TL; DR

Postgresqlバージョンを使用している場合> = 9.2
THENを使用 私が思いついた解決策

コードを書きたくない場合
THENを使用 arqnidの解

38
Stephan

興味のある方のために、 Craig Ringer のコメントに触発された、私が思いついた解決策を以下に示します。

(...)cronジョブを使用して、接続が最後にアクティブになった時間を調べ(pg_stat_activityを参照)、pg_terminate_backendを使用して古い接続を削除します。(...)

選択したソリューションは次のようになります。

  • まず、Postgresql 9.2にアップグレードします。
  • 次に、1秒ごとに実行するスレッドをスケジュールします。
  • スレッドが実行されると、古い非アクティブな接続を探します。
    • 接続は、そのstateidleidle in transactionidle in transaction (aborted)またはdisabledのいずれかである場合、 inactive と見なされます。
    • 接続は、stateが5分以上同じままであった場合、 old と見なされます。
  • 上記と同じことを行う追加のスレッドがあります。ただし、これらのスレッドは異なるユーザーでデータベースに接続します。
  • データベースに接続されているアプリケーションに対して、少なくとも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
42
Stephan

PgBouncer のようなプロキシを介して接続します。これにより、server_idle_timeout秒。

14
araqnid

9.6以上のPostgreSQLを使用している場合、さらに簡単な解決策があります。 5分ごとにすべてのアイドル状態の接続を削除する場合、次のコマンドを実行するだけです。

alter system set idle_in_transaction_session_timeout='5min';

スーパーユーザーとしてアクセスできない場合(Azureクラウドの例)、試してください:

SET SESSION idle_in_transaction_session_timeout = '5min';

ただし、後者は現在のセッションでのみ機能しますが、ほとんどの場合、これは望みのものではありません。

無効化機能

alter system set idle_in_transaction_session_timeout=0;

または

SET SESSION idle_in_transaction_session_timeout = 0;

(ところで、0はデフォルト値です)。

alter systemを使用する場合、構成をリロードして変更を開始する必要があり、変更は永続的です。たとえば、サーバーを再起動する場合、クエリを再実行する必要はありません。

機能の状態を確認するには:

show idle_in_transaction_session_timeout;
9
fresko