PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie werden inaktive Verbindungen in PostgreSQL automatisch geschlossen?

Für diejenigen, die daran interessiert sind, hier ist die Lösung, die ich mir ausgedacht habe, inspiriert von Craig Ringers Kommentar:

(...) Verwenden Sie einen Cron-Job, um zu sehen, wann die Verbindung zuletzt aktiv war (siehe pg_stat_activity) und verwenden Sie pg_terminate_backend, um alte zu beenden.(...)

Die gewählte Lösung sieht so aus:

  • Zuerst aktualisieren wir auf Postgresql 9.2.
  • Dann planen wir einen Thread, der jede Sekunde ausgeführt wird.
  • Wenn der Thread läuft, sucht er nach alten inaktiven Verbindungen.
    • Eine Verbindung wird als inaktiv betrachtet wenn sein Zustand ist entweder idle , idle in transaction , idle in transaction (aborted) oder disabled .
    • Eine Verbindung gilt als alt wenn sein Zustand blieb für mehr als 5 Minuten gleich.
  • Es gibt zusätzliche Threads, die dasselbe tun wie oben. Diese Threads verbinden sich jedoch mit anderen Benutzern mit der Datenbank.
  • Wir lassen mindestens eine Verbindung offen für jede Anwendung, die mit unserer Datenbank verbunden ist. (rank() Funktion)

Dies ist die vom Thread ausgeführte SQL-Abfrage:

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