开发者学堂课程【PolarDB for PostgreSQL 开源人才初级认证培训课程:PolarDB 数据库结构】学习笔记(一),与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/1077/detail/15551
PolarDB 数据库结构
内容介绍:
一、数据库集群逻辑结构
二、数据库集群物理结构
三、表数据文件内部布局
四、访问表的读写方式
五、进程和内存结构
一、数据库集群逻辑结构
1、数据库集群逻辑结构
PolarDB 由众多数据库组成,称为是一个数据库集群。数据库集群有多个数据库,每个数据库下面存放各自的对象,对象包括表、索引、视图、存储过程、序列等等。登录到数据库以后可以用 /l 去查看当前所有的数据库信息。
PolarDB 提供两种 sql 语句,一种是标准的 sql 语句是 sql select,还有一种提供的叫 psql,也是 select ,起了一个别名,比如起了 l=要访问的后面很多的数据库,实际也是执行标准的 sql 语句,只是为了方便执行,所以起别名,psql l=select pg_database。/l 可以看当前所有数据库的信息。PolarDB 提供了很多类似的 psql 语句,可以用 /? 可以看里面所有 psql 的密令,可以根据不同的需求去选择,在不断的学习当中会学到各种各样的密令。
2、数据库对象标识
PolarDB 中的所有数据库对象都由各自的对象标识符( oid )在内部管理。
这些对象标识符是无符号的4字节整数。数据库对象和相应的 oid之间的关系存储在适当的系统目录中,具体取决于对象的类型。
数据库的 oid 和堆表的 oid 分别存储在 pg_database和pg_class中。
postgres=#select datnameoid
from pg_database;
datname | oid
-----------------+---------
postgres | 13887
Templatel | 1
template0 |13886
polardb_admin |13888
testdb |16384
sampledb | 32768
PolarDB 在管理对象的时候用 oid,oid 叫对象 ID,比如数据库可以通过 pg_database去查,通过#select datnameoid from pg_database; 可以查看每个数据库的对象 ID 号,对象 ID 号很重要,跟数据库物理结构的名字是一一对应的,pg_class 里面存放了所有表或者视图等等对象的名字和 ID。
比如现在连到 testdb 数据库,查一下当前数据库有哪些对象,借一个表就可以通过数据质点去访问。
postgres=# \c testdb
You are now connected to database "testdb" as user "postgres".
testdb-#
testdb=# id
Did not find any relations.
testdb-#
testdb-s
testdb=#
create table t1 ();
CREATE TABLE
testdb-#
testdb= select relname,oid from pg_class where re o1names'tl'
ERROR: column "reolname" does not exist
LINE 1: select relname,oid from pg_class where reolname='tl';
HINT: Perhaps you meant to reference the column "pg_class.relname".
testdb=#
testdb=# select relname,oid from pg_class where relname='tl'; relname| oid
---------+----
t1 |32772
(1 row)
Testdb=#
数据质点里面没有看到 oid 列,plogdb 下面的列是隐藏的列可以去访问,虽然没看到,但是可以去访问,每一个对象都有一个对象号。
数据库是以对象号来管理,名字只是为了让管理者用户访问的时候方便有意义。
二、数据库集群物理结构
1、数据库集群物理结构
PolarDB 物理结构是实际上面存放数据的位置,在进行数据库访问的时候,里面有一个变量叫做 PAGATA,这个变量指定了整个数据库一个基本的位置,在目录下会看到很多很多,比如配置文件,还有各种各样的目录。在目录下面注意 base 目录,所有数据库的数据目录都放在 base 目录下,base 目录下有很多子目录,这些子目录的名字都是以数字起名,数字实际上跟每个数据库的 OID 是对应上的。
Last ogin: sun Jul 17 22:31:26 2022 from 192.168.18.1
[postgres@pg-xc3 ~]$
[postgres@pg-xc3 ~]$
[postgres@pg-xc3 ~]$
[postgres@pg-xc3 ~]$
[postgres@pg-xc3 ~]$
[postgres@pg-xc3 ~]$ more .bash_profile
#.bash profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
.~/.bashrc
fi
# User specific environment and startup programs
PATH-$PATH:$HOME/.1ocal/bin:$HOME/bin export PATH
#export PG_HOME-/usr/1oca1/pg12.2/
#export PGDATA=/usr/1ocal/pg12.2/data
#export PGPORT=1922
#export PATH=$PATH:$PG_HOME/bin
export PG_HOME=/home/postgres/tmp_basedir_po1ardb_p g_1100_b1d
export PGDATA=/home/postgres/tmp_master_dir_polardb_p g_1100_b1d
export PGPORT=5432
export PATH=SPATH:SPG_HOME/bin
export pGuser=postgres
export PGHOST=127.0.0.1
export PGDATABASE=postgres
[postgres@pg-xc3cd~]/home/postgres/tmp_master_dir_polardb_pg_1100_b1d
[postgres@pg-xc3 ~]tmp_master_dir_polardb_pg_1100_bld
[postgres@pg-xc3 tmp_master_dir_polardb_pg_1100_bld]$
[postgres@pg-xc3 tmp_master_dir_polardb_pg_1100_b1d]s
- bash: 1: command not found
[postgres@pg-xc3 tmp_master_dir_polardb_pg_1100_b1d]$
比如现在找当前数据库的物理位置,首先看 pg_data 目录在哪里到路径下里面包含了很多数据库里面所需要的文件和目录,在目录下有base 目录。到目录下,下面有很多目录,这些目录的名字都是以数字命名。
上面这个数字跟刚才查到的 database 的 oid 是对应的,每个数据库都有一个 oid,pg_db 给数据库创建目录的时候,目录的名字跟 oid 一样。
13887 意味着 postgres 数据库的目录。物理结构,物理存放数据的一个地方。
2、数据库集群文件布局
(1)数据库集群的布局的主要文件和子目录如下所示:
files description
PG VERSION A file containing the major version number of Polardb
pg_hba.conf A file to control Polardb's client authentication
pg_ident.conf A file to control Polardb's user name mapping
postgresql.conf A file to set configuration parameters
postgresql.auto.conf A file used for storing configuration parameters that are set in ALTER SYSTEM (version
9.4 or later)
postmaster.opts A file recording the command line options the server was last started with
在 pg_data 目录下, pg_data 目录非常重要,是一个数据库数据的一个 home。在目录下面有各种各样的目录,不同的目录和文件有不同的作用。比如 pg_hba.conf 文件里面控制的是实例的访问权限,可以在文件里面定义哪一些主机可以访问哪一些数据库。postgresql.conf 是 pg_db 数据库的主要参数文件,postgresql.auto.conf 是二进制的参数文件,两个可以结合着用,然后 pg_db 在启动的时候先读 postgresql.conf 文件,然后再读postgresql.auto.conf 文件。
(2)数据库集群的布局的主要文件和子目录如下所示:
subdirectories description
base/ Subdirectory containing per-database subdirectories
global/ Subdirectory containing cluster-wide tables, such as pg database and Pg_control.
pg commit ts/ Subdirectory containing transaction commit timestamp data.Version 9.5 or later.
pg clog/ (Version 9.6 or earlier) Subdirectory containing transaction commit state data. It is renamed to pg xact in Version 10.
pg_dynshmem/ Subdirectory containing files used by the dynamic shared memory subsystem. Version 9.4 or later.
pg_logical/ Subdirectory containing status data for logical decoding.Version 9.4 or later.
pg_multixact/ Subdirectory containing multitransaction status data (used for shared row locks)
pg_notify/ Subdirectory containing LISTENTIFY status data
pg_repslot/ Subdirectory containing replication slot data.Version 9.4 or later.
pg_serial/ Subdirectory containing information about committed serializable transactions(version 9.1 or later)
pg_snapshots/ Subdirectory containing exported snapshots(version 9.2 or later)
不同的目录都有各自的一些作用,比如 base 目录还有其他的一些目录。
三、表数据文件内部布局
1、数据库布局
数据库目录与 oid 对应关系
数据库是 base 子目录下的子目录;数据库目录名与相应的 oid 相同。
例如,当数据库 sampledb 的 OID 为 16384 时,其子目录名为16384。
$ cd $PGDATA
$ ls -ld base/16384
drwx- ----- 213 postgres postgres 7242 8 26 16:33 16384
数据库的布局,前面讲的是数据库目录和 ID 的关系。数据库是 base 目录下面的子目录,base 本身就是一个子目录,在这个目录下面这些子目录对应各个数据库目录。
2、表与索引对应的数据文件
(1)OID与对应的数据文件之间的关系
sampledb=# SELECT relname, oid, relfilenode FROM pg class
WHERE relname = 'sampletbl'.
Relname | oid | relfilenode
------------+---------+------------
sampletbl | 18740 | 18740
(1 row)
初始化时 oid 与 relfilenode 一样,但是TRUNCATE、REINDEX、CLUSTER 等操作会造成 relfilenode 号的改变。
表放在哪个目录下要看表是放在哪一个数据库下,在不同的数据库下表的数据文件就放在这个数据库的目录下面,比如现在想查一下 =‘sampletbl’ 表所在的数据文件放在哪里,表的数据存放的地方叫做数据文件,一开始的时候表的 ID 与数据文件的名字是一致的。但是如果表做 TRUNCATE、REINDEX、CLUSTER 操作以后会不一致,没关系告诉初始化的时候是一致的就可以。
首先登录到 smpledb,然后查一下,当前有一个表的 oid 与数据文件,这就是数据文件的位置。具体的物理位置根据前面 sample tabledb 的数据库,oid 是 32768。
里面有 32768,就是 sample tabledb 的一个目录。
[postgresepa-xc3 base ]$
[postgres@pg-xc3 base ]$
[postgres@pg-xc3 base ]$ cd 32768/
[postgres@pg-xc3 32768]$
[postgres@pg-xc3 32768]$11 32769
1s: cannot access 32769: No such file or directory
[postgresepg-xc3 32768]$ 11
total144
-rw---- ---- 1 postgres postgres 144364 ju1 18 00:02 pg_internal.init
[postgres@pg-xc3 32768]$ pwd
/home/postgres/tmp_master_dir_polardb_pg_1100_b1d/base/32768
[postgres@pg-xc3 32768]$ Ts
pg_internal.init
[postgresepg-xc3 32768]$ 11 total 144
-rw------- 1 postgres postgres 144364 ]u1 18 00:02 pg_internal.init
[postgres@pg-xc3 32768]$
到目录下然后去找 32769 文件,是刚才表的一个路径。
postgres@pg-xc3 32768]$ pwd
home7postgres/tmp_master_dir_polardb_pg_1100_b1d/base/32768
[postgres@pg-xc3 32768]$
[postgres@pg-xc3 32768]$
[postgres@pg-xc3 32768]$
[postgresepg-xc3 32768 ]$
[postgres@pg-xc3 32768]$
[postgres@pg-xc3 32768]$ 11
total 144
-rw- ------ 1 postgres postgres 144364 Ju1 18 00:02 pg_internal.init
[postgres@pg-xc3 32768]$
Ipostgresepg-xc3 32768]$ pwd
home/postgres/tmp_master_dir_polardb_pg_1100_b1d/base/32768
[postgres@pg-xc3 32768]$
[postgres@pg-xc3 32768]$
[postgres@pg-xc3 32768]$
刚才在 pgdata 目录下面的 base 目录路径下去看表的数据文件在哪里,会发现里面只有一个文件,实际的数据不放在这个路径下,pgdb 把数据存放的位置进行分流。
真正的数据放在安装路基径下面 tmp_datadir 下面,在目录下相同的子目录下面可以看到要找到的表的文件
(2)使用函数查看表或者索引数据文件路径
查看表的文件路径:
sampledb=# SELECT pg_relation filepath('sampletbl');
-------------------------------------------------------------------
file-dio:///home/postares/tmp datadir polardb pa 1100 bld/base/32768/32769
文件尺寸超过1GB后,新文件的产生规则:
$ cd $PGDATA
$ 1s -la -h base/16384/19427*
-rw-------1 data/base/16384/19427
-rw------- 1 data/base/16384/19427.1
PolarDB 为了方便找到表数据文件的位置,提供了一个函数,可以调用函数去查看表所在的位置。可能会看到有 file-dio 是 PolarDB 专门弄的存储,共享存储。后面有一节课专门介绍 PolarDB 的方案共享存储,数据文件是放在共享存储下面的目录下。表的数据文件随着表的数据越来越多,它的数据文件可能会越来越多。产生一开始的时候如果数据文件是 1G,按照名字如果超过 1G,就会产生新的文件名字,文件的名字前面以数据文件的名字为前缀后面加上 .1,看到 .1 意味着表的数据文件超过了1G,这是它的命名规则。
3、表与索引对应的其它相关数据文件
数据文件、空闲空间地图和可见性地图('fsm’和'vm’)
$ cd $PGDATA
$ 1s -la base/16384/18751*
-rw------- 1 base/16384/18751
-rw------- 1 base/16384/18751 fsm
-rw------- 1 base/16384/18751 vm
它们也可以在内部称为每个关系的分岔( fork );空闲空间映射是表/索引数据文件的第一个分岔( fork 编号为 1),可见性映射是表数据文件的第二个分岔(fork编号为2)。数据文件的 fork 号为 0。
除了存放表数据的这些文件以外,同时还会看到一个 _fsm 和 _vm 两个文件,比如 _fsm 叫做 free space map 空闲可用空间地图。假如表有多个分配了多个数据块,将来如果往表插入数据的时候,每个数据块里面有可用的空间来存放新插入的数据的时候,PolarDB 会先查看一下 _fsm 文件从里面去找到哪一个数据块有可用的空间来存放数据,就是 _fsm 的作用。_vm 实际上是可见性地图,是将来对表空间进行整理,比方 vacuum 的时候要用到,_vm 的作用是为了协助 vacuum 在做空间整理的时候提高效率。比如数据文件它分为很多分岔,比如数据文件就是第一个分叉,第一个分叉就是一,然后第二个分叉。数据文件应该是分岔为零,第一是 _fsm 是1,然后 _vm 数据文件分岔是 2。
4、表空间
(1)表空间
PolarDB 中的表空间是基本目录之外的附加数据区域
PolarDB 也支持自荐表空间,比如现在想把表的数据放在一个可用的空间、可用的存储上面,可以创建一个新的表空间,新的表空间会在 PolarDB、PGDATA 目录下有 pg table space,在这个目录下面会有跟表空间名字一样的目录,实际上面是一个指针叫做软链接,软链接会知道创建表空间时候的物理位置。然后数据最后是放在 /home/postgres/tbispc 上面。如果是社区版PolarDB 表空间的功能是不支持的,如果是企业版支持。
(2)续
表空间目录由 pg_tblspc 子目录中的软链接寻址,链接名与表空间的 OID 值相同。
postgres=#select oid,spcname from pg tablespace;
oid | spcname
------+-----------
1663 | pg_default
1664 | pg_global
90208| new_tblspc
(3rows)
$Is-$PGDATA/pgtblspc/
total 0
Irwxrwxrwx. 1 postgres postgres90208->/home/postgres/tb lspo
在 PolarDB 下面默认有两个可用的表空间,一个是 pg_global,还有一个是pg_global,默认的情况下用的表工具是 pg_default 。
5、表数据文件布局
表数据文件内部布局
固定长度的页(或块),默认值为8192字节(8kb)
页面的内部布局取决于数据文件类型
PG 数据库下面表的数据文件布局。比如有一张表分配了这么多的数据块,table file 是一个数据文件,数据文件也分配了很多块,为了方便找到这些块,每个块会给一个 ID 从零开始,比如每个块里面尺寸默认是 8K。数据块的结构根据存放的内容分为是前面,上面叫块头,块头上面放了很多一些控制性的信息,比如常见的叫函指针,数据放在块的哪个位置有个函指针,去找函的时候就很快,快的使用是如果存放数据的时候是从下往上增长,像把水放到瓶子里面是从下往上增长,文件头的信息,快头的信息是从上往下长,中间区域是可用的空间,如果数据越来越多,中间剩下的应该就是空闲空间,这是存放数据的一种方式。