本文介绍一组PostgreSQL恢复测试脚本,核心结论是pg_dump/pg_restore后数据库并未就绪,需手动维护。测试比较了VACUUM、VACUUM FREEZE、ANALYZE等选项的耗时与WAL开销,并验证autovacuum能否自动补做。分区父表的统计信息需单独执行ANALYZE,vacuumdb --analyze会跳过父表。调查28篇文档,仅8篇建议ANALYZE、3篇建议VACUUM、1篇解释可见性映射,说明官方指南普遍缺失这一关键步骤。
PostgreSQL中“事务中空闲”会话虽不执行语句,但仍持有锁和连接槽,并可能阻止VACUUM清理死行。仅执行SELECT的会话在READ COMMITTED隔离级别下会阻塞ALTER TABLE并连带阻塞后续查询;REPEATABLE READ或已写入的会话还会阻碍清理。该超时默认值为0,可按角色设置idle_in_transaction_session_timeout,超时后连接被终止、事务回滚。
PostgreSQL 删除行后表在磁盘上不会缩小。实测 200 万行表删除一半后仍占 137MB,VACUUM 后不变,VACUUM FULL 才降至 68MB。VACUUM 仅使空间可复用,不归还操作系统。TRUNCATE 比 DELETE 快且 WAL 少,但会锁表且不触发触发器。将 fillfactor 设为 90 可提高 HOT 更新比例,使表更小。
实测 PostgreSQL 17 多租户单租户删除:级联删除与逐表删除耗时相同,瓶颈在外键触发器,需为外键列建索引。删除不阻塞其他租户读写,但阻塞该租户写入并阻碍 vacuum。批量删除应按执行计划选批次,过大反而全表扫描更慢。删除后数据库不缩小,空间留给新租户,数据仍残留在 WAL、备份、审计日志中。分区 DROP 最快,但需先删引用分区,且加排他锁,应设 lock_timeout。
PostgreSQL 行锁不存于共享内存,而是写入元组头:t_xmax 记录加锁事务 ID,t_infomask 位标记锁类型。四种锁强度由三位编码,FOR UPDATE 与键更新、删除冲突。多事务同时加锁时用 MultiXactId 指向磁盘成员列表,外键检查自动加 FOR KEY SHARE。锁提交后标记仍留在页上,直到 VACUUM 清理。大量短事务与长事务并发会快速消耗 multixact 成员空间,需监控避免超限。
PostgreSQL通过MVCC实现多版本并发控制,每次更新会保留旧版本元组,导致表膨胀。事务使用XID和命令ID跟踪可见性,快照隔离决定数据可见性。VACUUM清理死元组,但受事务地平线限制,长事务会阻止清理。子事务和HOT链影响清理效率,需定期维护以避免性能下降。
本文讨论了PostgreSQL中的VACUUM过程,包括堆扫描、索引清理和堆清理三个阶段。VACUUM通过清理死元组和更新可见性图来回收空间,提高数据库性能。文章还强调了VACUUM与VACUUM FULL的区别,后者用于压缩文件大小。
Codex 将本地日志写入 logs_2.sqlite,导致数据库膨胀超 1GB,且无公开的日志保留或大小限制配置。作者用 SQLite 触发器拦截 logs 表插入以阻止新日志写入,并给出 Windows 版本、恢复写入及 VACUUM 清理旧日志的方法。该方案只是临时止损,会削弱本地调试能力,长期仍需官方提供日志保留设置。
PostgreSQL的锁机制可能导致阻塞和死锁。文章讨论了五种常见的锁行为,包括ACCESS EXCLUSIVE锁的排队、外键约束引发的隐性死锁、唯一约束检查导致的死锁、自动清理的特殊行为以及VACUUM的隐藏ACCESS EXCLUSIVE阶段。建议通过设置锁超时和监控活动来减轻这些问题。
Autovacuum's most powerful tuning lever: the scale factor that determines when dead tuples trigger a vacuum. On large tables, the 20% default waits too long.
PostgreSQL 18 finally fixes the autovacuum formula that left billion-row tables waiting for 200M dead tuples.
PostgreSQL 13 added insert-triggered autovacuum to solve a critical problem: append-only tables never vacuumed, breaking index-only scans and delaying tuple…
Three autovacuum parameters control how often PostgreSQL vacuums, how hard it works, and how long it pauses.
PostgreSQL的多版本并发控制(MVCC)允许读者和写者并行操作而不互相阻塞。每个元组包含两个事务ID(t_xmin和t_xmax),用于确定可见性。更新操作创建新版本并标记旧版本,VACUUM负责清理无效元组,但长时间运行的事务可能会阻止清理,导致空间浪费。不同的隔离级别影响快照的捕获时机,从而影响查询结果。
PostgreSQL中的表膨胀是由于UPDATE或DELETE操作产生的“死元组”未被VACUUM回收,导致数据文件增大。造成膨胀的原因包括长时间运行的事务、未提交的准备事务、启用hot_standby_feedback的备用服务器查询和逻辑复制延迟。解决方法是终止阻止VACUUM的事务或查询。
许多开发者误以为运行VACUUM可以保持PostgreSQL数据库健康,但VACUUM只能删除死元组,无法重组B树索引,导致索引膨胀。处理堆膨胀适合使用VACUUM,而索引膨胀则需手动使用REINDEX。应监控索引状态,及时处理膨胀问题。
PostgreSQL中的“数据库不接受命令”错误通常与事务ID环绕有关。解决方法包括处理旧的准备事务、结束长时间运行的事务、删除过期的复制槽,并执行VACUUM命令。避免使用单用户模式和VACUUM FULL,以减少停机时间,并确保自动清理配置正确,以防未来问题。
我从杜塞尔多夫机场出发前往pgday.at,因技术问题延误,但最终顺利抵达维也纳。在会议上,我意外成为演讲者,分享了现代PostgreSQL VACUUM的内容。活动精彩,结识了许多社区成员,最后在博物馆度过了愉快的早晨。
在PGConf.DE会议前,我参加了汉堡的Debian MiniDebConf,随后前往柏林。会议吸引了340名与会者,讨论了PostgreSQL的VACUUM演变、现代SSL和高可用性策略等主题,促进了社区交流。尽管回程遇到交通堵塞,但整体经历丰富而有意义。
I am (slowly) adding handy PostgreSQL queries to my GitHub, and Vacuum is the newest category. The end goal is to have a compilation of queries for those of us who need to keep an instance...
完成下面两步后,将自动完成登录并继续当前操作。