9.3 9.4 9.5 9.6 10 11 12
阿里云PostgreSQL 问题报告 纠错本页面

59.1. 数据库文件布局

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

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

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

表 59-1. PGDATA内容

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

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

每个表和索引都存储在单独的文件中,对于普通关系,这些文件 以该表或者该索引的filenode值命名, 该值可以在pg_class.relfilenode中找到。 但对于临时关系,其以tBBB_FFF这样的形式作为文件名, 其中BBB是创建文件的后端ID,FFF是filenode值。 在任何情况下,除了主文件(a/k/a主分支文件), 每个表和索引有空闲空间映射(参阅第 59.3 节), 其用来存储关系中空闲空间的相关信息。 空闲空间映射存储在以filenode值加后缀_fsm命名的文件中。 表也有可见映射,存储在一个后缀为_vm的分支文件中, 用来跟踪那些没有无效元组的页, 该可见映射在第 59.4 节中进一步的描述。 不记录日志的表和索引有第三个分支,被称之为初始化分支,其存储在一个后缀为_init 的分支文件中(参阅第 59.5 节)。

小心

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

在表或者索引超过1GB之后,将被分割为1GB大小的。 第一个段的文件名和filenode相同; 随后的段名为filenode.1, filenode.2 ... 等等。 这样可以避免在某些平台上文件大小限制的问题。 (实际上,1GB只是缺省的段大小。当构建PostgreSQL时, 可以使用配置选项--with-segsize调整段大小。) 原则上,空闲空间映射和可见映射分支文件可能需要多个段, 尽管这在实践中不可能发生。

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

表和索引的内容在第 59.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_vm_init 后缀来找到与该关系相关的所有文件。

临时文件(对于一些操作,如对超过内存大小的数据进行排序)会被创建,其通常 在PGDATA/base/pgsql_tmp目录下,如果表空间不是pg_default, 则在表空间目录的pgsql_tmp子目录下。 临时文件名表示为pgsql_tmpPPP.NNN, 这里PPP是其后端进程的PID,NNN用以区分后端进程的不同临时文件。

<
/BODY >