PostgreSQL进程及内存架构

1,043 阅读6分钟

进程架构

postgres主进程

启动PG数据库时,会先启动一个postmaterf的主进程,并且会fork出一些辅助的子进程,Postmaster是整个数据库实例的总控进程,负责启动和关闭数据库实例。postmaster命令是一个指向postgres的链接,所以主进程postmaster实际上是第一个postgres进程。

[postgres@VM-0-11-centos bin]$ ls /opt/pgsql/bin/postmaster -l
lrwxrwxrwx 1 postgres postgres 8 Sep  1  2020 /opt/pgsql/bin/postmaster -> postgres

pg12.2启动后的进程如下:

postgres 22512     1  0 23:05 ?        00:00:00 /opt/pgsql/bin/postgres -D ./data
postgres 22513 22512  0 23:05 ?        00:00:00 postgres: logger
postgres 22515 22512  0 23:05 ?        00:00:00 postgres: checkpointer
postgres 22516 22512  0 23:05 ?        00:00:00 postgres: background writer
postgres 22517 22512  0 23:05 ?        00:00:00 postgres: walwriter
postgres 22518 22512  0 23:05 ?        00:00:00 postgres: autovacuum launcher
postgres 22519 22512  0 23:05 ?        00:00:00 postgres: archiver
postgres 22520 22512  0 23:05 ?        00:00:00 postgres: stats collector
postgres 22521 22512  0 23:05 ?        00:00:00 postgres: logical replication launcher

当客户端与数据库库建立连接时,客户端程序发送身份验证信息给postgres主进程,postgres主进程根据消息中的信息进行客户端身份验证。若验证成功,则fork出一个子进程未该连接提供服务。通过执行"select * from pg_stat_activity;"可以查看连接情况。

和线程架构的MySQL不同,PostgreSQL数据库为进程架构模型,每一个连接都会启动一个服务进程为该连接服务。

当某个服务进程出现错误时,postgres主进程会自动完成系统恢复。恢复过程会停掉所有服务进程,然后进行数据库数据的一致性恢复。

Logger系统日志进程

本进程负责将错误消息写入日志文件,只有在logging_collect设置为on时,会启动logger辅助进程。

logger通过主进程、所有服务进程及辅助进程收集所有stderr输出,当一个日志文件达到配置的大小或其他条件时,logger会关闭旧的日志文件,并创建新的日志文件。如果收到加载配置文件的信号(SIGHUP),会检查配置文件中的配置参数log_directory和log_filename与当前配置是否相同,如果不相同会切换日志文件并使用新的配置。

BgWriter后台写进程(background writer)

本进程负责将共享缓冲池中的脏页逐渐刷入持久化存储中(例如,HDD,SSD)(在9.1及更旧版本中,它还负责处理检查点(checkpoint)

BgWriter辅助进程将共享内存中的脏页写到磁盘上。可周期性的将内存中的脏数据刷新到磁盘,这个频率不能太快也不能太慢,若太快且一个数据块被改变多次,会导致I/O次数增多; 若太慢,若有新的查询或更新需要内存保存从磁盘读取的数据块时,由于没有空闲空间存储这些数据块,那么就需要将内存中的脏页落盘,这会增加查询或更新的时间,降低性能。

同时,因为bgwriter预先写出了一些脏页面,可以减少checkpoint时要进行的io操作, 使系统的IO负载趋于平稳。

WalWriter预写式日志

本进程周期性地将WAL缓冲区中的WAL数据刷入持久存储中。

预写式日志(wal)在修改数据前必须把先这些修改操作记录到磁盘。所以在后续更新数据时不用实时地把数据持久化到文件中。

Archiver归档进程

本进程负责将日志归档。

由于wal日志循环使用,之前的wal日志会被覆盖,所以归档进程会在覆盖前将wal日志备份。

AutoVaccum launcher自动清理进程

周期性地启动自动清理工作进程(更准确地说,它向Postgres服务器请求创建自动清理工作进程)

由于PG的"多版本",在对标进行DELETE操作后,原有数据并不会立即被删除,在更新数据时,也并不会在原有数据更新,而是会新生成一行数据。原有数据被标识为删除状态,当没有并发的其他操作读取这些旧数据时,有AutoVacuum launcher自动清除这些旧数据。

Stats Collector统计数据收集进程

本进程负责收集统计信息,收集的信息主要用于查询优化时的代价估算。这些信息包括在一个表和索引上进行了多少次插入、更新、删除操作,磁盘块读写的次数以及行的读次数。系统表pg_statistic中存储了其收集的各类统计信息。

Checkpointer检查点进程

该进程负责处理检查点,将缓存中的脏数据写入到磁盘。

Checkpointer和BgWriter区别

checkpointer以特定的时间间隔刷新所有脏页,并创建检查点用于数据恢复。Bgwriter是在检查点之间刷新一些脏页面,以便始终有足够多的干净页面可以使用,提高数据查询性能。

内存架构

PostgreSQL的内存架构分为两部分:

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

共享内存

PostgreSQL服务器启动时会分配共享内存区域。共享内存主要用作数据块的缓冲区,以便提高读写性能。该区域分为几个子区域

  • shared buffer pool:PostgreSQL将表和索引中的页面从持久存储加载至此,并直接操作它们。
  • WAL buffer:为确保服务故障不会导致任何数据丢失,PostgreSQL实现了WAL机制。 WAL数据(也称为XLOG记录)是PostgreSQL中的事务日志;WAL缓冲区是WAL数据在写入持久存储之前的缓冲区。
  • commit log:提交日志(Commit Log, CLOG)为并发控制(CC)机制保存了所需的所有事务状态(例如进行中,已提交,已中止等)。 除此之外,一些全局信息也保存在共享内存中,后台进程信息(例如checkpointerautovacuum)、锁的信息(例如信号量,轻量级锁,共享和排他锁等)、事务处理(保存点(save-point) 与 两阶段提交(2PC)),以及全局统计信息等。PG9.3之后,使用mmap()方式的共享内存,所以无需配置kernel.shmmax和kernel.shmall这些System V共享内存的内核参数,就能使用较大内存。

本地内存

每个后端进程会分配一块本地内存区域用于查询处理,以便暂存一些不需要全局存储的数据,主要有以下几个:

  • 临时缓冲区(temp_buffers) :用于访问临时表的本地缓冲区。
  • work_mem:执行器在执行ORDER BYDISTINCT时使用该区域对元组做排序,以及存储归并连接和散列连接中的连接表(内部排序和hash表在使用临时磁盘文件之前使用的内存缓冲区)。
  • maintenance_work_mem:某些类型的维护操作使用该区域(例如VACUUMREINDEXCREATE INDEXALTER TABLE ADD FOREIGN KEY等)。

参考《PostgreSQL修炼之道 从小工到专家 第2版》

参考《PostgreSQL指南:内幕探索》