PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment fermer automatiquement les connexions inactives dans PostgreSQL ?

Pour ceux que ça intéresse, voici la solution que j'ai trouvée, inspirée du commentaire de Craig Ringer :

(...) utilisez une tâche cron pour voir quand la connexion a été active pour la dernière fois (voir pg_stat_activity) et utilisez pg_terminate_backend pour tuer les anciennes.(...)

La solution choisie se résume ainsi :

  • Tout d'abord, nous effectuons une mise à niveau vers Postgresql 9.2.
  • Ensuite, nous planifions l'exécution d'un thread toutes les secondes.
  • Lorsque le thread s'exécute, il recherche les anciennes connexions inactives.
    • Une connexion est considérée comme inactive si son état est soit idle , idle in transaction , idle in transaction (aborted) ou disabled .
    • Une connexion est considérée comme ancienne si son état resté le même pendant plus de 5 minutes.
  • Il existe des threads supplémentaires qui font la même chose que ci-dessus. Cependant, ces threads se connectent à la base de données avec un utilisateur différent.
  • Nous laissons au moins une connexion ouverte pour toute application connectée à notre base de données. (rank() fonction)

Voici la requête SQL exécutée par le 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