PostgreSQL的体系结构
1. 体系架构
1、应用程序访问接口
整个应用架构中,Postgresql数据库位于操作系统和应用程序之间,不同的编程语言使用不同的驱动程序链接到Postgresql数据库上,驱动分为两类:
1.使用纯语言实现的Postgresql驱动,如JDBC、.NET等方式,这种链接方式不需要 libpq 库。
2.通过包装Postgresql的C语言接口库libpq实现的驱动,比如,python下的psycopg2库、Perl的DBD::Pg模块、ODBC等,所以在安装这些驱动之前,需要先安装Postgresql的libpq库。
一般情况下,各种应用程序都是通过 TCP/IP 协议链接到Postgresql数据库,如果应用程序和数据库在一台服务器上,可以通过 UNIX domain socket 链接到Postgresql数据库。
2、进程及内存结构
2.1 进程和内存架构图
Postgresql数据库启动时,会先启动一个叫 Postmaster 的主进程,如上图。还会 fork 出一些辅助子进程,这些辅助紫禁城各自负责自己的功能。主要辅助子进程如下:
SysLogger(系统日志)进程
BgWriter(后台写)进程
WalWriter(预写式日志)进程
PgArch(归档)进程
AutoVAcuum(系统自动清理)进程
PgStat(统计收集)进程
进程详解:
1.主进程Postmaster
Postgresql数据库的主要功能都集中在于postgres程序,这个程序位于安装目录的bin目录下,如下:
[postgres@local ~]$ which postgres
/data/pgsql/bin/postgres
[postgres@local ~]$ ls -l /data/pgsql/bin/postgres
-rwxr-xr-x 1 root root 8242972 Feb 12 21:03 /data/pgsql/bin/postgres
主进程Postmaster时整个数据库实例的总控进程,负责启动和关闭该数据库实例。用户可以运行postmaster、postgres命令并加上合适的参数启动数据库。实际上,postmaster命令是一个指向postgres的链接,如下
[postgres@local ~]$ which postmaster
/data/pgsql/bin/postmaster
[postgres@local ~]$ ls -l /data/pgsql/bin/postmaster
lrwxrwxrwx 1 root root 8 Feb 12 21:03 /data/pgsql/bin/postmaster -> postgres
不过,通常会使用pg_ctl命令来启动数据库,pg_ctl也是通过运行postgres来启动数据库的,只是它做了一下包装,使我们更容易启动数据库。所以,主进程postmaster实际上是第一个postgres进程,此进程还会fork出一些与数据库实例相关的辅助子进程,并管理它们。
当用户与Postgresql数据库建立连接时,实际上先与postmaster进程建立连接,此时,客户端程序会发出身份验证的消息给postmaster主进程,postmaster主进程根据消息中的消息进行客户端身份验证,如果验证通过,它会fork出一个子进程来为这个连接服务。fork出的子进程称为服务进程。查询pg_stat_activity
表时看到的pid,就是这些服务进程的pid,如下:
postgres=# select pid,usename,client_addr,client_port from pg_stat_activity ;
pid | usename | client_addr | client_port
--------+----------+-------------+-------------
19107 | | |
19109 | postgres | |
2415 | postgres | | -1
2424 | postgres | | -1
4056 | postgres | | -1
119083 | mytest | | -1
19105 | | |
19104 | | |
19106 | | |
(9 rows)
客户端每次与数据库建立连接时,Postgresql数据库就会启动一个服务进程来给这个连接服务,所以Postgresql数据库是进程架构模型。这与MySQL数据库不一样,MySQL数据库每建立一个连接时,数据库启动的是一个线程,所以MySQL数据库是线程架构模型。
当某个服务进程出现错误时,postmaster主进程会自动完成系统的恢复。恢复过程中会停掉所有的服务进程,然后进行数据库数据的一致性恢复,等恢复完成或,数据库又可以构建新的链接了。
2.2 辅助进程
在系统终端界面查询后台进程:
[root@local Desktop]# ps -ef|grep postgres
postgres 13581 1 0 12:57 ? 00:00:00 /data/pg12.1/bin/postgres -D /data/pgsql_data
postgres 13582 13581 0 12:57 ? 00:00:00 postgres: logger
postgres 13584 13581 0 12:57 ? 00:00:00 postgres: checkpointer
postgres 13585 13581 0 12:57 ? 00:00:00 postgres: background writer
postgres 13586 13581 0 12:57 ? 00:00:00 postgres: walwriter
postgres 13587 13581 0 12:57 ? 00:00:00 postgres: autovacuum launcher
postgres 13588 13581 0 12:57 ? 00:00:00 postgres: stats collector
postgres 13589 13581 0 12:57 ? 00:00:00 postgres: logical replication launcher
root 14076 14063 0 14:23 pts/0 00:00:00 grep postgres
(1)SysLogger(系统日志)进程–logger
在配置文件postgresql.conf中有很多与日志相关的参数,其中只有参数 logging_collect 设置为 on 时,主进程才会启动 SysLogger(系统日志)进程。
SysLogger 辅助进程通过从postmaster主进程,所有的服务进程及其他辅助进程收集所有的stderr输出,并将这些输出写入到日志文件中。在postgresql.conf配置文件中设置了日志文件的大小和存在时间。当一个日志文件达到了配置中的大小或其他条件时,SysLogger 辅助进程就会关闭旧的日志文件,并创建一个新的日志文件。如果收到了装载配置文件的信号,就会检查配置文件中的配置参数 “log_directory“ 和 ”log_filename“ 是否与当前的相同,如果不同,则会切换日志文件并使用新的配置。
(2)BgWriter(后台写)进程-- background writer
在Postgresql中,BgWriter辅助进程是把共享内存中的脏页写到磁盘上的进程。当数据库插入或者更新数据时,并不会马上把数据持久化到数据文件中,也就是将数据马上写到磁盘中。这主要是为了提高插入、更新、删除数据的行能,因此数据写磁盘是比较好性能的操作,如果每条修改的记录都进行写磁盘操作,会严重消耗系统性能。所以一般是将数据读取到内存并修改后会被BgWriter辅助进程周期性的刷新到磁盘中,这个操作不能过快也不能太慢,太快消耗性能,太慢会导致大量脏数据一直存放内存中,导致内存消耗过大,读取数据就会因为内存不足导致等待时间过长,降低数据库性能。
上面提到的机制是以 “bgwriter_” 开头的配置参数来控制。
(3)WalWriter(预写式日志写)进程–walwriter
WAL是 Writer Ahead Log 的缩写,中文意思是预写式日志。WAL log也被简写为xlog。
WalWriter 进程就是写WAL日志的过程,预写式日志的概念就是在修改数据之前,必须要把这些修改操作记录到磁盘中,这样后面更新实际数据时,就不需要实时的把数据持久化到磁盘中了,即使记起突然宕机或者数据库异常退出,导致一部分内存中的脏数据没有及时刷新到新的文件中,在数据库重启后,通过读取WAL日志,并把最后一部分的WAL日志重新执行一遍就可以恢复到宕机时的状态。
WAL日志保存在 pg_xlog 下,每个xlog默认是16MB大小,为了满足恢复要求,在xlog目录下会产生过个WAL日志,这样可保证在宕机后,未持久化的数据可以通过WAL日志来恢复,那些不需要的WAL日志就会被自动覆盖。
(4)PgArch(归档)进程–开启归档后后台才会有此进程-archiver
WAL日志会被循环使用,也就是说,较早时间的WAL日志会被覆盖。PgArch归档进程会把覆盖前的WAL日志备份出来。Postgresql从 8.X 版本开始提供PITR(Point-In-Time-Recovery)技术,通俗的说,就是在数据库进行一次全量备份后,该技术将备份时间点之后的WAL日志通过归档进行备份,使用数据库全量备份加上后面产生的WAL日志,就可以将数据库向前推到全量备份的任意一个时间点。
(5)AutoVacuum(自动清理)进程–autovacuum launcher
在Postgresql数据库中,对表进行的 DELETE 操作后,旧的数据并不会立即删除,并且在更新数据时,也并不会在旧的数据上做更新,而是产生一行新数据(多版本)。此时,旧数据只是被标记为可删除状态,只有在没有并发的其他事物访问这些旧数据时,它们才会被清除掉,这个清除工作就是有 AutoVacuum 进程来完成。
(6)PgStat(统计数据收集)进程–stats collector
PgStat 辅助进程主要做数据的统计收集工作。收集的信息主要用于查询优化时的代价估算,这些信息包括在一个表和索引上进行了多少次的DML操作,磁盘读写的次数,以及航的读次数。系统表 pg_statistic 中存储了 PgStat 收集的各类统计信息。
2.3 共享内存
Postgresql启动后,会生成一块共享内存,共享内存主要用作数据块的缓冲区,一遍提高读写性能。WAL日志缓冲区和 CLOG(Commit log)缓冲区也存在于共享内存中。除此之外,一些全局信息也保存在共享内存中,如进程信息、所信息、全局统计信息等等。
Postgresql 9.X之前的版本和Oracle数据库一样,都是使用 “system V” 类型的共享内存,但是Postgresql 9.3之后,PG使用 “mmap()” 方式的共享内存,使用这种共享内存的好处是不在需要配置 “System V” 共享内存的内核参数 “kernel.shmmax” 和 “kernel.shmall”,就能使用较大的共享内存。
共享内存中存放的信息如下:
2.4 本地内存
后台服务进程除了访问共享内存外,还会申请分配一些本地内存,以便于缓存一些不需要全局存储的数据,这些内存缓冲区主要有以下几类:
1.临时缓冲区:用于访问临时表的本地缓冲区。
2.work_mem:内部排序操作和Hash表在使用临时磁盘文件之前使用的内存缓冲区。
3.maintenance_work_mem:在维护性操作(比如VACUUM、CREATE INDEX、ALTER TABLE ADD FOREIGN KEY等)中使用的内存缓冲区。
目录结构
1.安装目录结构
Postgresql默认安装在 /usr/local目录下,可以在安装编译时指定安装目录,软件目录结构如下:
2.数据目录结构
一般使用环境变量 PGDATA 指向数据目录的根目录,类似于Oracle数据库的变量ORACLE_HOME。这个目录是在安装数据库时指定的,所以在安装时一定要选择一个合理的目录来作为数据目录的根目录。而且每个数据库实例都需要这样一个目录。目录的初始化是通过 initdb 命令初始化来的。初始化完成后,会在数据目录下生成以下配置文件:
1.postgresql.conf:数据库实例的主要配置文件,基本上数据库运行的所有配置信息都记录在此文件中。它可以直接编辑,类似oracle数据库的pfile参数文件
2.postgresql.auto.conf:从9.4版本开始,postgresql 引入了一个新的配置文件 postgresql.auto.conf 在存在相同配置的情况下系统先执行 auto.conf 这个文件,auto.conf 配置文件优先级高于 conf 文件。而且 auto.conf文件参数必须在 psql 中使用 alter system 来修改,而conf可以直接在文本编辑器中修改。类似于oracle数据库的spfile参数文件。
3.pg_hba_conf:数据库认证配置文件,主要配置数据库的访问信息。
4.pg_ident.conf:“ident”认证方式的用户映射文件。
5.PG_VERSION:pg数据库主版本号文件。
6.postmaster.opts:记录服务器最后一次启动时使用的命令行参数。
此目录下还会生成各种子目录:
1.base:默认表空间的目录,系统表和没有执行表空间的表创建后会存放在此目录下的表空间目录中。
2.global:数据库共享系统表的目录
3.pg_tblspc:存储了一个指向用户自定义表空间实际存放目录位置的链接文件。初始是空目录,在数据库中创建表空间存储数据后,会在目录下生成连接文件,指向用户创建表空间指定的目录。
4.pg_commit_ts:包含事务提交时间戳数据的子目录。
5.pg_xact:包含事务提交状态数据的子目录。
6.pg_dynshmem:包含被动态共享内存子系统所使用文件的子目录。
7.pg_logical:包含用于逻辑复制的状态数据的子目录。
8.pg_multixact:包含多事务状态数据的子目录(用户共享的行锁)。
9.pg_notify:包含LISTEN/NOTIFY状态数据的子目录。
10.pg_repslot:包含复制槽数据的子目录。
11.pg_serial:包含已提交的可序列化事务信息的子目录。
12.pg_snapshots:包含到处的快照的子目录。
13.pg_stat:包含用于统计子系统的永久文件的子目录。
14.pg_stat_tmp:包含用于统计信息子系统临时文件的子目录。
15.pg_subtrans:包含子事务状态数据的子目录。
16.pg_tblspc:包含指向表空间的符号链接的子目录。
17.pg_twophase:用于预备事务状态文件的子目录。
18.pg_wal:保存预写日志。
19.pg_xact:记录事务提交状态数据。