物理存储结构
本节在文件和目录的层次上描述存储格式。
在传统上,数据库实例所使用的配置和数据文件都被一起存储在实例的数据目录里,通常用PGDATA
来引用(用的是可以定义它的环境变量的名字)。PGDATA
的一个常见位置是/var/lib/pgsql/data
。由不同数据库实例所管理的多个实例可以在同一台机器上共存。
PGDATA
目录包含几个子目录以及一些控制文件,如 表 1 所示。除了这些必要的东西之外,实例的配置文件postgresql.conf
、pg_hba.conf
和pg_ident.conf
通常都存储在PGDATA
中,不过可以把它们放在别的地方。
表 1. PGDATA
的内容
项 | 描述 |
---|---|
PG_VERSION |
一个包含 PostgreSQL 主版本号的文件 |
base |
包含每个数据库对应的子目录的子目录 |
global |
包含实例范围的表的子目录,比如pg_database |
pg_dynshmem |
包含被动态共享内存子系统所使用的文件的子目录 |
pg_logical |
包含用于逻辑复制的状态数据的子目录 |
pg_notify |
包含 LISTEN/NOTIFY 状态数据的子目录 |
pg_replslot |
包含复制槽数据的子目录 |
pg_snapshots |
包含导出的快照的子目录 |
pg_stat |
包含用于统计子系统的永久文件的子目录 |
pg_tblspc |
包含表空间存储位置的配置文件的子目录 |
pg_tmp |
包含实例运行时的临时文件的子目录。里面包含: 子目录 caches 用于进程启动初始化元数据缓存信息的临时文件;子目录 stats 用于统计信息子系统的临时文件;文件 current_logfiles 记录当前被日志收集器写入的日志文件的文件 |
pg_wal |
包含 WAL 预写日志文件的子目录 |
postgresql.auto.conf |
一个用于存储由ALTER SYSTEM 设置的配置参数的文件 |
postmaster.opts |
一个记录服务器最后一次启动时使用的命令行参数的文件 |
postmaster.pid |
一个锁文件,记录着当前的 postmaster 进程ID(PID)、实例数据目录路径、postmaster 启动时间戳、端口号、Unix 域套接字目录路径(Windows 上为空)、第一个可用的 listen_address(IP地址或者* ,或者为空表示不在 TCP 上监听)以及共享内存段 ID(服务器关闭后该文件不存在) |
对于实例里的每个数据库,在PGDATA/base
里都有一个子目录对应,子目录的名字为该数据库在 pg_database
里的 OID。这个子目录是该数据库文件的缺省位置;特别值得一提的是,该数据库的系统表存储在此。
每个表和索引都存储在独立的文件里。对于普通关系,这些文件以表或索引的 filenode 号命名,它可以在pg_class.relfilenode
中找到。但是对于临时关系,文件名的形式为 tBBB_FFF,其中 BBB 是创建该文件的后台的后台 ID,FFF 是文件节点号。在每种情况下,在主文件(又叫主分支)之外,每个表和索引有一个空闲空间映射(见第 68.3 节),它存储关系中可用空闲空间的信息。空闲空间映射存储在一个文件中,该文件以节点号加上后缀_fsm
命名。不被日志记录的表和索引还有第二个分支,即初始化分支,它存储在后缀为_init
的分支中(见第 68.5 节)。
请注意,虽然一个表的文件节点通常和它的 OID 相匹配,但实际上并不必须如此;有些操作,比如TRUNCATE
、REINDEX
、CLUSTER
以及某些形式的ALTER TABLE
,都可以改变文件节点而同时保留 OID。我们不应该假设文件节点和表 OID 相同。此外,对于包含pg_class
本身在内的特定系统表,其pg_class.relfilenode
包含0。这些系统表的实际文件节点号被存储在一个底层数据结构中,并且可以使用pg_relation_filenode()
函数获取。
在表或者索引超过 1GB 之后,它就被划分成 1G 大小的段。第一个段的文件名和文件节点相同;随后的段被命名为 filenode.1、filenode.2 等等。这样的安排避免了在某些有文件大小限制的平台上的问题。原则上,空闲空间映射分支也可以要求多个段,但实际上这很少发生。
如果一个表的列中可能存储相当大的项,那么该表就会有个与之相关联的 TOAST 表,它用于存储无法保留在在表行中的域值的线外存储。如果表有 TOAST 表,该表的pg_class.reltoastrelid
链接到它的 TOAST 表。参阅第 68.2 节获取更多信息。
表和索引的内容在第 68.6 节中进一步讨论。
表空间的情况更复杂些。每个数据库都在PGDATA/pg_tblspc
目录里面有一个记录表空间信息的配置文件,它记录了物理的表空间存储位置(就是在CREATE TABLESPACE
命令里指定的那个位置)。这个配置文件是用数据库的 OID 加上后缀.tsm
命名的。在物理表空间目录中,每个在这个表空间目录里有数据的数据库都会有一个子目录,以数据库的 OID 命名。该目录里的表和索引遵循文件节点命名模式。
pg_relation_filepath()
函数显示任何关系的完整路径(相对于PGDATA
)。它可以作为记住上面这么多规则的替代方法。但是记住该函数只给出关系的主分支的第一个段的名称 — 你也许需要追加一个段号和/或_fsm
或者_init
来找到与该关系相关的所有文件。
临时文件(用于如排序不能放在内存中的数据等操作)被创建在PGDATA/base/pg_tmp
中,如果临时文件被指定在一个非pg_default
表空间中则它们会被创建在该表空间的pg_tmp
子目录中。临时文件的名称的形式为 pgtmp_PPP.NNN,其中 PPP 是其所属后端的 PID,而 NNN 用于区别该后端的不同临时文件。