暂无图片
暂无图片
7
暂无图片
暂无图片
暂无图片

PG体系结构

原创 福娃筱欢 恩墨学院 2023-09-02
463

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使用经典的C/S架构,进程架构。在服务器端有主进程、服务进程、子进程、共享内存以及文件存储几大部分。

1.1.物理结构

Database Cluster --》Tablespaces --》Files --》 Blocks
image.png

[postgres@localhost ~]$ psql
psql (14.5)
Type "help" for help.

postgres=# select datname,oid from pg_database;
  datname  |  oid  
-----------+-------
 postgres  | 13892
 template1 |     1
 template0 | 13891
 test      | 16385
(4 rows)

postgres=# \q
[postgres@localhost ~]$ cd $PGDATA/base && ls -l
total 48
drwx------. 2 postgres postgres 8192 Jun 12 23:01 1
drwx------. 2 postgres postgres 8192 Jun 12 23:01 13891
drwx------. 2 postgres postgres 8192 Aug 31 06:58 13892
drwx------. 2 postgres postgres 8192 Jul  5 21:12 16385

$PGDATA目录下的文件和子目录的布局

[postgres@localhost base]$ cd $PGDATA
[postgres@localhost data5785]$ ls -l
total 72
drwx------. 6 postgres postgres    54 Jun 12 23:05 base #包含每个数据库的子目录
-rw-------  1 postgres postgres    44 Aug 31 06:57 current_logfiles #记录日志采集器当前写入的日志文件的文件
drwx------. 2 postgres postgres  4096 Aug 31 06:58 global #包含集群范围表的子目录,例如pg_database
drwx------. 2 postgres postgres  4096 Aug 31 06:57 log
drwx------. 2 postgres postgres     6 Jun 12 23:01 pg_commit_ts #包含事务提交时间戳数据的子目录
drwx------. 2 postgres postgres     6 Jun 12 23:01 pg_dynshmem #包含动态共享内存子系统使用的文件的子目录
-rw-------. 1 postgres postgres  4857 Jun 12 23:03 pg_hba.conf
-rw-------. 1 postgres postgres  1636 Jun 12 23:01 pg_ident.conf
drwx------. 4 postgres postgres    68 Aug 31 06:57 pg_logical #包含用于逻辑解码的状态数据的子目录
drwx------. 4 postgres postgres    36 Jun 12 23:01 pg_multixact #包含多事务状态数据的子目录(用于共享行锁)
drwx------. 2 postgres postgres     6 Jun 12 23:01 pg_notify #包含监听/通知状态数据的子目录
drwx------. 2 postgres postgres     6 Jun 12 23:01 pg_replslot #包含复制槽位数据的子目录
drwx------. 2 postgres postgres     6 Jun 12 23:01 pg_serial #包含关于已提交的可序列化事务信息的子目录
drwx------. 2 postgres postgres     6 Jun 12 23:01 pg_snapshots #导出快照的子目录
drwx------. 2 postgres postgres     6 Jun 13 07:11 pg_stat #包含统计子系统永久文件的子目录
drwx------. 2 postgres postgres    63 Aug 31 06:59 pg_stat_tmp #包含统计子系统临时文件的子目录
drwx------. 2 postgres postgres    18 Jun 12 23:01 pg_subtrans
drwx------. 2 postgres postgres     6 Jun 12 23:01 pg_tblspc #包含到表空间的符号链接的子目录
drwx------. 2 postgres postgres     6 Jun 12 23:01 pg_twophase #包含已准备事务状态文件的子目录
-rw-------. 1 postgres postgres     3 Jun 12 23:01 PG_VERSION   #包含PG大版本号的文件
drwx------. 3 postgres postgres    92 Jun 13 08:49 pg_wal #包含WAL(Write Ahead Log)文件的子目录
drwx------. 2 postgres postgres    18 Jun 12 23:01 pg_xact #包含事务提交状态数据的子目录
-rw-------. 1 postgres postgres    88 Jun 12 23:01 postgresql.auto.conf #alter system设置的参数
-rw-------. 1 postgres postgres 28803 Jun 12 23:02 postgresql.conf
-rw-------. 1 postgres postgres    57 Aug 31 06:57 postmaster.opts #记录服务器上次启动时使用的命令行参数的文件
-rw-------  1 postgres postgres    76 Aug 31 06:57 postmaster.pid #一个锁文件,记录当前postmaster进程的pid,cluster data目录路径,
postmaster进程启动时的时间戳,端口号,Unix-domain socket目录listen_address(ip地址或者*如果为空表示server不基于tcp),共享内存端id。帮助
pg_ctl判断服务器当前是否在运行

数据文件种类:

  • 数据库文件:位置在$PGDATA/base目录下,数据库对象,如: 数据库、表,索引,序列等对象
  • 控制文件:用来记录数据库集群的状态信息,如:版本信息、集群所管理的各种文件信息、检查点信息、事务状态信息等
  • 参数文件:位置在$PGDATA目录下
  • 日志文件: 记录数据修改操作的日志,用于系统发生故障时进行数据恢复。
  • 临时文件:存放数据库进行计算的过程中,生成的各种中间对象,如排序运算的外存归并单元

1.1.1.数据库文件

位置在$PGDATA/base目录下,数据库对象,如: 数据库、表,索引,序列等对象。

global目录介绍

用于存储全局的系统表信息和全局控制信息。
global下有四种文件:

  1. pg_control
    用于存储全局控制信息
  2. pg_filenode.map
    用于将当前目录下系统表的OID与具体文件名进行硬编码映射(每个用户创建的数据库目录下也有同名文件)。
  3. pg_internal.init
    用于缓存系统表,加快系统表读取速度(每个用户创建的数据库目录下也有同名文件)。
  4. 全局系统表文件
    数字命名的文件,用于存储系统表的内容。它们在pg_class里的relfilenode都为0,是靠pg_filenode.map将OID与文件硬编码映射。(注:不是所有的系统表的relfilenode都为0)

base目录介绍

用于存放数据库的所有实体文件。例如,创建的第一个库testdb的OID为16384,那么在data/base下就会产生一个名为16384的目录,用于存储testdb的数据文件

testdb=# select oid,datname from pg_database;
  oid  |  datname
-------+-----------
 12407 | postgres
 16384 | testdb
     1 | template1
 12406 | template0
(4 rows)

base目录结构

data
├── base                  # use to store database file(SELECT oid, datname FROM pg_database;)
│   ├── 1                 # template database
│   ├── 12406             # template0 database
│   ├── 12407             # postgres database
│   └── 16384             # testdb, first user database
│   │   ├── 3600
│   │   ├── 3600_fsm
│   │   ├── 3600_vm
│   │   ├── 16385
│   │   ├── pg_filenode.map
│   │   ├── pg_internal.init
│   │   └── PG_VERSION
  1. pg_filenode.map 是pg_class里relfilenode为0的系统表,OID与文件的硬编码映射。
  2. pg_internal.init 是系统表的cache文件,用于加快读取。默认不存在,查询系统表后自动产生。
  3. PG_VERSION 是当前数据库数据格式对应的版本号
  4. 其它文件是需要到pg_class里根据OID查到对应的relfilenode来与文件名匹配的。
    例如:tab1的relfilenode是16385,那么16385这个文件就是tab1的数据文件
    testdb=# select oid,relfilenode,relname from pg_class where relname='tab1';
      oid  | relfilenode | relname
    -------+-------------+---------
     16385 |       16385 | tab1
    (1 row)
  1. 空闲空间映射表
    名字以_fsm结尾的文件是数据文件对应的FSM(free space map)文件,用map方式来标识哪些block是空闲的。用一个Byte而不是bit来标识一个block。对于一个有N个字节的block,它在_fsm文件中第blknum个字节中记录的值是(31+N)/32。通过这种方式标识一个block空闲字节数。FSM中不是简单的数组,而是一个三层的树形结构。FSM文件是在执行VACUUM操作时,或者是为了插入行而第一次查询FSM文件时才会创建。
  2. 可见性映射表文件
    名字以_vm结尾的文件是数据文件对应的VM(visibility map)。PostgreSQL中在做多版本并发控制时是通过在元组头上标识“已无效”来实现删除或更新的,最后通过VACUUM功能来清理无效数据回收空闲空间。在做VACUUM时就使用VM开快速查找包含无效元组的block。VM仅是个简单的bitmap,一个bit对应一个block。注意索引没有VM。

**注:**系统表分为全局系统表和库级系统表。
全局系统表位于global下,例如:pg_database,pg_tablespace,pg_auth_members这种存储系统级对象的表。
库级系统表位于数据库目录下,例如:pg_type,pg_proc,pg_attribute这种存储库级对象的表。
值得注意的是pg_class位于库级目录的里,但也包含全局系统表信息,因此研发或运维人员在改动全局系统表信息时需要注意。

表空间目录介绍

在DB2和Oracle数据库中;一个表空间只属于一个数据库使用;而一个数据库可以拥有多个表空间。属于"一对多"的关系。
在PostgreSQL集群中;一个表空间可以让多个数据库使用;而一个数据库可以使用多个表空间。属于"多对多"的关系。用户下面拥有表,拥有模式。模式下面拥有表空间。

创建表空间
--创建目录
mkdir -p /data/pg_tblspc
chown -R postgres:postgres /data/pg_tblspc
chmod -R 755 /data/pg_tblspc
--创建表空间
create tablespace dbspace location '/data/pg_tblspc';
--更改表到新的表空间
postgres=# select pg_relation_filepath('tab3');
 pg_relation_filepath 
----------------------
 base/13892/24591
(1 row)
postgres=# alter table tab3 set tablespace dbspace;
ALTER TABLE
postgres=# select pg_relation_filepath('tab3');
            pg_relation_filepath             
---------------------------------------------
 pg_tblspc/24585/PG_14_202107181/13892/24586
(1 row)

查询表空间

testdb=# \db
或
testdb=# select oid,* from pg_tablespace;
  oid  |  spcname   | spcowner | spcacl | spcoptions
-------+------------+----------+--------+------------
  1663 | pg_default |       10 |        |
  1664 | pg_global  |       10 |        |
 49162 | dbspace    |       10 |        |
(3 rows)

每一个Oid都在data/pg_tblspc下对应一个名为Oid的软链接文件,指向真正的space目录。

 tree ../data/pg_tblspc/
../data/pg_tblspc/
└── 49162 -> /data/pg_tblspc

在space目录是如何组织的呢?

testdb=# create table tab3(a int) tablespace dbspace;
CREATE TABLE

testdb=# select oid,relname,relfilenode from pg_class where relname='tab3';
  oid  | relname | relfilenode
-------+---------+-------------
 57351 | tab3    |       57351
(1 row)

 tree ../data/pg_tblspc/49162
../data/pg_tblspc/49162
└── PG_14_202107181
    └── 16384
        └── 57351

1.1.2.控制文件

PostgreSQL 控制文件在$PGDATA/global目录下名为pg_control
存储的数据是一个ControlFileData结构。保持小于512个字节以使其适合一个典型的磁盘驱动的物理簇的大小。这会减少由于电源故障而写控制文件直接失败的可能性。但控制文件的物理大小是8K,远大于512个字节。这样做是为了控制文件格式变化时保持物理大小不变,如果正在读一个不兼容文件,以使ReadControlFile能传递一个合适的错误版本控制文件信息而代替一个读错误。系统里定义了和自己匹配的控制文件版本变量PG_CONTROL_VERSION,启动时会做系统和控制文件的匹配校验
pg_controldata命令可以显示出控制文件中内容:

--控制文件位置
-bash-4.2$ cd /data/pgsql/pgdata/global/
-bash-4.2$ ls -l pg_control 
-rw-------. 1 postgres postgres 8192 Aug 11 20:09 pg_control

--控制文件内容
[postgres@localhost ~]$ pg_controldata
pg_control version number:            1300       #控制文件的版本
Catalog version number:               202107181   #系统表版本号,PG9.4版本为201409291.PG版本
由三个数字表示“X.Y.Z”,通常有重大功能变化X才会发生变化,Y变化通常指系统表发生了变化,Z变化系统表
不会变化。若只是Z变化,通常只需要把二进制程序升级一个就可以,系统表没有变化,数据文件就是可以兼容
Database system identifier:           7243814926055691141 
Database cluster state:               in production
pg_control last modified:             Wed 05 Jul 2023 09:12:09 PM CST
Latest checkpoint location:           0/7000148
Latest checkpoint's REDO location:    0/7000148
Latest checkpoint's REDO WAL file:    000000010000000000000007
Latest checkpoint's TimeLineID:       1
Latest checkpoint's PrevTimeLineID:   1
Latest checkpoint's full_page_writes: on
Latest checkpoint's NextXID:          0:751
Latest checkpoint's NextOID:          24585
Latest checkpoint's NextMultiXactId:  1
Latest checkpoint's NextMultiOffset:  0
Latest checkpoint's oldestXID:        727
Latest checkpoint's oldestXID's DB:   1
Latest checkpoint's oldestActiveXID:  0
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:            Wed 05 Jul 2023 09:12:09 PM 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:                off
max_connections setting:              500
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 #在一些文件系统上,单个文件大小受限制,PG会把一个
表的数据分到多个数据文件中存储,此值制定了每个数据文件最多多少个数据块,默认为131072个块,每个块
8k,数据文件最大为1G
WAL block size:                       8192  #WAL日志块大小
Bytes per WAL segment:                16777216  #WAL日志块大小
Maximum length of identifiers:        64  #name类型的长度,实际上指一些数据库对象名称的最大长
--控制文件位置
-bash-4.2$ cd /data/pgsql/pgdata/global/
-bash-4.2$ ls -l pg_control 
-rw-------. 1 postgres postgres 8192 Aug 11 20:09 pg_control


--控制文件内容
[postgres@localhost ~]$ pg_controldata
pg_control version number:            1300       #控制文件的版本
Catalog version number:               202107181   #系统表版本号,PG9.4版本为201409291.PG版本
由三个数字表示“X.Y.Z”,通常有重大功能变化X才会发生变化,Y变化通常指系统表发生了变化,Z变化系统表
不会变化。 若只是Z变化,通常只需要把二进制程序升级一个就可以,系统表没有变化,数据文件就是可以兼容
Database system identifier:           7243814926055691141  #数据库的唯一标识串,这个标识串
是一个64bit的整数,其中包含了创建数据库的时间戳和initdb时初始化的进程号,因此通常不会重复
Database cluster state:               in production  #记录实例的状态,包括以下几个值:
 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数据库正常启动后不是此状态

pg_control last modified:             Wed 05 Jul 2023 09:12:09 PM CST
Latest checkpoint location:           0/7000148 #数据库异常停止后再重新启动时,需要做实例恢
复,实例恢复的过程是从WAL日志中,找到最后一次的checkpoint点,然后读取这个点之后的WAL日志,重新
应用这些日志,此过程称为数据库实例前滚,最后一次的checkpoint点的信息记录在“Latest checkpont”项中
Latest checkpoint's REDO location:    0/7000148
Latest checkpoint's REDO WAL file:    000000010000000000000007
Latest checkpoint's TimeLineID:       1
Latest checkpoint's PrevTimeLineID:   1
Latest checkpoint's full_page_writes: on
Latest checkpoint's NextXID:          0:751
Latest checkpoint's NextOID:          24585
Latest checkpoint's NextMultiXactId:  1
Latest checkpoint's NextMultiOffset:  0
Latest checkpoint's oldestXID:        727
Latest checkpoint's oldestXID's DB:   1
Latest checkpoint's oldestActiveXID:  0
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:            Wed 05 Jul 2023 09:12:09 PM CST
Fake LSN counter for unlogged rels:   0/3E8
Minimum recovery ending location:     0/0 #此值与Standby库应用WAL日志有关,需要注意的是主库
与备库的控制文件中的checkpoint信息不同。在备库中,每replay一些WAL日志后,就会做一次
checkpoint点,然后把这个checkpoint点的信息记录到控制文件中。当在备库replay一些日志,如果有一些
脏数据刷新到磁盘中,会把产生脏数据的最新日志的位置记录到“Minimum recovery ending location”。
为了能保证恢复到一个一致点。备库异常停机后,再启动,若备库提供只读服务或激活成主库,磁盘上的数据
不一致,此时读备库会读到错误数据。因此replay日志要超过“Minimum recovery ending location”后,
才能对外提供服务
Min recovery ending loc's timeline:   0
Backup start location:                0/0
Backup end location:                  0/0
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”记录了备库恢复过程中的一些中间
状态。
End-of-backup record required:        no
wal_level setting:                    replica
wal_log_hints setting:                off
max_connections setting:              500
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 #在一些文件系统上,单个文件大小受限制,PG会把一个
表的数据分到多个数据文件中存储,此值制定了每个数据文件最多多少个数据块,默认为131072个块,每个块
8k,数据文件最大为1G
WAL block size:                       8192  #WAL日志块大小
Bytes per WAL segment:                16777216  #WAL日志块大小
Maximum length of identifiers:        64  #name类型的长度,实际上指一些数据库对象名称的最大长
度,如表名、索引名的最大长度
Maximum columns in an index:          32  #一个索引最多多少列,目前为32个
Maximum size of a TOAST chunk:        1996  #TOAST chunk的长度
Size of a large-object chunk:         2048   #大对象的chunk大小
Date/time type storage:               64-bit integers  #Date/time类型是用浮点数(double)
类型表示还是由64bit的长整数表示,与不同类UNIX平台有关
Float8 argument passing:              by value  #Float8类型的参数是传值还是传引用
Data page checksum version:           0  #数据块checksum的版本,如果为0,数据块没有使用
checksum。运行initdb时加了-k参数,PG才会在数据块上启用checksum功能
Mock authentication nonce:            ef4ded3954269af6d2d08db0e960b841f7a9e6599c8ac4c3e1dce9759fa79bcc
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:            ef4ded3954269af6d2d08db0e960b841f7a9e6599c8ac4c3e1dce9759fa79bcc

1.1.3.参数文件

位置:初始化安装的数据库目录下,例如:/pgdb/data/pg_hba.conf

pg_hba.conf 黑名单参数文件

相当于mysql数据库中的mysql.user表

连接方式      连接的数据库   连接的用户        连接的主机IP              认证方式
# TYPE        DATABASE        USER            ADDRESS                 METHOD
# 禁止超级用户从远程连接      
host all postgres 0.0.0.0/0 reject    
#允许所有来源,通过任意用户访问任意数据库   
host all all 0.0.0.0/0 md5  

通过视图查看pg_hba.conf里的内容
select * from pg_hba_file_rules;

postgresql.conf数据库参数文件

查看参数

cat /data/pgdb/data5785/postgresql.conf

--查看所有参数  show all 对应的函数是 current_setting(setting_name text)
postgres=# show all;
postgres=# select * from pg_catalog.pg_settings;
--查看具体参数
postgres=# show ssl;
 ssl 
-----
 off
(1 row)

postgres=# select current_setting('ssl');
 current_setting 
-----------------
 off
(1 row)
修改参数
  1. 手工修改postgresql.conf数据库参数文件
  2. 命令全局修改

alter system改变全局默认值,功效上等同于修改postgresql.conf
alter database命令允许针对一个数据库覆盖其全局设置.
alter role 命令允许用用户指定的值来覆盖全局设置和数据库设置.
只有当开始一个新的数据库会话时,用ALTER DATABASE和 ALTER ROLE设置的值才会被应用。它们会覆盖从配置文件或服务器命令行 获得的值,并且作为该会话后续的默认值.
3.命令临时修改
SET命令允许修改对于一个会话可以本地设置的参数的当前值, 它对其他会话没有影响。对应的函数是 set_config(setting_name, new_value, is_local);

参数生效
方式1. 发送 SIGHUP 信号给主服务进程;
方式2. 运行 pg_ctl reload 命令;
方式3. 调用函数 select pg_reload_conf();
关键参数修改
alter system set max_connections=1000;
alter system shared_buffers=2G;   1/4
alter system effective_cache_size=4MB;  1/2
alter system work_mem=30M;--内存排序
alter system maintenance_work_mem=2G; --清理和创建索引外键的速度。min( 8G, (主机内存*1/8)/max_parallel_maintenance_workers )
  • max_connections

允许的最大客户端连接数。这个参数设置大小和work_mem有一些关系。配置的越高,可能会占用系统更多的内存
。通常可以设置数百个连接,如果要使用上千个连接,建议配置连接池来减少开销。

  • work_mem

这个参数主要用于写入临时文件之前内部排序操作和散列表使用的内存量,增加work_mem参数将使PostgreSQL可以进行更大的内存排序。这个参数和max_connections有一些关系,假设你设置为30MB,则40个用户同时执行查询排序,很快就会使用1.2GB的实际内存。同时对于复杂查询,可能会运行多个排序和散列操作,例如涉及到8张表进行合并排序,此时就需要8倍的work_mem
示例:该环境使用4MB的work_mem,在执行排序操作的时候,使用的Sort Method是external merge Disk。

kms=> explain (analyze,buffers) select * from KMS_BUSINESS_HALL_TOTAL  order by buss_query_info;                                                                       QUERY PLAN                                                                        
---------------------------------------------------------------------------------------------------------------------------------------------------------
 Gather Merge  (cost=262167.99..567195.15 rows=2614336 width=52) (actual time=2782.203..5184.442 rows=3137204 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   Buffers: shared hit=68 read=25939, temp read=28863 written=28947
   ->  Sort  (cost=261167.97..264435.89 rows=1307168 width=52) (actual time=2760.566..3453.783 rows=1045735 loops=3)
         Sort Key: buss_query_info
         Sort Method: external merge  Disk: 50568kB
         Worker 0:  Sort Method: external merge  Disk: 50840kB
         Worker 1:  Sort Method: external merge  Disk: 49944kB
         Buffers: shared hit=68 read=25939, temp read=28863 written=28947
         ->  Parallel Seq Scan on kms_business_hall_total  (cost=0.00..39010.68 rows=1307168 width=52) (actual time=0.547..259.524 rows=1045735 loops=3)
               Buffers: shared read=25939
 Planning Time: 0.540 ms
 Execution Time: 5461.516 ms
(14 rows)

当把参数修改成512MB的时候,可以看到Sort Method变成了quicksort Memory,变成了内存排序。

kms=> set work_mem to "512MB";
SET
kms=> explain (analyze,buffers) select * from KMS_BUSINESS_HALL_TOTAL  order by buss_query_info;
                                                                QUERY PLAN                                                                
------------------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost=395831.79..403674.80 rows=3137204 width=52) (actual time=7870.826..8204.794 rows=3137204 loops=1)
   Sort Key: buss_query_info
   Sort Method: quicksort  Memory: 359833kB
   Buffers: shared hit=25939
   ->  Seq Scan on kms_business_hall_total  (cost=0.00..57311.04 rows=3137204 width=52) (actual time=0.019..373.067 rows=3137204 loops=1)
         Buffers: shared hit=25939
 Planning Time: 0.081 ms
 Execution Time: 8419.994 ms
(8 rows)
  • shared_buffers

PostgreSQL使用自己的缓冲区,也使用Linux操作系统内核缓冲OS Cache。这就说明数据两次存储在内存中,
首先是PostgreSQL缓冲区,然后是操作系统内核缓冲区。与其他数据库不同,PostgreSQL不提供直接IO,所以
这又被称为双缓冲。PostgreSQL缓冲区称为shared_buffer,建议设置为物理内存的1/4。而实际配置取决于硬
件配置和工作负载,如果你的内存很大,而你又想多缓冲一些数据到内存中,可以继续调大shared_buffer。
image.png

  • Effective_cache_size

这个参数主要用于Postgre查询优化器。是单个查询可用的磁盘高速缓存的有效大小的一个假设,是一个估算值,它并不占据系统内存。由于优化器需要进行估算成本,较高的值更有可能使用索引扫描,较低的值则有可能使用顺序扫描。一般这个值设置为内存的1/2是正常保守的设置,设置为内存的3/4是比较推荐的值。通过free命令查看操作系统的统计信息,您可能会更好的估算该值。

  • maintenance_work_mem

指定维护操作使用的最大内存量,例如(Vacuum、Create Index和Alter Table Add Foreign Key),默认值是64MB。由于通常正常运行的数据库中不会有大量并发的此类操作,可以设置的较大一些,提高清理和创建索引外键的速度。

postgres=# set maintenance_work_mem to "64MB";
SET
Time: 1.971 ms
postgres=# create index idx1_test on test(id);
CREATE INDEX
Time: 7483.621 ms (00:07.484)
postgres=# set maintenance_work_mem to "2GB";
SET
Time: 0.543 ms
postgres=# drop index idx1_test;
DROP INDEX
Time: 133.984 ms
postgres=# create index idx1_test on test(id);
CREATE INDEX
Time: 5661.018 ms (00:05.661)

可以看到在使用默认的64MB创建索引,速度为7.4秒,而设置为2GB后,创建速度是5.6秒

  • wal_sync_method

每次发生事务后,PostgreSQL会强制将提交写到WAL日志的方式。可以使用pg_test_fsync命令在你的操作系统上进行测试,fdatasync是pg在Linux上的默认方法。如下所示,我的环境测试下来fdatasync还是速度可以的。不支持的方法像fsync_writethrough直接显示n/a。

postgres=# show wal_sync_method ;
 wal_sync_method 
-----------------
 fdatasync
(1 row)

[pg@e22 ~]$ pg_test_fsync -s 3
3 seconds per test
O_DIRECT supported on this platform for open_datasync and open_sync.

Compare file sync methods using one 8kB write:
(in wal_sync_method preference order, except fdatasync is Linux's default)
        open_datasync                      4782.871 ops/sec     209 usecs/op
        fdatasync                          4935.556 ops/sec     203 usecs/op
        fsync                              3781.254 ops/sec     264 usecs/op
        fsync_writethrough                              n/a
        open_sync                          3850.219 ops/sec     260 usecs/op

Compare file sync methods using two 8kB writes:
(in wal_sync_method preference order, except fdatasync is Linux's default)
        open_datasync                      2469.646 ops/sec     405 usecs/op
        fdatasync                          4412.266 ops/sec     227 usecs/op
        fsync                              3432.794 ops/sec     291 usecs/op
        fsync_writethrough                              n/a
        open_sync                          1929.221 ops/sec     518 usecs/op

Compare open_sync with different write sizes:
(This is designed to compare the cost of writing 16kB in different write
open_sync sizes.)
         1 * 16kB open_sync write          3159.780 ops/sec     316 usecs/op
         2 *  8kB open_sync writes         1944.723 ops/sec     514 usecs/op
         4 *  4kB open_sync writes          993.173 ops/sec    1007 usecs/op
         8 *  2kB open_sync writes          493.396 ops/sec    2027 usecs/op
        16 *  1kB open_sync writes          249.762 ops/sec    4004 usecs/op

Test if fsync on non-write file descriptor is honored:
(If the times are similar, fsync() can sync data written on a different
descriptor.)
        write, fsync, close                3719.973 ops/sec     269 usecs/op
        write, close, fsync                3651.820 ops/sec     274 usecs/op

Non-sync'ed 8kB writes:
        write                            400577.329 ops/sec       2 usecs/op
  • wal_buffers

事务日志缓冲区的大小,PostgreSQL将WAL记录写入缓冲区,然后再将缓冲区刷新到磁盘。在PostgreSQL 12版中,默认值为-1,也就是选择等于shared_buffers的1/32 。如果自动的选择太大或太小可以手工设置该值。一般考虑设置为16MB。

  • synchronous_commit

客户端执行提交,并且等待WAL写入磁盘之后,然后再将成功状态返回给客户端。可以设置为on,remote_apply,remote_write,local,off等值。默认设置为on。如果设置为off,会关闭sync_commit,客户端提交之后就立马返回,不用等记录刷新到磁盘。此时如果PostgreSQL实例崩溃,则最后几个异步提交将会丢失。

  • default_statistics_target

PostgreSQL使用统计信息来生成执行计划。统计信息可以通过手动Analyze命令或者是autovacuum进程启动的自动分析来收集,default_statistics_target参数指定在收集和记录这些统计信息时的详细程度。默认值为100对于大多数工作负载是比较合理的,对于非常简单的查询,较小的值可能会有用,而对于复杂的查询(尤其是针对大型表的查询),较大的值可能会更好。为了不要一刀切,可以使用ALTER TABLE … ALTER COLUMN … SET STATISTICS覆盖特定表列的默认收集统计信息的详细程度。

  • checkpoint_timeout、max_wal_size,min_wal_size、checkpoint_completion_target

了解这两个参数以前,首先我们来看一下,触发检查点的几个操作。
(1)直接执行checkpoint命令
(2)执行需要检查点的命令(例如pg_start_backup,Create database,pg_ctl stop/start等等)
(3)自上一个检查点以来,达到了已经配置的时间量(checkpoint_timeout )
(4)自上一个检查点以来生成的WAL数量(max_wal_size)
使用默认值,
checkpoint_timeout=5min --检查点每5分钟触发一次。
max_wal_size --自动检查点之间增长的最大预写日志记录(WAL)量。默认是1GB,如果超过了1GB,则会发生检查点。这是一个软限制。在一个特殊的情况下,比如系统遭遇到短时间的高负载,日志产生几秒种就可以达到1GB,这个速度已经明显超过了checkpoint_timeout ,pg_wal目录的大小会急剧增加。此时可以从日志中看到相关类似的警告。

LOG:  checkpoints are occurring too frequently (9 seconds apart)
HINT:  Consider increasing the configuration parameter "max_wal_size".
LOG:  checkpoints are occurring too frequently (2 seconds apart)
HINT:  Consider increasing the configuration parameter "max_wal_size".

所以要合理配置max_wal_size,以避免频繁的进行检查点。一般推荐设置为16GB以上,不过具体设置多大还需要和工作负荷相匹配。
min_wal_size参数是只要 WAL 磁盘使用量保持在这个设置之下,在做检查点时,旧的 WAL 文件总是被回收以便未来使用,而不是直接被删除。
而检查点的写入不是全部立马完成的,PostgreSQL会将一次检查点的所有操作分散到一段时间内。这段时间由参数checkpoint_completion_target控制,它是一个分数,默认为0.5。也就是在两次检查点之间的0.5比例完成写盘操作。如果设置的很小,则检查点进程就会更加迅速的写盘,设置的很大,则就会比较慢。一般推荐设置为0.9,让检查点的写入分散一点。但是缺点就是出现故障的时候,影响恢复的时间。

参数优化工具

1.PGTune工具
https://pgtune.leopard.in.ua/#/
在线生成参数
2.postgresqltuner工具
该工具基于Perl语言开发

--安装Perl相关的开发包
yum -y install perl-DBD-Pg perl-DBI 
--下载脚本
cd /tmp
wget -O postgresqltuner.pl https://postgresqltuner.pl --no-check-certificate
或
curl -Lo postgresqltuner.pl https://postgresqltuner.pl
--赋权
chmod +x postgresqltuner.pl
--通过TCP连接到PostgreSQL server
./postgresqltuner.pl --host=dbhost --database=testdb --user=username --password=qwerty
或通过Unix套接字
./postgresqltuner.pl --host=/var/run/postgresql  # PostgreSQL socket directory

postgresql.auto.conf

和postgresql.conf相同的格式(不应该被手动编辑),保存了通过alter system命令提供的设置。
每当postgresql.conf被读 取时这个文件会被自动读取,并且它的设置会以同样的方式生效。 postgresql.auto.conf中的设置会覆盖postgresql.conf 中的设置。

1.1.4. 日志文件

pg_log

数据库运行日志,告警日志,错误日志
pg_log表示数据库运行日志,pg_log默认是关闭的,需要配置postgresql.con相关的参数启用此日志,默认路径$PGDATA/pg_log/;记录各种Error信息,定位慢查询SQL,数据库的启动关闭信息,发生checkpoint过于频繁等的告警信息。

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_wal 重做日志

WAL日志,即重做日志,也就是一些事务日志信息(transaction log)

  • PostgreSQL在将缓存的数据刷入到磁盘之前,先写日志,这就是PostgreSQL WAL( Write-Ahead Log )方式,也就是预写日志方式
  • 默认存放在$pgdata/pg_wal,单个文件大小是16M,内容一般不具有可读性,默认强制开启,无法关闭
  • 物理备份的时候需要备份此日志

PostgreSQL提供WAL切换三种方式

  • pg_switch_wal()函数可以手工切换WAL日志
  • WAL日志写满后触发归档
  • 设置archive_timeout

PG 10之前,是pg_xlog。

pg_xact事务提交日志

pg_xact(事务提交日志,记录的是事务的元数据,pg_xact是pg_wal的辅助日志),这个日志记录哪些事务完成了,哪些没有完成。

  • 一般位于:$PGDATA/pg_xact,这个日志文件一般非常小,但是重要性也是相当高,不得随意删除或者对其更改信息。
  • 内容一般不具有可读性,默认强制开启,无法关闭﹔
  • 物理备份的时候需要备份此日志。

PG 10之前,是pg_clog

1.2.逻辑结构

Database Cluster(instance)–》Database–》Schema–》Objects(Table)–>Tuples
image.png
逻辑结构分为实例、数据库、schema、对象; 最上层是实例,实例中允许创建多个数据库,每个数据库中可以创建多个schema,每个schema下面可以创建多个对象。对象包括表、索引、视图、序列、函数等。
image.png
PG与大多数的关系型数据库一样都是由表来存储数据,一个表(table)属于某个数据库(database),数据库(database)又同属于一个database cluster。
在一个数据库集群中,除了有表、数据库这些数据库对象,还有比如索引、视图、函数、序列等对象,pg对这些对象统一采用对象标识符(object identifiers (oid))来管理,oid是无符号的4字节整数。数据库对象和各自的oid存储在各自的system catalogs中,比如table是存储在pg_class, 而dababase存储在pg_database中。

test=# select datname,oid from pg_database where datname in ('test');
 datname |  oid  
---------+-------
 test    | 16385
(1 row)
test=# select relname,oid from pg_class where relname in ('walminer_lhr2');
    relname    |  oid  
---------------+-------
 walminer_lhr2 | 16396
(1 row)

1.3.内存结构

内存体系结构可以分为两大类:

  • Local memory area 本地内存区域——由每个后端进程分配供自己使用。
  • Shared memory area 共享内存区域——由PostgreSQL服务器的所有进程使用。

image.png

1.3.1.本地内存

后台服务进程除了访问共享内存外,还会申请分配一些本地内存,以便暂存一些不需要全局存储的数据,用于查询处理,这些内存缓冲区主要有以下几类:

  • 临时缓冲区:用于访问临时表的本地缓冲区
  • work_mem:内存排序操作和Hash表在使用临时磁盘文件之前使用的内存缓冲区.
  • maintenance_work_mem:在维护性操作(如vacuum,create index,和alter table add foreign key等)中使用的内存缓冲区.

image.png

子区域 描述
work_mem Executor使用此区域按顺序和不同的操作对元组进行排序,并使用merge-join和hash-join操作来连接表。
内部排序操作和Hash表在使用临时操作文件之前使用的存储缓冲区。
maintenance_work_mem 某些维护操作(如VACUUM, REINDEX)使用这个区域。在维护操作比如:VACUUM(收集表和索引的统计信息,整理表和索引)、
CREATE INDEX、ALTER TABLE ADD FOREIGN Key等中使用的内存缓冲区。
temp_buffers Executor使用此区域存储临时表。用于访问临时表的缓冲区。

1.3.2.共享内存

PostgreSQL启动后,会生成一块共享内存,共享内存主要做数据块的缓冲区,以便提高读写新能,WAL日志缓冲区和CLOG缓冲区也存在于共享内存中,除此之外,一些全局信息也保存在共享内存中,如进程信息,锁信息,全局统计信息,等.
image.png
image.png
PostgreSQL启动后,会生成一块共享内存,用于做数据块的缓冲区,以便提高读写性能。WAL日志缓冲区和xact事务日志缓冲区也存在共享内存中,除此之外还有全局信息比如进程、锁、全局统计等信息也保存在共享内存中。 其中最重要的组成部分是Shared Buffer和WAL Buffer。

Shared Buffer Pool

PostgreSQL将表和索引中的页面从持久存储加载到这里,并直接操作它们。Shared Buffer的目的是减少磁盘IO。为了达到这个目的,必须满足以下规则∶

  • 当需要快速访问非常大的缓存时(10G、100G等)
  • 如果有很多用户同时使用缓存,需要将内容尽量缩小
  • 频繁访问的磁盘块必须长期放在缓存中

WAL Buffer

WAL Buffer是用来临时存储数据库变化的缓存区域。存储在WAL Buffer中的内容会根据提前定义好的时间点参数要求写入到磁盘的WAL文件中。为了保证数据不因服务器故障而丢失,PostgreSQL支持WAL机制。WAL data(也称XLOG records)是PostgreSQL中的事务日志;WAL buffer是WAL数据写入持久存储之前的缓冲区域。 在备份和恢复的场景下,WAL Buffer和WAL文件是极其重要的。
pg10之后XLOG—>WAL

1.4.进程结构

image.pngimage.png

Postmaster主进程和服务进程

当PG数据库启动时,首先会启动Postmaster主进程。这个进程是PG数据库的总控制进程,负责启动和关闭数据库实例。实际上Postmaster进程是一个指向postgres命令的链接,如下:

[root@localhost ~]# ll /data/pgdb/pgsql/bin/postmaster 
lrwxrwxrwx. 1 root root 8 Jun 12 22:58 /data/pgdb/pgsql/bin/postmaster -> postgres

当用户和PG数据库建立连接时,要先与Postmaster进程建立连接,此时客户端进程会发送身份验证消息给Postmaster主进程,Postmaster主进程根据消息进行身份验证,验证通过后,Postmaster主进程会fork出一个会话服务进程为这个用户连接服务。可以通过pg_stat_activity表来查看服务进程的pid,如下:

postgres=# select pid,usename,client_addr,client_port from pg_stat_activity;
 pid  | usename  | client_addr | client_port 
------+----------+-------------+-------------         
  975 | postgres |             |            
 1153 | postgres |             |          -1           
(7 rows)

background writer(后台写)进程

background writer进程是把共享内存中的脏页写到磁盘上的进程。它的作用有两个:
一是定期把脏数据从内存缓冲区刷出到磁盘中,提高了缓存的替换速度,提高了数据查询性能。因为数据库在进行查询处理时,若发现要读取的数据不在缓冲区要先从磁盘中读入该页,这时如果缓冲区已满,就需要先选择一些缓冲区中的页面替换出去。如果要被替换的页被修改了,则必须先将这个页面读出到磁盘才能替换,这样数据库的查询就会被阻塞在这里。通过bgwriter定期的写出缓冲区的部分页面,就可以为缓冲区腾出空间。减少查询时的阻塞;
二是PG在定期作检查点时需要把所有脏页写出到磁盘,通过background writer预先写出一些脏页,可以减少设置检查点(CheckPoint,数据库恢复技术的一种)时要进行的IO操作,使系统的IO负载趋向平稳。background writer是PostgreSQL 8.0以后新加的特性,它的机制可以通过postgresql.conf文件中以"bgwriter_"开头配置参数来控制:

# - Background Writer -

#bgwriter_delay = 200ms    # 10-10000ms between rounds backgroud writer进程连续两次flush数据之间的时间的间隔。默认值是200,单位是毫秒。

#bgwriter_lru_maxpages = 100            # max buffers written/round, 0 disables backgroud writer进程每次写的最多数据量,默认值是100,单位buffers。如果脏数据量小于该数值时,写操作全部由backgroud writer进程完成;反之,大于该值时,大于的部分将有server process进程完成。设置该值为0时表示禁用backgroud writer写进程,完全有server process来完成;配置为-1时表示所有脏数据都由backgroud writer来完成。(这里不包括checkpoint操作)

#bgwriter_lru_multiplier = 2.0          # 0-10.0 multiplier on buffers scanned/round扫描/舍入缓冲区上的 0-10.0 乘数  这个参数表示每次往磁盘写数据块的数量,当然该值必须小于bgwriter_lru_maxpages。设置太小时需要写入的脏数据量大于每次写入的数据量,这样剩余需要写入磁盘的工作需要server process进程来完成,将会降低性能;值配置太大说明写入的脏数据量多于当时所需buffer的数量,方便了后面再次申请buffer工作,同时可能出现IO的浪费。该参数的默认值是2.0。
backgroud writer的最大数据量计算方式:
1000/bgwriter_delay*bgwriter_lru_maxpages*8K=最大数据量

#bgwriter_flush_after = 512kB           # measured in pages, 0 disables 数据页大小达到bgwriter_flush_after时触发backgroud writer,默认是512KB。

那么checkpoint与Bgwriter的区别是什么?
checkpoint是以特定的时间间隔刷新所有脏页,并创建一个用于数据库恢复用的检查点。
而Bgwriter是在检查点之间刷新一些脏页面,以便始终有足够多的干净页面可以使用。
两者的目的和执行频率都有不同。

archiver (归档)进程

类似于Oracle数据库的ARCH归档进程,不同的是ARCH是吧redo log进行归档,archiver 是把WAL日志进行归档。再深入点,WAL日志会被循环使用,也就是说,过去的WAL日志会被新产生的日志覆盖,archiver 进程就是为了在覆盖前把WAL日志备份出来。归档日志的作用是为了数据库能够使用全量备份和备份后产生的归档日志,从而让数据库回到过去的任一时间点。PG从8.X版本开始提供的PITR(Point-In-Time-Recovery)技术,就是运用的归档日志。
archiver 进程通过postgresql.conf文件中的如下参数进行配置:

# - Archiving -
archive_mode = on               # enables archiving; off, on, or always               # (change requires restart) 表示是否进行归档操作,可选择为off(关闭)、on(启动)和always(总是开启),默认值为off(关闭)

archive_command ='/usr/bin/lz4 -q -z %p /data/pgdb/pg_archive/%f.lz4'           # command to use to archive a logfile segment
                                # placeholders: %p = path of file to archive
                                #               %f = file name only
                                # e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f' 由管理员设置的用于归档WAL日志的命令。在用于归档的命令中,预定义变量“%p”用来指代需要归档的WAL全路径文件名,“%f”表示不带路径的文件名(这里的路径都是相对于当前工作目录的路径)。每个WAL段文件归档时将调用archive_command所指定的命令。当归档命令返回0时,PostgreSQL就会认为文件被成功归档,然后就会删除或循环使用该WAL段文件。否则,如果返回一个非零值,PostgreSQL会认为文件没有被成功归档,便会周期性地重试直到成功。

#archive_timeout = 0            # force a logfile segment switch after this
                                # number of seconds; 0 disables
表示归档周期,在超过该参数设定的时间时强制切换WAL段,默认值为0(表示禁用该功能)。

stats collector(统计数据收集)进程

stats collector进程是PostgreSQL数据库的统计信息收集器,用来收集数据库运行期间的pg_stat_activity和pg_stat_database等统计信息,如表的增删改次数,数据块的个数,索引的变化等等。收集统计信息主要是为了让优化器做出正确的判断,选择最佳的执行计划。postgresql.conf文件中与stats collector进程相关的参数,如下:

# STATISTICS
#------------------------------------------------------------------------------

# - Query and Index Statistics Collector -

#track_activities = on 表示是否对会话中当前执行的命令开启统计信息收集功能,该参数只对超级用户和会话所有者可见,默认值为on(开启)

#track_activity_query_size = 1024       # (change requires restart)  设置用于跟踪每一个活动会话的当前执行命令的字节数,默认值为1024,只能在数据库启动后设置

#track_counts = on 表示是否对数据库活动开启统计信息收集功能,由于在AutoVacuum自动清理进程中选择清理的数据库时,需要数据库的统计信息,因此该参数默认值为on。

#track_io_timing = off  定时调用数据块I/O,默认是off,因为设置为开启状态会反复的调用数据库时间,这给数据库增加了很多开销。只有超级用户可以设置

#track_wal_io_timing = off
#track_functions = none                 # none, pl, all 表示是否开启函数的调用次数和调用耗时统计

#stats_temp_directory = 'pg_stat_tmp' #统计信息的临时存储路径。路径可以是相对路径或者绝对路径,参数默认为pg_stat_tmp,设置此参数可以减少数据库的物理I/O,提高性能。此参数只能在postgresql.conf文件或者服务器命令行中修改。

autovacuum launcher(自动清理)进程

在PG数据库中,对数据进行UPDATE或者DELETE操作后,数据库不会立即删除旧版本的数据,而是标记为删除状态。这是因为PG数据库具有多版本的机制,如果这些旧版本的数据正在被另外的事务打开,那么暂时保留他们是很有必要的。当事务提交后,旧版本的数据已经没有价值了,数据库需要清理垃圾数据腾出空间,而清理工作就是autovacuum launcher进程进行的。postgresql.conf文件中与autovacuum launcher进程相关的参数有:

# AUTOVACUUM
#------------------------------------------------------------------------------

#autovacuum = on   #是否启动系统自动清理功能,默认值为on
#autovacuum_max_workers = 3   #设置系统自动清理工作进程的最大数量
#autovacuum_naptime = 1min   #设置两次系统自动清理操作之间的间隔时间
#autovacuum_vacuum_threshold = 50  #设置当表上被更新的元组数的阈值超过这些阈值时分别需要执行vacuum和analyze
#autovacuum_vacuum_insert_threshold = 1000      # min number of row inserts
                                        # before vacuum; -1 disables insert
                                        # vacuums
#autovacuum_analyze_threshold = 50  #设置当表上被更新的元组数的阈值超过这些阈值时分别需要执行vacuum和analyze

#autovacuum_vacuum_scale_factor = 0.2   # 设置清理操作之前表大小的缩放系数
#autovacuum_vacuum_insert_scale_factor = 0.2    # fraction of inserts over table
                                        # size before insert vacuum
#autovacuum_analyze_scale_factor = 0.1  #设置清理操作之前表大小的缩放系数
#autovacuum_freeze_max_age = 200000000  #设置需要强制对数据库进行清理的XID上限值
#autovacuum_multixact_freeze_max_age = 400000000        # maximum multixact age
                                        # before forced vacuum
                                        # (change requires restart)
#autovacuum_vacuum_cost_delay = 2ms   #当autovacuum进程即将执行时,对 vacuum 执行 cost 进行评估,如果超过 autovacuum_vacuum_cost_limit设置值时,则延迟,这个延迟的时间即为 autovacuum_vacuum_cost_delay。如果值为 -1, 表示使用 vacuum_cost_delay 值,默认值为 20 ms。

#autovacuum_vacuum_cost_limit = -1     #这个值为 autovacuum 进程的评估阀值, 默认为 -1, 表示使用 "vacuum_cost_limit " 值,如果在执行 autovacuum 进程期间评估的cost 超过 autovacuum_vacuum_cost_limit, 则 autovacuum 进程则会休眠。

walwriter(预写式日志写)进程


wal_level = replica  #wal_level:控制wal存储的级别。wal_level决定有多少信息被写入到WAL中。 默认值是最小的(minimal),其中只写入从崩溃或立即关机中恢复的所需信息。replica 增加 wal 归档信息 同时包括 只读服务器需要的信息。(9.6 中新增,将之前版本的 archive 和 hot_standby 合并) 。logical 主要用于logical decoding 场景

#fsync = on   #fsync:该参数直接控制日志是否先写入磁盘。默认值是ON(先写入),表示更新数据写入磁盘时系统必须等待WAL的写入完成。可以配置该参数为OFF,表示更新数据写入磁盘完全不用等待WAL的写入完成。

#synchronous_commit = on  #synchronous_commit:参数配置是否等待WAL完成后才返回给用户事务的状态信息。默认值是ON,表明必须等待WAL完成后才返回事务状态信息;配置成OFF能够更快地反馈回事务状态。

#wal_sync_method = fsync  #wal_sync_method:WAL写入磁盘的控制方式,默认值是fsync,可选用值包括open_datasync、fdatasync、fsync_writethrough、fsync、open_sync。open_datasync和open_sync分别表示在打开WAL文件时使用O_DSYNC和O_SYNC标志;fdatasync和fsync分别表示在每次提交时调用fdatasync和fsync函数进行数据写入,两个函数都是把操作系统的磁盘缓存写回磁盘,但前者只写入文件的数据部分,而后者还会同步更新文件的属性;fsync_writethrough表示在每次提交并写回磁盘会保证操作系统磁盘缓存和内存中的内容一致。

#full_page_writes = on  #full_page_writes:表明是否将整个page写入WAL。

#wal_buffers = -1  #wal_buffers:用于存放WAL数据的内存空间大小,系统默认值是64K,该参数还受wal_writer_delay、commit_delay两个参数的影响。 

#wal_writer_delay = 200ms  #wal_writer_delay:WalWriter进程的写间隔时间,默认值是200毫秒,如果时间过长可能造成WAL缓冲区的内存不足;时间过短将会引起WAL的不断写入,增加磁盘I/O负担。 

#wal_writer_flush_after = 1MB  #wal_writer_flush_after 以页为单位,0 禁用

#commit_delay = 0  #commit_delay:表示一个已经提交的数据在WAL缓冲区中存放的时间,默认值是0毫秒,表示不用延迟;设置为非0值时事务执行commit后不会立即写入WAL中,而仍存放在WAL缓冲区中,等待background writer进程周期性地写入磁盘。

#commit_siblings = 5  #commit_siblings:表示当一个事务发出提交请求时,如果数据库中正在执行的事务数量大于commit_siblings值,则该事务将等待一段时间(commit_delay的值);否则该事务则直接写入WAL。系统默认值是5,该参数还决定了commit_delay的有效性。

 wal_writer_flush_after:当脏数据超过阈值时,会被刷出到磁盘。

checkpointer(检查点)进程

checkpoint又名检查点,会将某个时间点之前的脏数据全部刷新到磁盘,以实现数据的一致性与完整性。其主要目的是为了缩短崩溃恢复时间,在进行数据恢复时,会以最近的checkpoint为参考点执行事务前滚。而在WAL机制的浅析中,在崩溃恢复时会以最近的checkpoint为基础,不断应用这之后的WAL日志。postgresql.conf文件中与之相关的参数有:

#checkpoint_timeout = 5min              # range 30s-1d
#checkpoint_completion_target = 0.9     # checkpoint target duration, 0.0 - 1.0
#checkpoint_flush_after = 256kB         # measured in pages, 0 disables
#checkpoint_warning = 30s               # 0 disables
max_wal_size = 1GB
min_wal_size = 80MB

logger进程

日志信息是数据库管理员获取数据库系统运行状态的有效手段。在数据库出现故障时,日志信息是非常有用的。把数据库日志信息集中输出到一个位置将极大方便管理员维护数据库系统。然而,日志输出将产生大量数据(特别是在比较高的调试级别上),单文件保存时不利于日志文件的操作。因此,在logger的配置选项中可以设置日志文件的大小,logger会在日志文件达到指定的大小时关闭当前日志文件,产生新的日志文件。在postgresql.conf里可以配置日志操作的相关参数:


# - Where to Log -

log_destination = 'csvlog' #配置日志输出目标,根据不同的运行平台会设置不同的值,Linux下默认为stderr

# This is used when logging to stderr:
logging_collector = on  #是否开启日志收集器,当设置为on时启动日志功能;否则,系统将不产生系统日志辅助进程。

# These are only used if logging_collector is on:
log_directory = 'log'  #配置日志输出文件夹
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' #配置日志文件名称命名规则
log_file_mode = 0600                    # creation mode for log files,
                                        # begin with 0 to use octal notation
log_rotation_age = 1d                   # Automatic rotation of logfiles will
                                        # happen after that time.  0 disables.
log_rotation_size = 10MB   #配置日志文件大小,当前日志文件达到这个大小时会被关闭,然后创建一个新的文件来作为当前日志文件。
#log_truncate_on_rotation = off         # If on, an existing log file with the
                                        # same name as the new log file will be
                                        # truncated rather than appended to.
                                        # But such truncation only occurs on
                                        # time-driven rotation, not on restarts
                                        # or size-driven rotation.  Default is
                                        # off, meaning append to existing files
                                        # in all cases.

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论