逻辑结构
数据库集群(Database Cluster)是由单个PostgreSQL服务器管理的数据库集合。PostgreSQL服务器运行在单个主机上,并管理单个数据库集群。
数据库(Database)是数据库对象的集合。在关系数据库理论中,数据库对象是用来存储或引用数据的数据结构。堆表就是一个典型的例子,还有很多类似于索引(index)、序列(sequence)、视图(view)、函数(function)等。在PostgreSQL中,数据库本身也是数据库对象,并且在逻辑上彼此分离。所有其他数据库对象(例如表、索引等)都属于它们各自的数据库,虽然它们隶属于同一个数据库集群,但无法直接从集群中的一个数据库访问该集群中的另一个数据库中的对象。
PostgreSQL中的所有数据库对象都由各自的对象标识符(OID)进行内部管理,这些标识符是无符号的4字节整数。根据对象的类型,数据库对象和相应的OID之间的关系存储在适当的系统编目中。例如,数据库和堆表的OID分别存储在pg_database和pg_class中。
testdb=# create table student(no int, name varchar(20));
CREATE TABLE
testdb=# select relname, oid from pg_class where relname = 'student';
relname | oid
---------+-------
student | 16401
(1 row)
testdb=# select relname, oid, relfilenode from pg_class where relname = 'student';
relname | oid | relfilenode
---------+-------+-------------
student | 16401 | 16401
(1 row)
testdb=# select datname, oid from pg_database where datname = 'testdb';
datname | oid
---------+-------
testdb | 16384
(1 row)
testdb=# select pg_relation_filepath('student');
pg_relation_filepath
----------------------
base/16384/16401
(1 row)
物理结构
数据库的文件默认保存在initdb时创建的数据目录中,通常将数据目录路径配置为环境变量$PGDATA。初始化完成后,会再这个目录生成相关的子目录以及一些文件。在Postgresql中,tablespace的概念并不同于其他关系型数据库,一个tablespace对应一个目录。
数据目录结构
文件 | 描述 |
---|---|
PG_VERSION | PostgreSQL主版本号文件 |
pg_hba.conf | 客户端认证控制文件 |
pg_ident.conf | 用户名映射控制文件 |
postgresql.conf | 配置参数文件 |
postgresql.auto.conf | 用于存储在ALTER SYSTEM (9.4 及以上版本) |
postmaster.opts | 记录服务端上一次启动的命令行选项 |
目录 | 描述 |
base/ | 包含每个数据库对应的子目录的子目录 |
global/ | 包含集群范围的表的子目录,例如pg_database和pg_control |
pg_commit_ts/ | 包含事务提交时间戳数据的子目录 |
pg_clog/ (Version 9.6 or earlier) | 包含事务提交状态数据的子目录,10.0及以上版本中重命名为pg_xact |
pg_dynshmem/ | 包含被动态共享内存子系统所使用文件的子目录,9.4版本及以上 |
pg_logical/ | 包含用于逻辑复制的状态数据的子目录,9.4版本及以上 |
pg_multixact/ | 包含多事务状态数据的子目录(用于共享行锁) |
pg_notify/ | 包含LISTEN/NOTIFY状态数据的子目录 |
pg_repslot/ | 包含复制槽数据的子目录,9.4版本及以上 |
pg_serial/ | 包含已提交的可序列化事务信息的子目录,9.1版本及以上 |
pg_snapshots/ | 包含导出快照的子目录(9.2版本以后)。 PostgreSQL的函数pg_export_snapshot在此子目录中创建快照信息文件 |
pg_stat/ | 包含统计子系统永久文件的子目录 |
pg_stat_tmp/ | 包含统计子系统临时文件的子目录 |
pg_subtrans/ | 包含子事物状态数据的子目录 |
pg_tblspc/ | 包含指向表空间的符号链接的子目录 |
pg_twophase/ | 包含预备事务状态文件的子目录 |
pg_wal/ (Version 10 or later)/ | 保存预写日志,在版本10中从pg_xlog重命名而来 |
pg_xact/ (Version 10 or later) | 包含事务提交状态数据的子目录,10.0及以上版本从pg_xact重命名而来 |
pg_xlog/ (Version 9.6 or earlier) | 保存预写日志,10.0及以上版本中重命名为pg_wal |
数据库文件布局
数据库是base目录下的子目录;数据库目录名与各自的oid相同。例如,当数据库testdb的OID为16384时,它的子目录名为16384。
[liyang@dhss206 ~]$ cd $PGDATA
[liyang@dhss206 data]$ ls -ld base/16384
drwx------ 2 liyang liyang 12288 Sep 29 10:03 base/16384
OID
在Postgresql中每个表或索引都用单个文件存储,新创建的表以表的OID命名,对于大小超出1GB的表数据文件,自动切分成多个文件来存储,切分出的文件用OID.<顺序号>来命名。作为数据库对象的表和索引由各个OID在内部管理,而这些数据文件由变量relfilenode管理。表和索引的relfilenode值基本相同,但并不总是匹配各自的oid。
testdb=# select relname, oid, relfilenode from pg_class where relname = 'student';
relname | oid | relfilenode
---------+-------+-------------
student | 16401 | 16401
(1 row)
[liyang@dhss206 data]$ ls -ld base/16384/16401
-rw------- 1 liyang liyang 8192 Sep 29 15:44 base/16384/16401
表空间
堆表文件的内部布局
在数据文件(堆表和索引,以及空闲空间映射和可见性映射)中,它被划分为固定长度的Page(或块),缺省值为8192字节(8 KB)。每个文件中的那些页都是从0开始按顺序编号的,这些编号称为块号。如果文件已经被填满,PostgreSQL会在文件末尾添加一个新的空页来增加文件大小。
页面的内部布局取决于数据文件类型。在本节中,表的布局被描述为以下章节中需要的信息。