För den som är intresserad, här är lösningen jag kom fram till, inspirerad av Craig Ringers kommentar:
(...) använd ett cron-jobb för att titta på när anslutningen senast var aktiv (se pg_stat_activity) och använd pg_terminate_backend för att döda gamla.(...)
Den valda lösningen ser ut så här:
- Först uppgraderar vi till Postgresql 9.2.
- Då schemalägger vi en tråd som ska köras varje sekund.
- När tråden körs letar den efter gamla inaktiva anslutningar.
- En anslutning anses vara inaktiv om dess tillstånd är antingen
idle
,idle in transaction
,idle in transaction (aborted)
ellerdisabled
. - En anslutning anses vara gammal om dess tillstånd förblev densamma under mer än 5 minuter.
- En anslutning anses vara inaktiv om dess tillstånd är antingen
- Det finns ytterligare trådar som gör samma sak som ovan. Men dessa trådar ansluter till databasen med en annan användare.
- Vi lämnar minst en anslutning öppen för alla program som är anslutna till vår databas. (
rank()
funktion)
Det här är SQL-frågan som körs av tråden:
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