Đối với những ai quan tâm, đây là giải pháp tôi đưa ra, lấy cảm hứng từ nhận xét của Craig Ringer:
(...) sử dụng cron job để xem thời điểm kết nối hoạt động lần cuối (xem pg_stat_activity) và sử dụng pg_termina_backend để loại bỏ các kết nối cũ. (...)
Giải pháp đã chọn xuất hiện như sau:
- Đầu tiên, chúng tôi nâng cấp lên Postgresql 9.2.
- Sau đó, chúng tôi lên lịch một chuỗi để chạy mỗi giây.
- Khi chuỗi chạy, nó sẽ tìm kiếm mọi kết nối cũ không hoạt động.
- Kết nối được coi là không hoạt động nếu trạng thái của nó
idle
,idle in transaction
,idle in transaction (aborted)
hoặcdisabled
. - Kết nối được coi là cũ nếu trạng thái của nó giữ nguyên trong hơn 5 phút.
- Kết nối được coi là không hoạt động nếu trạng thái của nó
- Có các chủ đề bổ sung thực hiện tương tự như trên. Tuy nhiên, các chuỗi đó kết nối với cơ sở dữ liệu với người dùng khác.
- Chúng tôi để mở ít nhất một kết nối cho bất kỳ ứng dụng nào được kết nối với cơ sở dữ liệu của chúng tôi. (
rank()
chức năng)
Đây là truy vấn SQL được chạy bởi chuỗi:
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