PostgreSQL体系架构知多少

33 阅读8分钟

PostgreSQL体系架构知多少

Whoami:5年+金融、政府、医疗领域工作经验的DBA Certificate:PGCM、OCP、YCP Skill:Oracle、Mysql、PostgreSQL、国产数据库 Platform:CSDN、墨天伦、公众号(呆呆的私房菜)

业务范围:数据库安装部署、日常维护、主备切换、故障处理、性能优化、技术培训等。 需要的伙伴或者商业合作请移步 公众号【呆呆的私房菜】获取联系方式。

阅读本文可以了解PostgreSQL数据库的体系架构,包含内存结构和进程结构,逻辑结构和物理结构。

01 内存结构

  1. **共享进程:**PostgreSQL 启动之后,会生成一块共享内存(shared_buffers),共享内存主要用作数据块的缓冲区,以便提高读写性能。wal 日志缓冲区 和 clog 缓冲区也存放于共享内存中。除此之外,一些全局信息也存放在内存中,如进程信息,锁信息、全局统计信息等。

  2. **本地进程:**后台进程除了访问共享内存外,还会申请分配一些本地内存,以便暂存一些不需要全局存储的数据,这些内存缓冲区主要有:

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

02 进程结构

  1. **postmaster:**客户端发起连接,PG会启动一个服务进程为这个连接服务。当某个服务进程出现异常,Postmaster主进程会自动完成系统的恢复,恢复过程中会停掉所有的服务进程,然后进行数据一致性恢复,恢复完成之后才开始接收新的连接。
  2. **syslogger:**通过从postmaster进程、所有的服务进程及其他辅助进程收集所有的stderr输出,并将这些输出写入到日志文件中。
  3. **bgwriter:**辅助进程是把共享内存中的脏页写入磁盘上的进程。
  4. **walwriter:**负责写入Wal日志的进程。概念就是在修改数据之前,必须将这些修改操作记录到磁盘中,后面更新实际数据时,就不需要实时的将数据持久化到文件中了。WAL日志保存在pg_wal下,每个文件默认是16MB。
  5. **pgarch:**由于Wal日志会被循环使用,PgArch归档进程会把覆盖前的WAL日志备份出来。
  6. **autovacuum:**postgresql对表进行delete操作后,旧的数据并不会立即被删除。并且,在更新数据时,也不会在旧的数据上做更新,而是生成一行新的数据。旧的数据只是被表示为删除状态,只有在没有并发的其他事务读到这些旧数据时,它们就会被autovacuum进程清除。
  7. **pgstat:**该辅助进程用来做数据的统计收集工作。收集的信息主要用于查询优化时的代价估算,这些信息包括在一个表和索引上进行了多少次的插入、更新、删除操作,磁盘块读写的次数以及行的读次数。系统表pg_statistic中存储了PgStat收集的各类统计信息。

03 物理结构

  1. 数据文件:物理存储结构是操作系统中组织和管理数据库的方式。主要包括数据文件、日志文件、参数文件、控制文件、wal文件。执行initdb的时候会初始化一个目录,在这个目录会生成相关的子目录和一些文件。PG的表空间概念不同于其他关系型数据库,这里的tablespace对应的都是一个目录。 下图是对每个目录的功能和作用的介绍。 数据文件用于存储数据。文件名以oid命名,对于超出1G的表数据文件,PostgreSQL会自动将其拆分为多个文件来存储,而拆分的文件名将由pg_class中的relfilenode字段来决定。
## 查看t1表物理文件存储路径,实际上就是 base/<database oid>/<relation oid>
test=# select pg_relation_filepath('t1');
 pg_relation_filepath 
----------------------
 base/16384/16413
(1 行记录)

## 查看数据库oid
test=# select oid, datname from pg_database where datname = 'test';
  oid  | datname 
-------+---------
 16384 | test
(1 行记录)

## 如下是查看t1表的oid和relfilenode
test=# select oid, relfilenode, relname, relkind from pg_class where relname = 't1';
  oid  | relfilenode | relname | relkind 
-------+-------------+---------+---------
 16413 |       16413 | t1      | r
(1 行记录)

## 值得注意的是,relation的oid是唯一的,但是relfilenode是会变化的,例如当执行vacuum full t1的时候,relfilenode就会变化,这跟
  1. 日志文件: **运行日志文件:**默认没有开启,开启后会自动生成。这个日志一般是记录服务器与DB的状态,比如各种Error信息,定位慢查询SQL,数据库的启动关闭信息,发生checkpoint过于频繁等的告警信息,诸如此类。该日志有.csv格式和.log。 建议使用.csv格式,因为它一般会按大小和时间自动切割。pg_log是可以被清理删除,压缩打包或者转移,同时并不影响DB的正常运行。当我们有遇到DB无法启动或者更改参数没有生效时,第一个想到的就是查看这个日志。 **重做日志文件:**pg_xlog 这个日志是记录的Postgresql的WAL信息,默认存储在目录PGDATA/pgwal/,是一些事务日志信息(transactionlog)。默认单个大小是16M,源码安装的时候可以更改其大小(./configurewithwalsegsize=targetvalue参数即可设置)。这些日志会在定时回滚恢复(PITR),流复制(ReplicationStream)以及归档时能被用到,这些日志是非常重要的,记录着数据库发生的各种事务信息,不得随意删除或者移动这类日志文件,不然你的数据库会有无法恢复的风险。事务日志文件:pgxact是事务提交日志,记录了事务的元数据。默认开启。内容一般不能直接读。默认存储在目录PGDATA/pg_wal/,是一些事务日志信息(transaction log)。默认单个大小是16M,源码安装的时候可以更改其大小(./configure --with-wal-segsize=target_value 参数即可设置)。 这些日志会在定时回滚恢复(PITR), 流复制(Replication Stream)以及归档时能被用到,这些日志是非常重要的,记录着数据库发生的各种事务信息,不得随意删除或者移动这类日志文件,不然你的数据库会有无法恢复的风险。 **事务日志文件:**pg_xact是事务提交日志,记录了事务的元数据。默认开启。内容一般不能直接读。默认存储在目录PGDATA/pg_xact/。 **服务器日志文件:**如果用pg_ctl启动的时候没有指定-l参数来指定服务器日志,错误可能会输出到cmd前台。服务器日志记录了数据库的重要信息。 **参数文件:**postgresql.conf,PostgreSQL的主要参数文件,有很详细的说明和注释,和Oracle的pfile,MySQL的my.cnf类似。默认在PGDATA下。很多参数修改后都需要重启。9.6之后支持了altersystem来修改,修改后的会存在PGDATA下。很多参数修改后都需要重启。9.6之后支持了alter system来修改,修改后的会存在PGDATA/postgresql.auto.conf下,可以reload或者 restart来使之生效。 **pg_hba.conf:**数据库连接黑白名单的设置。 **pg_ident.conf:**pg_ident.conf是用户映射配置文件,用来配置哪些操作系统用户可以映射为数据库用户。结合pg_hba.conf中,method为ident可以用特定的操作系统用户和指定的数据库用户登录数据库。 **控制文件:**控制文件记录了数据库运行的一些信息,比如数据库id,是否open,wal的位置,checkpoint的位置等等。controlfile是很重要的文件。 **wal文件:**默认保存在$PGDATA/pg_wal目录下。文件名称为16进制的24个字符组成,每8个字符一组,每组的意义【时间线、逻辑线、物理ID】

04 逻辑结构

逻辑存储结构是内部的组织和管理数据的方式。所有的数据库对象都有各自的object identifers,oid是一个无符号的4字节整数,相关对象的oid都存放在相关的系统catalog表中,比如数据库的oid和表的oid分别存放在pg_database和pg_class表中。

**database cluster:**数据库集群簇,它是指向单个PG服务器实例管理的数据库集合,组合数据库集群的这些数据库使用相同的全局配置文件和监听端口,共用进程和内存结构。 一个Database cluster可以包含多个database、多个user以及databases中的所有对象。 database:在PG中,数据库本身也是数据库对象,并且在逻辑上彼此分离,出数据库之外的其他数据库对象(例如表、索引等)都属于它们各自的数据库。 database object:如:表、视图、索引、序列、函数等等。在PostgreSQL中的所有数据库对象都由各自的对象标识符(OID)进行内部的管理。数据库的OID存储在pg_database系统表中,数据库对象的OID存储在pg_class系统表中。 **tablespace:**数据库在逻辑上分为多个存储单元,称为表空间。表空间的作用把逻辑上相关的结构放在一起。数据库逻辑上是一个或多个表空间组成。初始化的时候,会自动创建pg_default和pg_global两个表空间。 **schema:**当创建一个数据库时,会为其创建一个名为public的默认schema。Schema是数据库中的命名空间。在数据库创建的所有对象都是在schema中创建。一个用户可以从同一个客户端连接中访问不同的schema。而不同的schema中可以有多个同名的table、index、view、sequence、Funcation等数据库对象。 **segment:**一个段是分配给一个逻辑结构(一个表、一个索引或其他对象)的一组区,是数据库对象使用的空间的集合;段可以有表段、索引段、回滚段、临时段和高速缓存段等。 extent: 区是数据库存储空间分配的一个逻辑单位,它由连续数据块所组成。第一个段是由一个或多个盘区组成。当一段中间所有空间已完全使用,PostgreSQL为该段分配一个新的范围。 **block:**数据块是PostgreSQL 管理数据文件中存储空间的单位,为数据库使用的I/O的最小单位,是最小的逻辑部件。默认值8K。