Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to close idle connections in PostgreSQL automatically?

Some clients connect to our postgresql database but leave the connections opened. Is it possible to tell Postgresql to close those connection after a certain amount of inactivity ?

TL;DR

IF you're using a Postgresql version >= 9.2
THEN use the solution I came up with

IF you don't want to write any code
THEN use arqnid's solution

IF you don't want to write any code
AND you're using a Postgresql version >= 14
THEN use Laurenz Albe's solution

like image 200
Stephan Avatar asked Sep 12 '12 15:09

Stephan


People also ask

How do I close all Postgres connections?

How to kill all other active connections to your database in PostgreSQL? Using SQL Query, run the query below: SELECT pg_terminate_backend(pg_stat_activity. pid) FROM pg_stat_activity WHERE pg_stat_activity.

Is there a timeout for idle PostgreSQL connections?

No, something akin to the other answers is required for previous versions. SET SESSION is just for the current session (it will go back to the default once you open a new connection).

Why does PostgreSQL say idle connection?

idle: This indicates that the connection is idle and we need to track these connections based on the time that they have been idle. idle in transaction: This indicates the backend is in a transaction, but it is currently not doing anything and could be waiting for an input from the end user.

Where is PostgreSQL idle sessions?

If you want to see how many idle connections you have that have an open transaction, you could use: select * from pg_stat_activity where (state = 'idle in transaction') and xact_start is not null; This will provide a list of open connections that are in the idle state, that also have an open transaction.


1 Answers

For those who are interested, here is the solution I came up with, inspired from Craig Ringer's comment:

(...) use a cron job to look at when the connection was last active (see pg_stat_activity) and use pg_terminate_backend to kill old ones.(...)

The chosen solution comes down like this:

  • First, we upgrade to Postgresql 9.2.
  • Then, we schedule a thread to run every second.
  • When the thread runs, it looks for any old inactive connections.
    • A connection is considered inactive if its state is either idle, idle in transaction, idle in transaction (aborted) or disabled.
    • A connection is considered old if its state stayed the same during more than 5 minutes.
  • There are additional threads that do the same as above. However, those threads connect to the database with different user.
  • We leave at least one connection open for any application connected to our database. (rank() function)

This is the SQL query run by the 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 
like image 199
Stephan Avatar answered Sep 20 '22 14:09

Stephan