SELECT pid, now() - xact_start AS dur FROM pg_stat_activity
ORDER BY dur DESC LIMIT 5;
SELECT slot_name, active FROM pg_replication_slots;
VACUUM (VERBOSE, ANALYZE) orders;

删掉三千万行后表还是 40G,pg_stat_user_tables 里 n_dead_tup 一直涨,磁盘空间一点没还回来。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。

原因不复杂,删行只是把元组标成死元组,空间要靠 vacuum 回收,长事务或闲置复制槽把 xmin 顶住,清理永远轮不到这些行,表只会继续涨。

「PG 表膨胀回收」排查到最后往往是很小的一处差异,前面那些复杂猜测可以先放一放。备份不是备了就行,恢复一次才算数,很多备份文件打开才发现是空的。

接口问题先分清是没发出去、发出去了没收到,还是收到了处理失败。偶发问题先统计频率,一小时几次和一天一次,查法完全不同。

改完顺手把文档补一句,省得下次自己重新推一遍。

处理上按这个顺序:先查运行最久的事务,看有没有开着不提交的;再看复制槽是否 active 为 false,restart_lsn 停在几天前;确认没有长事务后对该表单独跑 VACUUM ANALYZE。

改完只确认一件事:n_dead_tup 回落到几千,表大小不再每天上涨,查询耗时也稳了。

作者 9823189