Encontrar quem segura o xmin horizon e impede o VACUUM de remover dead tuples
PostgreSQLManutençãoComando
SELECT 'session' AS source, pid::text AS id, usename::text AS owner, state AS detail,
age(backend_xmin) AS xmin_age
FROM pg_stat_activity
WHERE backend_xmin IS NOT NULL AND pid <> pg_backend_pid()
UNION ALL
SELECT 'prepared_xact', gid, owner::text, prepared::text, age(transaction)
FROM pg_prepared_xacts
UNION ALL
SELECT 'replication_slot', slot_name::text, slot_type, active::text,
greatest(age(xmin), age(catalog_xmin))
FROM pg_replication_slots
WHERE xmin IS NOT NULL OR catalog_xmin IS NOT NULL
UNION ALL
SELECT 'standby_feedback', application_name, usename::text, state, age(backend_xmin)
FROM pg_stat_replication
WHERE backend_xmin IS NOT NULL
ORDER BY xmin_age DESC NULLS LAST;O que faz
Lista, ordenadas pela idade do xmin, as quatro fontes que podem bloquear a limpeza de dead tuples: sessões que seguram snapshots, prepared transactions, replication slots e standbys que enviam hot_standby_feedback.
Quando usar
Quando o VACUUM VERBOSE reporta 'dead row versions cannot be removed yet', o bloat continua crescendo e a idade de XID não cai.
Atenção
O xmin mais antigo define o horizonte de limpeza; replication slots e o feedback de standbys afetam todos os bancos. Prepared transactions sobrevivem a restarts; verifique o dono e feche-as com COMMIT PREPARED / ROLLBACK PREPARED '<gid>'. Remover um slot não utilizado quebra o seu downstream (standby, CDC); verifique o dono antes. Executado em um standby, mostra apenas as sessões daquele standby.