За тези, които се интересуват, ето решението, което измислих, вдъхновено от коментара на Craig Ringer:
(...) използвайте задача на cron, за да видите кога последно е била активна връзката (вижте pg_stat_activity) и използвайте pg_terminate_backend, за да унищожите старите.(...)
Избраното решение идва по следния начин:
- Първо, надграждаме до Postgresql 9.2.
- След това планираме нишка да се изпълнява всяка секунда.
- Когато нишката се изпълнява, тя търси всички стари неактивни връзки.
- Връзката се счита за неактивна ако е състояние е или
idle
,idle in transaction
,idle in transaction (aborted)
илиdisabled
. - Връзката се счита за стара ако е състояние остана същото за повече от 5 минути.
- Връзката се счита за неактивна ако е състояние е или
- Има допълнителни нишки, които правят същото като по-горе. Тези нишки обаче се свързват към базата данни с различен потребител.
- Оставяме отворена поне една връзка за всяко приложение, свързано с нашата база данни. (
rank()
функция)
Това е SQL заявката, изпълнявана от нишката:
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