sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cómo cerrar conexiones inactivas en PostgreSQL automáticamente?

Para aquellos que estén interesados, esta es la solución que se me ocurrió, inspirada en el comentario de Craig Ringer:

(...) use un trabajo cron para ver cuándo la conexión estuvo activa por última vez (vea pg_stat_activity) y use pg_terminate_backend para eliminar las antiguas.(...)

La solución elegida se reduce así:

  • Primero, actualizamos a Postgresql 9.2.
  • Luego, programamos un subproceso para que se ejecute cada segundo.
  • Cuando se ejecuta el subproceso, busca conexiones antiguas inactivas.
    • Una conexión se considera inactiva si es estado es idle , idle in transaction , idle in transaction (aborted) o disabled .
    • Una conexión se considera antigua si es estado permaneció igual durante más de 5 minutos.
  • Hay subprocesos adicionales que hacen lo mismo que el anterior. Sin embargo, esos hilos se conectan a la base de datos con un usuario diferente.
  • Dejamos al menos una conexión abierta para cualquier aplicación conectada a nuestra base de datos. (rank() función)

Esta es la consulta SQL ejecutada por el hilo:

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