Postgresql杂谈 02—Postgresql体系介绍

一、Postgresql的内存结构

       所谓的内存结构,就是Postgresql在运行时的内存构成,即有多少个进程,每个进程的作用是什么。我们先来看一张PG服务器的运行时内存结构图:

       接下来,我们分别介绍了Postgresql各个进程的作用。

1.1 主进程PostMaster

       postmaster进程是PG数据库最主要的管理进程,它的作用主要有两个:

(1)可以启动和关闭数据库的实例。

/usr/pgsql-11/bin/postmaster -D $PGDATA

       如果是在centos7+下使用yum安装的postgresql,那么postgresql的启停会托管给systemctl,我们在/usr/lib/systemd/system/postgresql-11.service文件中就可以看到配置的ExecStart就是使用的上述命令:

       实际上,postmaster 命令只是postgres命令的一个软链接,可以看到postmaster 的目标命令是postgres。如下所示,postmaster命令只是同目录postgres命令的一个软连接

[postgres@VM-115-39-centos /usr/pgsql-11/bin]ls -l postmaster 
lrwxrwxrwx 1 root root 8 Jul 25 2020 postmaster -> postgres

(2)为客户端的链接创建postgres子进程。

       Postgresql针对每个客户端的链接都会fork一个子进程,如下所示,圈出部分就是客户端的一个远程链接而创建的postgres进程,所以Postgresql在处理客户端链接时成本还是很高的。

1.2 backgroud writer进程

       bgwriter进程是将共享内存中的脏数据块写入到磁盘上的进程。这里,先解释下什么是脏数据块。当向数据库中插入或者更新数据时,往往不会马上将这些更新的数据写入到磁盘,而是直接在内存中进行更新,这样做主要是为了提高更新或者插入的效率。但是这也就引入了一个问题——内存中的数据和磁盘中已经持久化的数据是不一致的,我们就把这部分内存中的数据称为脏块。bgwriter进程的作用就是按照一定的周期,将脏块的数据写入到磁盘。这个更新的频率可以通过postgresql.conf配置文件进行配置,过高或者过低的频率都有问题,比如说过高的话,磁盘IO过于频繁,性能会降低;过低时,有可能造成内存不足,当有新的数据要写入或者要查询脏块中的数据时,就需要将数据先写入到内存中,必然会造成更新或者查询更慢。所以我们进行配置时要找到一个合适的频率。

1.3 wal writer进程

       postgresql中的wal日志也叫预写日志,和oracle中的redo日志类似,执行数据更新时,先要将更新记录记录到磁盘上,主要是为了防止在数据库服务器突然宕机时,内存中的脏数据丢失,可以根据wal日志进行数据的恢复。wal日志的保存目录是在$PGDATA/pg_wal目录下,可以看到文件名逐渐递增,而且每个文件的大小都是16M,总的大小可配置,当达到了最大的值,新的Wal日志会覆盖旧的: 

1.4 logger进程

       logger进程可以收集包括postmaster进程在内的所有进程的stderr日志,这里需要注意是错误日志哦,并不是所有的日志它都会收集。它支持通过postgresql.conf文件修改日志相关的参数,可以设置最大值并循环覆盖,日志的默认目录在$PGDATA/logs/,像我本机默认的日志记录如下,每天一个日志文件,按照星期存储:

       查看某个日志的内容,发现都是一些错误的信息:

1.5 checkpoint进程

       和oracle类似,postgresql也有检查点进程checkpoint,检查点进程的主要作用就是,辅助bgwriter进行内存中脏数据块的写入。实际上,当bgwriter向磁盘中写入脏块时,是通过checkpoint进程实际写入的。bgwriter在扫描出脏块后,会发起写入的request,而checkpoint进程会读取这些request,将脏块批量写入磁盘,并且会记录已经写入后的脏块,从而保证下次只会写入新的脏块。

1.6 autovacuum launcher进程

       该进程主要是两个作用:

(1)PG数据库中DELET操作,原来的数据并不会被立即删除。即使是Update的数据,也不会在旧的数据行上进行更新,而是新生成一行数据,将原来的数据行标记为删除状态。这就是为了PG数据库的共享锁和独占锁机制,只有在其它事务没有在读取这些旧数据时,它们才会被删除。而autovacuum进程的作用就是自动清理这些被标记为删除状态的数据。

(2)负责统计信息的收集,用于查询优化时的代价的估算。

1.7 state collector进程

       该进程的主要作用就是数据的统计收集,比如在一个表上进行了多少次的插入、更新和删除操作,磁盘块的读写次数、行的读写次数等等。

1.8 logical replication launcher进程

       用于逻辑复制,订阅者通过 logical replication launcher进程向发布者订阅表的更新并获取更新。

1.9 archiver进程

       归档进程,所谓归档,就是在旧的WAL日志在覆盖前把其备份出来,Postgresql支持一种PITR(Point-In-Time-Recovery)技术,就是在数据库进行一次全量备份之后,该技术会将备份时间点之后的WAL日志归档备份,这样使用全量备份再加上WAL日志,就可以将数据库恢复到任意的时间点了。但是需要注意的是Postgresql默认的配置是不开发归档功能的,如果需要开放,要在postgresql.conf文件中设置archive_mode = on

1.10 共享内存

       主要作为数据缓冲区,提高读写性能,作为WAL日志和Commit日志的缓冲区等等。

1.11 本地内存

  • 临时缓冲区,用来访问临时表的本地缓冲区
  • work_mem,作为内部排序操作和联合查询时合并链接、Hash链接的临时内存
  • maintenance_work_mem,在维护性操作(比如VACUUM、CREATE INDEX)中使用的内存缓冲区。

二、Postgresql的逻辑结构

  • 数据库簇

       可以理解为一个数据库的容器,可以存放多个数据库实例(create database)。Postgresql的数据库是一个多租户的概念,租户之间互相隔离。

  • 数据库

       这个不用多解释了,使用create database可以创建数据库。

  • 模式schema

       模式是相同数据库下逻辑隔离的基本单位,可以通过create schema创建不同的模式,其实有点类似与oracle中的用户,oracle中不同用户可以创建不同的表,表名可以重复,其它用户访问别的用户的表时需要带上用户名,这样就实现了用户间的数据隔离,而Postgresql中使用模式达到这种数据隔离的目的。

test=# create schema myschema;
CREATE SCHEMA
test=# create table myschema.mytable(id INT,name varchar);
CREATE TABLE
test=# \d+ myschema.mytable
                                      Table "myschema.mytable"
 Column |       Type        | Collation | Nullable | Default | Storage  | Stats target | Description 
--------+-------------------+-----------+----------+---------+----------+--------------+-------------
 id     | integer           |           |          |         | plain    |              | 
 name   | character varying |           |          |         | extended |              |    

三、Postgresql的目录结构

3.1 程序目录结构

  • 跟目录,一般是在/usr/pgsql-<主版本>下
  • bin/,存放了二进制的可执行程序,比如启停程序postgres,备份工具pg_dump、pg_restore等备份工具、psql客户端工具,都是在这里。
  • lib/,存放了动态库文件,*.so
  • share/,存放了文档和配置文档文件、以及扩展包的sql文件等等。

3.2 存储目录结构

  • 跟目录,/var/lib/pgsql/<主版本号>/data
  • postgresql.conf,数据库实例的配置文件,基本上所有的配置参数都在这个文件中
  • postgresql.auto.conf,通过alter system修改的配置参数存放到该文件内。
  • pg_ident.conf,ident认证方式的配置文件
  • pg_hba.conf,认证相关的配置文件
  • PG_VERSION,记录了数据库的主版本
  • postmaster.opts,记录上数据库启动的命令行参数
[postgres@VM-115-39-centos ~/11/data]cat postmaster.opts /usr/pgsql-11/bin/postgres "-D" "/var/lib/pgsql/11/data/"

       以上是主要的文件,接下来是几个主要的子目录

  • base/,默认表空间的目录,下面有多个子目录,子目录的名称对应的数据库的OID相同

数据库的OID:

postgres=# select oid,datname from pg_database;
  oid  |         datname         
-------+-------------------------
 13881 | postgres
     1 | template1
 13880 | template0
 16385 | stock_analysis_data
 17724 | stock_test_activiti
 18121 | stock_analysis_activiti
 18621 | test
 18622 | test1
 18623 | test2

base目录下的子目录:

[postgres@VM-115-39-centos ~/11/data]ls base/ 
13880 13881 16385 17724 18121 18621 18622 18623 pgsql_tmp
  • global/,共享系统表的目录
  • log/,logger进程存放的错误日志
  • pg_commit_ts/,视图提交的时间戳数据
  • pg_dynshmem/,动态共享内存子系统使用的文件
  • pg_logical/,logical replication launcher进程进行逻辑复制的中间数据
  • pg_multixact/,多事务的中间数据
  • pg_notify/,listen/notify状态的数据
  • pg_replslot/,复制槽的数据
  • pg_serial/,已经提交的可串行话的事务的数据
  • pg_snapshots/,函数pg_export_snapshot导出的快照文件存放目录。
  • pg_stat/,统计子系统的永久文件
  • pg_stat_tmp/,统计子系统的临时文件
  • pg_subtrans/,子事务状态数据
  • pg_tblspc/,存放指向用户表空间目录的链接文件
  • pg_twophase/,使用两阶段提交的分布式事务时的存储目录
  • pg_wal/,WAL日志的存放目录
  • pg_xact/,Commit Log的目录

       接下来,我们思考一个问题:数据库中每个表里面的数据都是存到磁盘文件中的,那么这些文件的存储位置在哪呢?要想弄清楚这个问题,我们需要了解一个概念——relfilenode,当我们创建一个表或者索引时,Postgresql会为每个表和索引都分配一个relfilenode(实际上就是一个int类型的编号),可以通过pg_class查询到某个表的relfilenode。比如查询表fund的relfilenode:

stock_analysis_data=# select relnamespace,relname,relfilenode from pg_class where relname='fund';
         2200 | fund    |       17586

       fund是数据库stock_analysis_data中的一个表,通过上面我们从pg_database查询数据库的OID得知,stock_analysis_data的OID是16385 ,而stock_analysis_data用的是默认的表空间,从上面的查询中可以看到,fund表的relfilenode为17586。一张表的数据文件目录为:

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

       其中,顺序号从1开始,当表或索引的大小超过1G时,顺序号加1,所以fund表对应的文件路径如下:

/var/lib/pgsql/11/data/base/16385/17586

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值