PgSQL 存储结构

xiaokeai Lv5

存储结构一般分为逻辑存储结构和物理存储结构。

逻辑存储结构通常指表、索引、视图、函数等逻辑对象

物理存储结构表示数据库在物理层面上是如何存储的,目前PostgreSQL数据库是运行在文件系统之上的

逻辑存储结构

逻辑对象是有层次关系的,数据库创建后,有一个叫数据库簇的概念,在数据库簇中可以创建很多数据库(使用create database创建),也就是说,数据库簇相当于是一个数据库的容器。

软件目录结构

二进制安装的PostgreSQL软件是在/usr/pgsql-(main_version是主版本号,如/usr/pgsql-12)下编译安装的,PostgreSQL软件通常安装在“/usr/local”目录下,当然也可以安装在其他目录下,其软件的目录结构如图7-4所示。

物理存储结构

般使用环境变量PGDATA指向数据目录的根目录。该目录是在安装时指定的,所以在安装时需要指定一个合适的目录作为数据目录的根目录,而且每一个数据库实例都需要一个根目录。目录的初使化是使用initdb来完成的,初始化完成后,数据根目录下就会生成以下6个配置文件。

·postgresql.conf:此数据库实例的主配置文件,基本上所有的配置参数都在此文件中。

·postgresql.auto.conf:使用ALTER SYSTEM修改的配置参数存储在该文件中(PostgreSQL 9.4及更高版本)。

·pg_hba.conf:认证配置文件,用于配置允许哪些IP的主机访问数据库、认证的方法是什么等信息。

·pg_ident.conf:ident认证方式的用户映射文件。

·PG_VERSION:存储PostgreSQL主版本号。

·postmaster.opts:记录服务器上次启动的命令行参数。

·此目录下还会生成如下子目录。

·base:默认表空间的目录。

·global:一些共享系统表的目录。

·log:程序日志目录,在查询一些系统错误时可查看此目录下的日志文件。在10版本之前此目录是“pg_log”。

·pg_commit_ts:视图提交的时间戳数据(PostgreSQL 9.5及更高版本)。

·pg_dynshmem:动态共享内存子系统使用的文件(PostgreSQL 9.4及更高版本)。

·pg_logical:逻辑复制的状态数据(PostgreSQL 9.4及更高版本)。

·pg_multixact:多事务状态数据。

·pg_notify:LISTEN/NOTIFY状态数据。

·pg_repslot:复制槽数据(PostgreSQL 9.4及更高版本)。

·pg_serial:已提交的可串行化事务相关信息(PostgreSQL 9.1及更高版本)。

·pg_snapshot:PostgreSQL函数“pg_export_snapshot”导出的快照信息文件(PostgreSQL 9.2及更高版本)。

·pg_stat:统计子系统的永久文件。

·pg_stat_tmp:统计子系统的永久文件。

·pg_subtrans:子事务状态数据。

·pg_tblsp:存储了指向各个用户自建表空间实际目录的链接文件。

·pg_twophase:使用两阶段提交功能时分布式事务的存储目录。

·pg_wal:WAL日志的目录,在PostgreSQL 10版本之前此目录是“pg_xlog”。

·pg_xact:Commit Log的目录,在PostgreSQL 10版本之前此目录是“pg_clog”。

在默认表空间的base目录下有很多子目录,这些子目录的名称与相应数据库的OID相同。

1
2
3
4
5
6
7
8
select oid, datname from pg_database;
oid | datname
-------+-----------
12937 | postgres
16384 | osdba
1 | template1
12936 | template0
(4 rows)

例如上面的内容中“osdba”数据库的oid为16384,则它对应的子目录名称就是16384。在16384目录下,存放着“osdba”这个数据库的表、索引等数据文件。

每个表或索引都会分配一个文件号relfilenode,数据文件格式则以“<relfilenode>[.顺序号]”命名,每个文件最大为1GB,当表或索引的内容大于1GB时,就会从1开始生成顺序号。所以一张表的数据文件的路径为:`

<默认表空间的目录>/<database oid> /<relfilenode>[.顺序号]

而一张表或索引的“relfilenode”是记录在系统表pg_class的relfilenode字段中的。如果要查询数据库“osdba”中表“test01”的数据文件,根据前面已经查出的数据库“osdba”的oid(为16384)来查,假设表“test01”是在默认表空间下的,那么查询这张表的relfilenode的命令如下:

1
2
3
4
5
osdba=# select relnamespace, relname, relfilenode from pg_class where relname='test01';
relnamespace | relname | relfilenode
--------------+---------+-------------
2200 | test01 | 33103
(1 row)

可以看出这个表的relfilenode为“33103”,则这张表的数据文件为“$PGDATA/base/16384/33103”:

表空间的目录

前面讲解了表的数据文件在默认表空间下是如何存储的。对于用户创建的表空间,相当于一个对应的目录,在创建完一个表空间后,会在表空间的根目录下生成带有“Catalog version”的子目录,示例如下:

1
CREATE TABLESPACE tbs01 LOCATION '/home/osdba/tbs01';

此时,在表空间的根目录下会生成一个子目录名“PG_12_201909212”:

子目录“PG_12_201909212”中的“12”代表大版本,而“201909212”就是“Catalog version”,“Catalog version”可以由pg_controldata命令查询出来:

1
2
osdba-mac:~ osdba$ pg_controldata |grep "Catalog version number"
Catalog version number: 201909212

在“PG_12_201909212”子目录下,又会有一些子目录,这些子目录的名称就是数据库的oid。

所以对于用户创建的表空间,表和索引存储数据文件的目录名为:

1
<表空间的根目录>/< Catalog version 目录>/<database oid> /<relfilenode>[.顺序号]