54.1. 数据库文件布局

本节在文件和目录的层次上描述存储格式。

数据库集群所需要的所有数据都存储在集群的数据目录里,通常用环境变量 PGDATA来引用。PGDATA的一个常见位值 /var/lib/pgsql/data。不同服务器实例管理的多个集群, 可以在同一台机器上共存。

PGDATA目录包含几个子目录以及一些控制文件, 在Table 54-1里面显示。除了这些必要的东西之外, 集群的配置文件postgresql.conf, pg_hba.conf, pg_ident.conf通常也都存储在这里。 (PostgreSQL8.0 之后也可以把它们放在别的地方)

Table 54-1. PGDATA的内容

Item描述
PG_VERSION一个包含PostgreSQL主版本号的文件
base包含与每个数据库对应的子目录的子目录
global包含集群范围的表的子目录,比如 pg_database
pg_clog包含事务提交状态数据的子目录
pg_multixact包含多重事务状态数据的子目录(使用共享的行锁)
pg_notify包含 LISTEN/NOTIFY 状态数据的子目录
pg_stat_tmp 包含临时文件的统计子系统的子目录
pg_subtrans包含子事务状态数据的子目录
pg_tblspc包含指向表空间的符号链接的子目录
pg_twophase包含用于预备事务的状态文件的子目录
pg_xlog包含 WAL(预写日志)文件的子目录
postmaster.opts一个记录服务器最后一次启动时使用的命令行参数的文件
postmaster.pid一个锁文件,记录着当前的服务器主进程 PID 和共享内存段 ID ,在服务器关闭之后此文件就不存在了。

对于集群里的每个数据库,在PGDATA/base 里都有对应的一个子目录,子目录的名字是该数据库在pg_database 里的 OID 。这个子目录是该数据库文件的缺省位置;特别值得一提的是, 该数据库的系统表存储在此。

每个表和索引都存储在独立的文件里,以该表或者该索引的filenode 号命名,该号码可以在pg_class.relfilenode找到。 另外,主文件(a/k/a 主叉文件),每个表和索引有个自由空间映射(参阅 Section 54.3), 其用来存储关于在关系中可用的自由空间的信息。自用空间映射存储在文件名为filenode编号加上后缀 _fsm的文件里。 表也有可见映射,存储在一个分叉文件,后缀为_vm,用来跟踪那些页,有活动的行。该可见映射在Section 54.4进一步的描述。

Caution

请注意,虽然一个表的 filenode 通常和它的 OID 相同,但实际上并必须如此; 有些操作,比如TRUNCATE, REINDEX, CLUSTER 以及一些特殊的ALTER TABLE形式,都可以改变 filenode 而同时保留 OID 。 避免假定filenode 和表 OID 相同。 还有,对于某种系统表包括pg_class自身,pg_class.relfilenode 包含零。这些表的实际的filenode编号存储在 低级别的数据结构,并且可以使用pg_relation_filenode()函数获取。

在表或者索引超过 1 GB 之后,将分割成 1GB 大小的段。第一个段的文件名 和 filenode 相同;随后的段名名为 filenode.1, filenode.2 ... 等等。 这样的安排避免了在某些平台上的有文件大小限制的问题。

(实际上,1GB 只是缺省的段大小。当构建PostgreSQL时,可以使用配置选项--with-segsize调整段大小。)
原则上,自由空间映射和可见映射叉文件可能需要多个段,尽管这在实践中不可能发生。

一个表如果有些字段里面可能存储相当大的数据,那么就会有个相关联的TOAST
表,用于存储无法在表的数据行中放置的超大行外数据。如果有的话,
pg_class.reltoastrelid从一个表链接到它
的TOAST表。参阅Section 54.2获取更多信息。

表的内容和索引在Section 54.5中有讨论。

表空间把情况搞得更复杂些。每个用户定义的表空间都在PGDATA/pg_tblspc
目录里面有一个符号连接,它指向物理的表空间目录(就是在CREATE TABLESPACE
命令里声明的那个目录)。这个符号连接是用表空间的 OID 命名的。
在物理的表空间目录内部,有个依赖PostgreSQL服务器版本的命名的子目录,如 PG_9.0_201008051。
(使用这个子目录的原因是为了让后续版本的数据库不产生冲突的情况下,可以使用相同的 CREATE TABLESPACE位置值。)
在有指定版本的子目录里,每个在表空间中有元素的数据库有个子目录,命名为数据库的OID。表和索引存储在那个目录,使用filenode命名方法。

pg_default没有通过pg_tblspc关联,
但是对应PGDATA/base。类似的还有,
pg_global没有通过pg_tblspc关联,
而是对应PGDATA/global。

pg_relation_filepath()函数用于显示任何关系的全路径。(相对于PGDATA)
替代记住许多上述规则,它往往是有用的。但是请记住,这个函数只给了关系主分叉文件的第一部分的名称—
你可能还需要一段数字和/或 _fsm或_vm用来找到关联该关系的所有文件。

创建临时文件(对于操作如更多数据于可适合内存的排序)在PGDATA/base/pgsql_tmp,
或如果表空间不是指定的pg_default,在表空间目录下的pgsql_tmp 子目录。
临时文件的名表示为pgsql_tmpPPP.NNN,这里PPP是后台拥有的PID和
NNN是后台来区分不同的临时文件。