PG体系结构之物理结构
Tags: PG体系结构口令文件密码文件控制文件日志文件物理文件物理结构
PG内存结构请参考:https://www.xmmup.com/pgtixijiegouzhineicunjiegou.html
简介
- PostgreSQL由一系列数据库组成。
- 一套PostgreSQL程序称之为一个数据库群集。PG中的集群,也即database cluster,是由PostgreSQL服务端来管理的一组数据库(database)的集合。注意这里是数据库(database)的集合,不是数据库服务(database servers)的集合。一个PostgreSQL服务器运行在单个主机上,管理单个数据库集群。
- 当initdb命令执行初始化数据库后,template0 , template1,和postgres数据库被创建。
- template0和template1数据库是创建用户数据库时使用的模版数据库,他们包含系统元数据表。
- initdb()刚完成后,template0和template1数据库中的表是一样的。但是template1数据库可以根据用户需要创建对象。用户数据库是通过克隆template1数据库来创建的
- initdb()后马上创建pg_default和pg_global表空间
- 建表时如果没有指定特定的表空间,表默认被存在pg_default表空间中。
- 用于管理整个数据库集群的表默认被存储在pg_global表空间中。
- pg_default表空间的物理位置为$PGDATA\base目录。
- pg_global表空间的物理位置为$PGDATA\global目录。
- 一个表空间可以被多个数据库同时使用。此时,每一个数据库都会在表空间路径下创建为一个新的子路径。
- 创建一个用户表空间会在$PGDATA\pg_tblspc目录下面创建一个软连接,连接到表空间制定的目录位置。
- 在PG中,当应用连接到一个数据库时,一般只能访问这个数据库中的数据,而不能访问其他数据库中的数据(除非使用dblink等其他手段)
- 在PG中,表的术语称为“Relation”,而在其他数据库中叫“Table”
- 在PG中,行的术语为“Tuple”,而在其他数据库中叫“Row”
- 在PG中,服务端不支持汉字字符集GBK和GB18030
物理结构
实际上,pg的数据库集群本质上是一个目录。目录中包含一些子目录和很多的文件。在我们安装pg时,我们一般使用initdb的命令去初始化一个新的数据库集群。initdb 有个-D
参数,通过它来指定应该存储数据库集群的目录。而集群中的database对应$PGDATA/base目录下的一个文件夹,文件夹的名称即oid。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | lhrdb=# SELECT datname, oid FROM pg_database; datname | oid -----------+------- postgres | 12661 lhrdb | 16384 template1 | 1 template0 | 12660 repmgr | 16386 (5 rows) [root@lhrrepmgr64361 base]# ll total 28 drwx------ 2 pg13 pg13 4096 Apr 26 17:02 1 drwx------ 2 pg13 pg13 4096 Apr 26 17:02 12660 drwx------ 1 pg13 pg13 4096 Apr 29 11:10 12661 drwx------ 2 pg13 pg13 4096 Apr 28 19:04 16384 drwx------ 2 pg13 pg13 4096 Apr 28 18:52 16386 drwx------ 2 pg13 pg13 4096 Apr 28 17:36 pgsql_tmp [root@lhrrepmgr64361 base]# pwd /pg13/pgdata/base |
$PGDATA
目录下的文件和子目录的布局:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | [root@lhrrepmgr64361 pgdata]# ll total 156 drwx------ 1 pg13 pg13 4096 Apr 28 17:35 base -rw------- 1 pg13 pg13 33 Apr 29 00:00 current_logfiles drwx------ 1 pg13 pg13 4096 Apr 29 11:10 global drwx------ 2 pg13 pg13 4096 Apr 26 17:02 pg_commit_ts drwx------ 2 pg13 pg13 4096 Apr 26 17:02 pg_dynshmem -rw------- 1 pg13 pg13 455 Apr 28 17:29 pg_hba.conf -rw------- 1 pg13 pg13 1636 Apr 26 17:02 pg_ident.conf drwx------ 1 pg13 pg13 4096 Apr 29 00:00 pg_log drwx------ 1 pg13 pg13 4096 Apr 28 19:12 pg_logical drwx------ 1 pg13 pg13 4096 Apr 26 17:02 pg_multixact drwx------ 2 pg13 pg13 4096 Apr 26 17:02 pg_notify drwx------ 1 pg13 pg13 4096 Apr 28 17:36 pg_replslot drwx------ 2 pg13 pg13 4096 Apr 26 17:02 pg_serial drwx------ 2 pg13 pg13 4096 Apr 26 17:02 pg_snapshots drwx------ 1 pg13 pg13 4096 Apr 28 18:52 pg_stat drwx------ 1 pg13 pg13 4096 Apr 29 11:28 pg_stat_tmp drwx------ 1 pg13 pg13 4096 Apr 26 17:02 pg_subtrans drwx------ 2 pg13 pg13 4096 Apr 26 17:02 pg_tblspc drwx------ 2 pg13 pg13 4096 Apr 26 17:02 pg_twophase -rw------- 1 pg13 pg13 3 Apr 26 17:02 PG_VERSION drwx------ 1 pg13 pg13 4096 Apr 28 19:07 pg_wal drwx------ 1 pg13 pg13 4096 Apr 26 17:02 pg_xact -rw------- 1 pg13 pg13 201 Apr 28 18:52 postgresql.auto.conf -rw------- 1 pg13 pg13 28588 Apr 28 17:27 postgresql.conf -rw------- 1 pg13 pg13 44 Apr 28 18:52 postmaster.opts -rw------- 1 pg13 pg13 78 Apr 28 19:07 postmaster.pid |
物理文件或文件夹名 | 解释 |
---|---|
PG_VERSION | 包含PG大版本号的文件 |
postgresql.auto.conf | 用于存储由ALTER SYSTEM设置的配置参数 |
postmaster.opts | 记录服务器上次启动时使用的命令行参数的文件 |
postmaster.pid | 一个锁文件,记录当前postmaster进程的pid,cluster data目录路径,postmaster进程启动时的时间戳,端口号,Unix-domain socket目录路径,有效的listen_address(ip地址或者*,如果为空表示server不基于tcp),共享内存端id。 |
current_logfiles | 记录日志采集器当前写入的日志文件的文件 |
base | 包含每个数据库的子目录,为默认表空间 |
global | 包含集群范围表的子目录,作为共享系统表目录,例如pg_database |
pg_commit_ts | 包含事务提交时间戳数据的子目录 |
pg_dynshmem | 包含动态共享内存子系统使用的文件的子目录 |
pg_logical | 包含用于逻辑解码的状态数据的子目录 |
pg_multixact | 包含多事务状态数据的子目录(用于共享行锁) |
pg_notify | 包含监听/通知状态数据的子目录 |
pg_replslot | 包含复制槽位数据的子目录 |
pg_serial | 包含关于已提交的可序列化事务信息的子目录 |
pg_snapshots | 导出快照的子目录 |
pg_stat | 包含统计子系统永久文件的子目录 |
pg_stat_tmp | 包含统计子系统临时文件的子目录 |
pg_subtrans | 包含子事务状态数据的子目录 |
pg_tblspc | 包含到表空间的符号链接的子目录 |
pg_twophase | 包含已准备事务状态文件的子目录 |
pg_wal | 包含WAL (Write Ahead Log)文件的子目录 |
pg_xact | 包含事务提交状态数据的子目录 |
数据库包含的文件种类:
√数据库文件:位置在$PGDATA/base目录下,数据库对象,如:数据库、表,索引,序列等对象。
√控制文件:用来记录数据库集群的状态信息,如:版本信息、集群所管理的各种文件信息、检查点信息、事务状态信息等
√参数文件:位置在$PGDATA目录下
√日志文件:记录数据修改操作的日志,用于系统发生故障时进行数据恢复。
√临时文件:存放数据库进行计算的过程中,生成的各种中间对象,如排序运算的外存归并单元。
相关物理文件
postmaster.pid :这个文件存在于数据目录中是为了帮助pg_ctl判断服务器当前是否在运行。
控制文件
PostgreSQL 控制文件在$PGDATA/global目录下名为pg_control
PG控制文件pg_control里存储的数据是一个ControlFileData结构。控制文件尽量保持小于512个字节以使其适合一个典型的磁盘驱动的物理簇的大小。这会减少由于电源故障而写控制文件直接失败的可能性。但控制文件的物理大小是8K,远大于512个字节。这样做是为了控制文件格式变化时保持物理大小不变,如果正在读一个不兼容文件,以使ReadControlFile能传递一个合适的错误版本控制文件信息而代替一个读错误。系统里定义了和自己匹配的控制文件版本变量PG_CONTROL_VERSION,启动时会做系统和控制文件的匹配校验
pg_controldata命令可以显示出控制文件中内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | [root@lhrrepmgr64361 /]# su - pg13 Last login: Fri Apr 30 15:36:24 CST 2021 on pts/4 [pg13@lhrrepmgr64361 ~]$ cd $PGDATA [pg13@lhrrepmgr64361 pgdata]$ cd global/ [pg13@lhrrepmgr64361 global]$ ll pg_control -rw------- 1 pg13 pg13 8192 May 1 01:07 pg_control [pg13@lhrrepmgr64361 global]$ pg_controldata pg_control version number: 1300 Catalog version number: 202007201 Database system identifier: 6955389182321723814 Database cluster state: in production pg_control last modified: Sat 01 May 2021 01:07:41 AM CST Latest checkpoint location: 1/22A131E8 Latest checkpoint's REDO location: 1/22A131B0 Latest checkpoint's REDO WAL file: 0000000D0000000100000022 Latest checkpoint's TimeLineID: 13 Latest checkpoint's PrevTimeLineID: 13 Latest checkpoint's full_page_writes: on Latest checkpoint's NextXID: 0:47603 Latest checkpoint's NextOID: 16502 Latest checkpoint's NextMultiXactId: 1 Latest checkpoint's NextMultiOffset: 0 Latest checkpoint's oldestXID: 478 Latest checkpoint's oldestXID's DB: 1 Latest checkpoint's oldestActiveXID: 47603 Latest checkpoint's oldestMultiXid: 1 Latest checkpoint's oldestMulti's DB: 1 Latest checkpoint's oldestCommitTsXid:0 Latest checkpoint's newestCommitTsXid:0 Time of latest checkpoint: Sat 01 May 2021 01:07:41 AM CST Fake LSN counter for unlogged rels: 0/3E8 Minimum recovery ending location: 0/0 Min recovery ending loc's timeline: 0 Backup start location: 0/0 Backup end location: 0/0 End-of-backup record required: no wal_level setting: replica wal_log_hints setting: on max_connections setting: 100 max_worker_processes setting: 8 max_wal_senders setting: 10 max_prepared_xacts setting: 0 max_locks_per_xact setting: 64 track_commit_timestamp setting: off Maximum data alignment: 8 Database block size: 8192 Blocks per segment of large relation: 131072 WAL block size: 8192 Bytes per WAL segment: 16777216 Maximum length of identifiers: 64 Maximum columns in an index: 32 Maximum size of a TOAST chunk: 1996 Size of a large-object chunk: 2048 Date/time type storage: 64-bit integers Float8 argument passing: by value Data page checksum version: 0 Mock authentication nonce: f68708343514d8430e9188b5d44be0cd9c90ccbe7fb15a82427dfa8af2c6010e |
pg_control version number:控制文件的版本
Catalog version number:系统表版本号,PG9.4版本为201409291.PG版本由三个数字表示“X.Y.Z”,通常有重大功能变化X才会发生变化,Y变化通常指系统表发生了变化,Z变化系统表不会变化。若只是Z变化,通常只需要把二进制程序升级一个就可以,系统表没有变化,数据文件就是可以兼容
Maximum data alignment:数据结构最大的对齐值
Database block size:数据块的大小
Blocks per segment of large relation:在一些文件系统上,单个文件大小受限制,PG会把一个表的数据分到多个数据文件中存储,此值制定了每个数据文件最多多少个数据块,默认为131072个块,每个块8k,数据文件最大为1G
WAL block size:WAL日志块大小
Bytes per WAL segment:WAL日志块大小
Maximum length of identifiers:“name”类型的长度,实际上指一些数据库对象名称的最大长度,如表名、索引名的最大长度
Maximum columns in an index:一个索引最多多少列,目前为32个
Maximum size of a TOAST chunk:TOAST chunk的长度
Size of a large-object chunk:大对象的chunk大小
Date/time type storage:Date/time类型是用浮点数(double)类型表示还是由64bit的长整数表示,与不同类UNIX平台有关
Float4 argument passing:Float4类型的参数是传值还是传引用
Float8 argument passing:Float8类型的参数是传值还是传引用
Data page checksum version:数据块checksum的版本,如果为0,数据块没有使用checksum。运行initdb时加了-k参数,PG才会在数据块上启用checksum功能
Database system identifier:数据库的唯一标识串,这个标识串是一个64bit的整数,其中包含了创建数据库的时间戳和initdb时初始化的进程号,因此通常不会重复
Database cluster state:记录实例的状态,包括以下几个值:
- starting up:表示数据库正在启动状态,实际上目前没有使用此状态
- shut down:数据库实例(非Standby)正常关闭后控制文件中就是此状态
- shut down in recovery:Standby实例正常关闭后控制文件中就是此状态
- shutting down:正常停库时,先做checkpoint,开始做checkpoint时,会把状态设置为此状态,做完后把状态设置为shut down
- in crash recovery:数据库实例非异常停止后,重新启动后,会先进行实例的恢复,在实例恢复时的状态就是此状态
- in archive recovery:Standby实例正常启动后,就是此状态
- in production:数据库实例正常启动后就是此状态。Standby数据库正常启动后不是此状态
Latest checkpoint location:数据库异常停止后再重新启动时,需要做实例恢复,实例恢复的过程是从WAL日志中,找到最后一次的checkpoint点,然后读取这个点之后的WAL日志,重新应用这些日志,此过程称为数据库实例前滚,最后一次的checkpoint点的信息记录在“Latest checkpont”项中
Minimum recovery ending location:此值与Standby库应用WAL日志有关,需要注意的是主库与备库的控制文件中的checkpoint信息不同。在备库中,每replay一些WAL日志后,就会做一次checkpoint点,然后把这个checkpoint点的信息记录到控制文件中。当在备库replay一些日志,如果有一些脏数据刷新到磁盘中,会把产生脏数据的最新日志的位置记录到“Minimum recovery ending location”。为了能保证恢复到一个一致点。备库异常停机后,再启动,若备库提供只读服务或激活成主库,磁盘上的数据不一致,此时读备库会读到错误数据。因此replay日志要超过“Minimum recovery ending location”后,才能对外提供服务
Backup start location、Backup end location、End-of-backup record required
“Backup start location”与“Backup end location”记录了一个WAL日志的位置。在主库上做“SELECT pg_start_backup(‘tangxxxx’);”,只是在主库的数据目录下生成了一个backup_label文件,这时拷贝主库,拷贝出来的数据文件中就包括了backup_label文件,备库启动时,若发现有backup_label文件,会从这个文件中记录的点开始恢复,同时备库会把此位置记录到控制文件的“Backup start location”中,“Backup end location”与“End-of-backup record required”记录了备库恢复过程中的一些中间状态
日志文件
pg_log(数据库运行日志)
pg_log表示数据库运行日志,pg_log默认是关闭的,需要配置postgresql.con相关的参数启用此日志,默认路径$PGDATA/pg_log/;记录各种Error信息,定位慢查询SQL,数据库的启动关闭信息,发生checkpoint过于频繁等的告警信息。
1 2 3 4 5 6 | logging_collector = on log_directory = 'pg_log' log_filename = 'postgresql-%a.log' log_truncate_on_rotation = on select * from pg_settings where name in ('logging_collector','log_directory','log_filename','log_truncate_on_rotation'); |
pg_xlog
pg_xlog ( WAL日志,即重做日志)也就是一些事务日志信息(transaction log)。
- PostgreSQL在将缓存的数据刷入到磁盘之前,先写日志,这就是PostgreSQL WAL( Write-Ahead Log )方式,也就是预写日志方式
- 默认存放在$pgdata/pg_wal,单个文件大小是16M,内容一般不具有可读性,默认强制开启,无法关闭;
- 物理备份的时候需要备份此日志。
PostgreSQL提供WAL切换三种方式
- pg_switch_xlog()函数可以手工切换WAL日志
- WAL日志写满后触发归档
- 设置archive_timeout
pg_clog
pg_clog(事务提交日志,记录的是事务的元数据,pg_clog是pg_xlog的辅助日志),这个日志告诉我们哪些事务完成了,哪些没有完成。
- 一般位于:$PGDATA/pg_clog,这个日志文件一般非常小,但是重要性也是相当高,不得随意删除或者对其更改信息。
- 内容一般不具有可读性,默认强制开启,无法关闭﹔
- 物理备份的时候需要备份此日志。
口令文件(密码文件)
http://postgres.cn/docs/13/libpq-pgpass.html
一个用户主目录中的.pgpass
文件能够包含在连接需要时使用的口令(并且其他情况不会指定口令)。在微软的 Windows 上该文件被命名为%APPDATA%\postgresql\pgpass.conf
(其中%APPDATA%
指的是用户配置中的应用数据子目录)。另外,可以使用连接参数passfile或者环境变量PGPASSFILE
指定一个口令文件。
这个文件应该包含下列格式的行:
1 | hostname:port:database:username:password |
(你可以向该文件增加一个提醒:把上面的行复制到该文件并且在前面加上#
)。前四个域的每一个都可以是文字值或者匹配任何东西的*
。第一个匹配当前连接参数的行中的口令域将被使用(因此,在使用通配符时把更特殊的项放在前面)。如果一个条目需要包含:
或者\
,用\
对该字符转义。如果指定了host
连接参数,主机名字段会被匹配到host
,否则如果指定了hostaddr
参数则匹配到hostaddr
,如果两者都没有给出,则会搜索主机名localhost
。当连接是一个Unix域套接字连接并且host
参数匹配libpq的默认套接字目录路径时,也会搜索主机名localhost
。在一台后备服务器上,值为replication
的数据库字段匹配连接到主服务器的里复制连接。否则数据库字段的用途有限,因为用户对同一个集簇中的所有数据库都有相同的口令。
在 Unix 系统上,口令文件上的权限必须不允许所有人或组内访问,可以用chmod 0600 ~/.pgpass
这样的命令实现。如果权限没有这么严格,该文件将被忽略。在微软 Windows 上,该文件被假定存储在一个安全的目录中,因此不会进行特别的权限检查。
需要注意:
1、当密码包含冒号(:)时,必须用反斜杠(\:)进行转义
2、字符“*”可以匹配任何字段中的任何值(密码除外)
3、如果设置了环境变量PGPASSWORD,则不会读取~/.pgpass
文件
4、Windows 7 64位上带有空格的路径的示例PGPASSFILE值:
设置PGPASSFILE = C:\Program Files\someapp\pgpass.conf
5、请注意,环境变量值不得使用“(双引号)
6、关于权限:在 Unix 系统上,口令文件上的权限必须不允许所有人或组内访问,可以用chmod 0600 ~/.pgpass
这样的命令实现。如果权限没有这么严格,该文件将被忽略。在Windows上,该文件被假定存储在一个安全的目录中,因此不会进行特别的权限检查。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | -- 格式 hostname:port:database:username:password -- 示例 echo "*:*:*:*:1qaz@WSX" > ~/.pgpass chmod 600 ~/.pgpass cat >> ~/.pgpass <<"EOF" 172.72.6.30:5432:replication:repl:lhr 172.72.6.31:5432:replication:repl:lhr 172.72.6.32:5432:replication:repl:lhr 172.72.6.35:9999:postgres:pgpool:lhr 172.72.6.35:9999:postgres:postgres:lhr lhrpg30:5432:replication:repl:lhr lhrpg31:5432:replication:repl:lhr lhrpg32:5432:replication:repl:lhr lhrpg30:5432:postgres:postgres:lhr lhrpg31:5432:postgres:postgres:lhr lhrpg32:5432:postgres:postgres:lhr EOF -- 环境变量:PGPASSFILE [pg12@lhrpgcm1 ~]$ psql psql (12.9) Type "help" for help. postgres=# \q [pg12@lhrpgcm1 ~]$ mv .pgpass .pgpass_bk [pg12@lhrpgcm1 ~]$ psql Password for user postgres: [pg12@lhrpgcm1 ~]$ [pg12@lhrpgcm1 ~]$ PGPASSFILE=~/.pgpass_bk [pg12@lhrpgcm1 ~]$ psql Password for user postgres: [pg12@lhrpgcm1 ~]$ [pg12@lhrpgcm1 ~]$ export PGPASSFILE=~/.pgpass_bk [pg12@lhrpgcm1 ~]$ psql psql (12.9) Type "help" for help. postgres=# \q |