Skip to content

体系结构与物理存储

PostgreSQL 使用多进程架构。一个主服务进程管理实例生命周期,通常每个客户端连接由独立 Backend Process 处理;后台辅助进程负责 WAL、检查点、清理、归档、复制和并行任务。


进程与内存

组成作用
Postmaster监听连接、派生子进程并管理实例生命周期
Backend Process处理一个客户端会话中的解析、优化、执行和事务
Checkpointer执行检查点并推进恢复起点
Background Writer提前写回部分脏页,平滑前台写入压力
WAL Writer将 WAL 缓冲区内容写入 WAL 文件
Autovacuum Launcher/Worker发现并处理需要 VACUUM、ANALYZE 的表
Archiver把完成的 WAL 段复制到归档目标
WAL Sender/Receiver在主库与备库之间传输 WAL

共享内存保存 Shared Buffers、WAL Buffers、锁和事务状态等跨进程数据。每个连接还可能消耗排序、哈希、维护操作等私有内存,因此内存上限不能只按单个参数判断,而要结合并发执行节点数量估算。


数据库集群与 PGDATA

一个 PostgreSQL 实例只管理一个 database cluster,对应一个数据目录。一个 cluster 可以包含多个 database;角色和部分系统目录是 cluster 级对象,Schema 和普通业务对象位于具体 database 中。

PGDATA 内容作用
base/各数据库默认表空间的数据目录,子目录名使用数据库 OID
global/cluster 级系统表
pg_wal/WAL 段文件
pg_xact/事务提交状态
pg_multixact/多事务与共享行锁状态
pg_tblspc/指向用户表空间目录的符号链接
pg_replslot/复制槽的持久化状态
postgresql.auto.confALTER SYSTEM 写入的参数
postmaster.pid运行实例的进程和数据目录等信息,正常停止后不存在

配置文件传统上位于 PGDATA,也可以放在其他位置。WAL 只记录数据库管理的变化,不会自动保护操作系统级配置文件、证书和外部脚本。


Relation、文件与 Fork

堆表和索引通常各自对应物理文件。文件名使用 Relation 的 filenode,而不是表名;较大的 Relation 会被拆成多个固定大小的文件段,避免依赖文件系统对超大单文件的支持。

同一个 Relation 可以包含多个 Fork:

Fork文件形式内容
Mainfilenode表或索引的主要数据页
Free Space Map_fsm各页可用空间的摘要,帮助插入寻找目标页
Visibility Map_vm堆页是否 all-visible、all-frozen;索引没有 VM
Initialization Fork_initUnlogged Relation 崩溃后重建所需的初始内容

表、索引、TOAST 表是独立 Relation。删除或重写对象可能改变 filenode,因此不能把文件名当作长期稳定的对象标识。


页、行与 TOAST

数据文件由固定大小的数据页组成,常见构建的页大小是 8 KiB。页头记录校验、WAL 位置和空闲空间边界,行指针指向页内 Tuple。更新行时通常写入新版本,旧版本保留到不再被任何快照需要并由 VACUUM 清理。

单行无法直接完整放入页时,TOAST 会根据列的存储策略进行压缩或移出主表,把大值拆成块保存在关联 TOAST 表中。TOAST 对应用透明,但会影响行宽估算、随机读取、更新放大和索引可用性。

text
Table Relation
├── Main Fork:Heap Page -> Line Pointer -> Tuple Version
├── FSM Fork:页空闲空间摘要
├── VM Fork:可见与冻结状态
└── TOAST Relation:被移出的变长大值

表空间边界

表空间用于把 Relation 放到 PGDATA 之外的文件系统位置。它可以做容量与 I/O 布局,但不是数据库内的独立故障域:表空间目录缺失会导致相关对象不可访问,物理备份也必须覆盖所有表空间。

表空间不等同于 Schema,也不能提供对象级资源隔离。把 WAL、数据和备份放在不同设备上可以改变性能与故障风险,但必须保证备份工具和恢复流程理解完整的文件布局。

参考资料