DBAtlas · Atlas de operaciones de bases de datos

Terminar de forma masiva y controlada las sesiones 'idle in transaction' largas

PostgreSQLSesiones

Comando

-- 1) Dry run first: who will be affected?
SELECT pid, usename, application_name, client_addr,
       now() - state_change AS idle_for, left(query, 80) AS last_query
FROM pg_stat_activity
WHERE state IN ('idle in transaction', 'idle in transaction (aborted)')
  AND now() - state_change > interval '15 minutes'
  AND backend_type = 'client backend'
  AND pid <> pg_backend_pid();

-- 2) Terminate; wait up to 5 s for each process to exit
SELECT pid, usename, now() - state_change AS idle_for,
       pg_terminate_backend(pid, 5000) AS terminated
FROM pg_stat_activity
WHERE state IN ('idle in transaction', 'idle in transaction (aborted)')
  AND now() - state_change > interval '15 minutes'
  AND backend_type = 'client backend'
  AND pid <> pg_backend_pid();

Qué hace

Primero lista las sesiones que han dejado una transacción abierta e inactiva durante un tiempo determinado y luego las termina; el parámetro timeout espera hasta que el proceso haya salido realmente (o venza el timeout).

Cuándo usarlo

Para una intervención de emergencia cuando sesiones olvidadas que retienen bloqueos causan bloqueos, o frenan el xmin horizon y paralizan el VACUUM.

Precaución

pg_cancel_backend no hace nada con una sesión 'idle in transaction' (no hay ninguna consulta en curso que cancelar); se requiere pg_terminate_backend y se revierten todos los cambios sin commit. Acote el filtro por usename/application_name; excluya las sesiones de replicación, backup y monitoreo. Los connection pools volverán a abrir las conexiones terminadas. Si vence el timeout, la función emite una advertencia y devuelve false. Como solución permanente, defina idle_in_transaction_session_timeout por rol.

Abrir en DBAtlas →

Relacionado