58.1. 数据库文件布局

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

传统上,数据库集群所需要的配置和数据文件都存储在集群的数据目录里, 通常用环境变量PGDATA来引用。(用于定义它的环境变量名称之后) PGDATA的一个常见位值/var/lib/pgsql/data。 不同服务器实例管理的多个集群, 可以在同一台机器上共存。

PGDATA目录包含一些子目录和控制文件,在Table 58-1中显示。 除了这些必要的东西外,集群配置文件postgresql.confpg_hba.confpg_ident.conf通常都存储在PGDATA这里。 (尽管PostgreSQL 8.0和之后版本中,有可能把它们放在其他地方)。

Table 58-1. PGDATA内容

描述
PG_VERSION 一个包含PostgreSQL主版本号的文件
base 包含与每个数据库对应的子目录的子目录
global 包含集群范围的表的子目录,比如pg_database
pg_clog 包含事务提交状态数据的子目录
pg_multixact 包含多重事务状态数据的子目录(使用共享的行锁)
pg_notify 包含LISTEN/NOTIFY状态数据的子目录
pg_serial 包含已提交可串行化事务信息的子目录
pg_snapshots 包含输出快照的子目录
pg_stat_tmp 包含临时文件的统计子系统的子目录
pg_subtrans 包含子事务状态数据的子目录
pg_tblspc 包含指向表空间的符号链接的子目录
pg_twophase 包含用于预备事务的状态文件的子目录
pg_xlog 包含WAL(预写日志)文件的子目录
postmaster.opts 一个记录服务器最后一次启动时使用的命令行参数的文件
postmaster.pid 一个锁文件, 记录着当前服务器主进程ID(PID),集群数据目录路径,服务器主起始时间戳,端口号, Unix-域套接目录路径(Windows上空),第一个有效listen_address(IP地址或者*, 如果不监听TCP,则为空),以及共享内存段ID, (在服务器关闭之后此文件就不存在了)。

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

每个表和索引都存储在独立的文件里,对于普通关系,这些文件 以该表或者该索引的filenode号命名, 该号码可以在pg_class.relfilenode中找到。 但是对于临时性关系,文件名称形式t``_BBB_`_FFF, 其中BBB是创建文件的后端ID,并且FFF是filenode号。 在任何情况下,除了主文件(a/k/a主叉文件), 每个表和索引有个_自由空间映射_(参阅[Section 58.3](#calibre_link-1512)), 其用来存储关于在关系中可用的自由空间的信息。 自用空间映射存储在文件名为filenode编号加上后缀fsm`的文件里。 表也有可见映射_,存储在一个分叉文件,后缀为_vm, 用来跟踪那些已知没有死行的页, 该可见映射在Section 58.4进一步的描述。 未记录的表和索引有三分之一分支,被称之为初始化分支,使用后缀_init 存储在分支中(参阅Section 58.5)。

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 58.2获取更多信息。

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

表空间把情况搞得更复杂些。 每个用户定义的表空间都在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 or _vm用来找到关联该关系的所有文件。

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