MVCC 与 VACUUM
PostgreSQL 用多版本:读不加锁也能看到合适的快照。副作用是表会留下死元组,必须有人清。
表脏了吗
SELECT relname, n_live_tup, n_dead_tup, last_autovacuum, last_autoanalyze
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 20;
死元组长期很高:autovacuum 跟不上,或者被长事务挡住(老快照还需要那些行)。
SELECT pid, usename, xact_start, state, query
FROM pg_stat_activity
WHERE xact_start IS NOT NULL
ORDER BY xact_start;
常规维护
VACUUM (VERBOSE) app_schema.orders;
ANALYZE app_schema.orders;
VACUUM FULL 会重写表、要排他锁,不是日常手段。膨胀严重再考虑,并安排窗口。
回卷
事务 ID 是 32 位循环。autovacuum 会 freeze。如果 freeze 被挡住,实例会为了保护数据变得激进,甚至拒绝新事务。这是紧急故障,不是「再拖一天」。
SELECT datname, age(datfrozenxid)
FROM pg_database;
注意
把「表变大」都怪给没建索引,会漏掉 bloat。先看死元组、表膨胀、索引膨胀,再决定 rebuild 还是调 autovacuum。
参考:VACUUM