PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come chiudere automaticamente le connessioni inattive in PostgreSQL?

Per coloro che sono interessati, ecco la soluzione che ho trovato, ispirata dal commento di Craig Ringer:

(...) usa un cron job per vedere quando la connessione è stata attiva l'ultima volta (vedi pg_stat_activity) e usa pg_terminate_backend per eliminare quelli vecchi.(...)

La soluzione scelta si riduce così:

  • In primo luogo, eseguiamo l'aggiornamento a Postgresql 9.2.
  • Quindi, pianifichiamo un thread da eseguire ogni secondo.
  • Quando il thread viene eseguito, cerca eventuali vecchie connessioni inattive.
    • Una connessione è considerata inattiva se il suo stato è idle , idle in transaction , idle in transaction (aborted) o disabled .
    • Una connessione è considerata vecchia se il suo stato è rimasto lo stesso per più di 5 minuti.
  • Ci sono thread aggiuntivi che fanno lo stesso di cui sopra. Tuttavia, quei thread si connettono al database con un utente diverso.
  • Lasciamo almeno una connessione aperta per qualsiasi applicazione connessa al nostro database. (rank() funzione)

Questa è la query SQL eseguita dal 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