2012-09-12 23 views
26

Alcuni client si connettono al nostro database postgresql ma lasciano aperte le connessioni. È possibile dire a Postgresql di chiudere la connessione dopo una certa quantità di inattività?Come chiudere automaticamente le connessioni inattive in PostgreSQL?

TL; DR

se si sta utilizzando una versione di PostgreSQL> = 9.2
quindi utilizzare the solution I came up with

SE non si vuole scrivere alcun codice
quindi utilizzare arqnid's solution

+2

Si potrebbe utilizzare un job cron a guardare quando la connessione precedentemente attivo (vedi 'pg_stat_activity') e l'uso' pg_terminate_backend' per uccidere quelli vecchi. Facilmente espresso in una semplice query. Non sono sicuro che 'pg_terminate_backend' fosse disponibile nella piuttosto antica 8.3, comunque. –

risposta

27

Per coloro che sono interessati, ecco la soluzione mi è venuta, ispirato dal commento Craig Ringer s':

(...) utilizzare un job cron a guardare quando la connessione è stata ultima attiva (vedi pg_stat_activity) e utilizzare pg_terminate_backend per uccidere quelli vecchi (...)

La soluzione scelta si riduce in questo modo:.

  • Innanzitutto, 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 stato è o idle, idle in transaction, idle in transaction (aborted) o disabled.
    • Una connessione è considerata vecchio se il suo ultimo stato è cambiato per più di 5 minuti.
  • Ci sono thread aggiuntivi che fanno lo stesso di sopra. Tuttavia, questi thread si connettono al database con utenti diversi.
  • Lasciamo aperta almeno una connessione per qualsiasi applicazione connessa al nostro database. (rank() funzione)

Questa è la query SQL gestito dalla discussione:

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 
+0

Infine, ci siamo spostati su Postgresql 9.2 per trarre vantaggio da 'pg_terminate_backend'. Abbiamo usato un lavoro come cron per invocare periodicamente 'pg_terminate_backend'. – Stephan

+0

Puoi pubblicare uno script che usi? – Andrus

+0

@Andrus Vedere l'aggiornamento nella mia risposta. – Stephan

10

Connessione tramite un proxy come PgBouncer che chiuderà le connessioni dopo server_idle_timeout secondi.

+0

can pg pool II fa lo stesso? – wolf97084

+0

@ wolf97084 Leggi questa risposta: http: // stackoverflow.com/a/30769511/363573 – Stephan

+0

@Stephan Grazie! Mi mancherebbe la risposta se non mi avessi taggato nel commento. – wolf97084

Problemi correlati