PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como fechar conexões ociosas no PostgreSQL automaticamente?


Para quem estiver interessado, aqui está a solução que encontrei, inspirada no comentário de Craig Ringer:

(...) use um cron job para ver quando a conexão foi ativa pela última vez (veja pg_stat_activity) e use pg_terminate_backend para eliminar as antigas.(...)

A solução escolhida fica assim:
  • Primeiro, atualizamos para o Postgresql 9.2.
  • Em seguida, agendamos um encadeamento para ser executado a cada segundo.
  • Quando o encadeamento é executado, ele procura conexões inativas antigas.
    • Uma conexão é considerada inativa se for estado é idle , idle in transaction , idle in transaction (aborted) ou disabled .
    • Uma conexão é considerada antiga se for estado permaneceu o mesmo por mais de 5 minutos.
  • Existem tópicos adicionais que fazem o mesmo que acima. No entanto, esses encadeamentos se conectam ao banco de dados com usuários diferentes.
  • Deixamos pelo menos uma conexão aberta para qualquer aplicativo conectado ao nosso banco de dados. (rank() função)

Esta é a consulta SQL executada pelo thread:
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