C'è un timeout per le connessioni PostgreSQL inattive?


94
1 S postgres  5038   876  0  80   0 - 11962 sk_wai 09:57 ?        00:00:00 postgres: postgres my_app ::1(45035) idle                                                                                 
1 S postgres  9796   876  0  80   0 - 11964 sk_wai 11:01 ?        00:00:00 postgres: postgres my_app ::1(43084) idle             

Ne vedo molti. Stiamo cercando di riparare la nostra perdita di connessione. Ma nel frattempo, vogliamo impostare un timeout per queste connessioni inattive, forse massimo a 5 minuti.


come ti connetti al DB? socketTimeout potrebbe essere quello che stai cercando.
Doon

Abbiamo questa app web Pylons legacy e abbiamo usato SQLAlchemy ma a quanto pare non l'abbiamo usata correttamente. Non ricordo Stiamo cercando di riparare la perdita. socketTimeoutdal documento sembra che questo chiuda completamente la connessione al DB. Sto cercando di chiudere ogni inattivo e il contatore si avvia non appena viene stabilita la connessione.
user1012451


@ user1012451 Quando dici "chiudi ogni inattività", intendi terminare le <IDLE> in transactionsessioni, lasciando la sessione in esecuzione ma nello <IDLE>stato? In altre parole, terminare la transazione ma non la sessione? (Downvoted: domanda poco chiara)
Craig Ringer

@ CraigRinger dopo un po ', raggiungiamo la connessione massima del client. Per risolverlo, dobbiamo riavviare la webapp, che forza il riavvio anche di postgresql. Questo cancella ogni connessione. Quando li vediamo idleper sempre, chiediamo se possiamo impostare un timeout su ogni connessione / sessione (onestamente non conosco la terminologia corretta, mi dispiace). Se una transazione richiede 5 minuti per una normale app web, qualcosa deve essere sbagliato ...
user1012451

Risposte:


118

Sembra che tu abbia un file perdita di connessione nella tua applicazione perché non riesce a chiudere le connessioni in pool . Non hai problemi solo con le <idle> in transactionsessioni, ma con troppe connessioni in generale.

Eliminare le connessioni non è la risposta giusta per questo, ma è una soluzione temporanea accettabile.

Invece di riavviare PostgreSQL per avviare tutte le altre connessioni da un database PostgreSQL, vedere: Come posso scollegare tutti gli altri utenti da un database postgres? e come eliminare un database PostgreSQL se ci sono connessioni attive ad esso? . Quest'ultimo mostra una query migliore.

Per impostare i timeout, come suggerito da @Doon, vedere Come chiudere automaticamente le connessioni inattive in PostgreSQL? , che consiglia di utilizzare PgBouncer per eseguire il proxy per PostgreSQL e gestire le connessioni inattive. Questa è un'ottima idea se hai un'applicazione difettosa che perde comunque le connessioni; Consiglio vivamente di configurare PgBouncer.

UN keepalive TCP non farà il lavoro qui, perché l'app è ancora connessa e attiva, semplicemente non dovrebbe esserlo.

In PostgreSQL 9.2 e versioni successive, è possibile utilizzare la nuova state_changecolonna timestamp e il statecampo di pg_stat_activityper implementare un mietitore di connessione inattivo. Fai eseguire a un cron job qualcosa del genere:

SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE datname = 'regress'
      AND pid <> pg_backend_pid()
      AND state = 'idle'
      AND state_change < current_timestamp - INTERVAL '5' MINUTE;

Nelle versioni precedenti è necessario implementare schemi complicati che tengano traccia di quando la connessione è diventata inattiva. Non si disturbi; basta usare pgbouncer.


4
Bene, ma ucciderà altri backend PgAdmin. Usa condizione aggiuntiva application_name = ''
Andrew Selivanov

1
Posso eseguire pg_terminate_backend se sto usando pgbouncer?
Henley Chiu

@HenleyChiu Non vedo perché no, anche se non ho controllato specificamente.
Craig Ringer

1
L'esecuzione di questo sembra aver interrotto il mio processo di invio WAL
Joseph Persie

@CraigRinger anche una connessione psql è considerata come connessione inattiva. E perché si deve chiudere la connessione inattiva in primo luogo. Ho un codice di lunga esecuzione che stabilisce la connessione con pg esegue alcune operazioni dml e quindi attendo il messaggio sulla coda e quindi eseguo altre operazioni dml.Ora durante quel periodo cioè mentre è in attesa sulla coda (per il messaggio) come menzionato sopra anche allora la connessione con i postges è idle. perché dovrei chiuderlo.
Viren

72

In PostgreSQL 9.6, c'è una nuova opzione idle_in_transaction_session_timeoutche dovrebbe realizzare ciò che descrivi. Puoi impostarlo utilizzando il SETcomando, ad esempio:

SET SESSION idle_in_transaction_session_timeout = '5min';

1
Fa schifo dover chiedere qualcosa di così semplice, ma sono nuovo di zecca ai database in generale - Potresti fornire un esempio molto semplice di come utilizzare questa funzione?
sg

Qualcosa di simile nelle versioni precedenti di PostgreSQL ??
sdsc81

No, per le versioni precedenti è richiesto qualcosa di simile alle altre risposte.
shosti

È necessario impostare questo parametro ad ogni riavvio del database? O dopo che hai fatto una volta che puoi dimenticarti? Grazie
fresko

5
SET SESSIONè solo per la sessione corrente (tornerà all'impostazione predefinita una volta aperta una nuova connessione). Puoi anche impostare i parametri di configurazione a livello di database usando ad esempio ALTER DATABASE SET idle_in_transaction_session_timeout = '5min', o usando i file di configurazione (vedi postgresql.org/docs/current/static/config-setting.html ).
shosti

22

In PostgreSQL 9.1, le connessioni inattive con la seguente query. Mi ha aiutato a scongiurare la situazione che richiedeva il riavvio del database. Ciò accade principalmente con le connessioni JDBC aperte e non chiuse correttamente.

SELECT
   pg_terminate_backend(procpid)
FROM
   pg_stat_activity
WHERE
   current_query = '<IDLE>'
AND
   now() - query_start > '00:10:00';

1
pg_terminate_backend è in dal 8.4
Andrew Banks

8

se stai usando postgresql 9.6+, allora nel tuo postgresql.conf puoi impostare

idle_in_transaction_session_timeout = 30000 (msec)


0

Una possibile soluzione alternativa che consente di abilitare il timeout della sessione del database senza un'attività pianificata esterna è utilizzare l'estensione pg_timeout che ho sviluppato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.