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