暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

《课程笔记 | PostgreSQL深入浅出》之核心体系架构-内存与进程(五)

原创 布衣&凡尘 2022-09-15
1450

一、进程结构

image.png

数据库启动的时候会先启动一个叫 Postmaster 的守护进程;
该进程启动后会 fock 出多个子进程,他们各自负责一部分功能。
常见的子进程包含:Logger,BgWriter,WALWriter,PgArch,PgStat。

二、内存结构

PostgreSQL 的内存分为两大类:本地内存和共享内存,另外还有一些为辅助进程分配的内存等。

共享内存: PostgreSQL启动后会分配一块共享内存;由所有的后端进程共同使用,主要包含以下三部分:

  1. shard buffer pool:提升读写性能的数据块缓冲区(shard buffer pool),将我们的表,索引中的页面从磁盘加载到这里,以便提升访问效率。
  2. WAL buffer:这部分是日志缓冲区,也就是WAL日志持久化之前在内存中存放的位置。
  3. CLOG(CommitLog buffer)缓冲区:存放一些诸如进程信息,锁信息,全局统计信息等事务状态的信息会存放在这里,供整个事务处理的过程中使用。

本地内存
本地内存就是每个后端服务进程分配给自己使用的内存,当后端服务进程被fork时,每个后端进程为查询分配一个本地内存区域。本地内存包含三部分:work_mem、maintenance_work_mem和temp_buffers。
work_mem: 这部分是要使用做排序和Hash join的使用。
maintenance_work_mem: 主要是维护操作,例如vacuum,reindex,create index等会用到这部分内存。
temp_fuffer: 用于数据库会话访问临时表数据,系统默认值为8M。可以在单独的session中对该参数进行设置。

三、主进程:postmast

主进程Postmaster是整个数据库实例的总控进程,也是 postgresql 的第一个进程,负责启动和关闭该数据库实例。我们可以通过运行postmaster、postgres命令并加上适当的参数对数据库进行操作。当我们运行 pg_ctl也是调用postgres命令来管理数据库的;

实际上 postmaster命令指向的就是 postgres 的软连接,见如下:
image.png

查看进程:postmast

ps -axjf |grep postgres | grep -v su |grep -v grep

image.png

select pid,client_addr,client_port,backend_type from pg_stat_activity ;

image.png

四、Logger(logging colloector):日志收集进程

通过 postmaster forck 出来的几个核心主进程;首先我们来介绍第一个进程:Logger
Logger(logging colloector):日志收集进程,将运行日志,错误日志写入到日志文件进程;该进程的策略受 logging_collector参数控制,默认是 on,也可以设置 off 关闭。pg 的日志管理类似于 Linux 系统的logrotate日志分割功能,受 log_rotation_age 和 log_rotation_size控制log_directory 和log_filename是指定日志文件存放的路径及文件格式。

相关参数介绍:

是否将日志重定向至文件中,默认是off(该配置修改后,需要重启DB服务),启动之后查看进程ps -ef|grep postgres,会多一个logger进程。

postgres=# show logging_collector; logging_collector ------------------- off (1 行记录)

单个日志文件的生存期,默认1天,在日志文件大小没有达到log_rotation_size时,一天只生成一个日志文件

postgres=# show log_rotation_age;
 log_rotation_age
------------------
 1d
(1 行记录)

单个日志文件的大小,如果时间没有超过log_rotation_age,一个日志文件默认最大只能到10M,否则将新生成一个日志文件。

postgres=# show log_rotation_size;
 log_rotation_size
-------------------
 10MB
(1 行记录)

日志文件目录,默认是PGDATA的相对路径,即PGDATA的相对路径,即{PGDATA}/log,也可以改为绝对路径,可以定义在其他目录或者分区,但是必须先创建此目录,并赋权限。

postgres=# show log_directory;
 log_directory
---------------
 log
(1 行记录)

日志文件命名格式,可以灵活配置

postgres=# show log_filename;
          log_filename
--------------------------------
 postgresql-%Y-%m-%d_%H%M%S.log
(1 行记录)

日志时区,最好和服务器设置同一个时区,方便问题定位

postgres=# show log_timezone;
 log_timezone
---------------
 Asia/Shanghai
(1 行记录)

当日志文件已存在时,该配置如果为off,新生成的日志将在文件尾部追加,如果为on,则会覆盖原来的日志。

postgres=# show log_truncate_on_rotation;
 log_truncate_on_rotation
--------------------------
 off
(1 行记录)

备注:参数修改方法如下,跟Oracle修改参数的方法是一样的:值需要加引号

alter system set logging_collector = 'on';

五、BgWrite后台写进程介绍

通过 postmaster forck 出来的几个核心主进程;另一个进程:BgWrite

BgWriter: 是将内存中的脏页定期写到磁盘上的进程,大部分时间是休眠状态。受 bgwriter_开头的参数控制;可以通过pg_stat_bgwriter视图查看。可以通过参数Bgwriter_delay,Bgwriter_lru_maxpages,Bgwriter_lru_multiplier,bgwriter_flush_after控制。

每次执行bgwriter的间隔时间200ms,休息避免阻塞用户线程

postgres=# show Bgwriter_delay;

bgwriter_delay
----------------
 200ms
(1 行记录)

每次执行bgwriter,刷新缓存的最大数目100page, 一旦达到这个数量,bgwriter就结束任务开始休息,也就是说bgwriter休眠200毫秒,然后写入几十毫秒就又开始了休息;

postgres=# show Bgwriter_lru_maxpages;
 bgwriter_lru_maxpages
-----------------------
 100
(1 行记录)

一个bgwriter工作周期内, 最多刷出多少个dirty page。0会禁用bgwriter,
默认缓存数是2

postgres=# show Bgwriter_lru_multiplier;
 bgwriter_lru_multiplier
-------------------------
 2
(1 行记录)

bgwriter时不时的触发OS写脏页,目的是让OS层别累积太多dirty page才去刷脏. 避免大的IO写盘动作影响|争抢用户的IO。这个配置项比较特殊,如果没有附带单位,那么表示缓存的个数。如果有,表示缓存的容量。

postgres=# show bgwriter_flush_after;
 bgwriter_flush_after
----------------------
 512kB
(1 行记录)

一个视图:

select * from pg_stat_bgwriter;

image.png

视图解释:

checkpoints_timed     | 15462                       #计划检查点的发生次数,这种检查点是checkpoint_timeout参数规定的超时达到后系统启动的checkpoint;
checkpoints_req       | 148                         #非计划检查点的次数,包含手工检查点、xlog(redo日志)检查点(指当某些数据库预定的阈值达到时启动的检查点,比如WAL已经超出了max_wal_size或者checkpoint_segments,也会触发xlog ckpt)
checkpoint_write_time | 2130524730                  #检查点写入的总时长
checkpoint_sync_time  | 72082                       #检查点同步文件的总时长
buffers_checkpoint    | 174657791                   #检查点清理的脏块
buffers_clean         | 0                           #bgwriter清理的脏块数量
maxwritten_clean      | 0                           #bgwriter清理脏块的时候达到bgwriter_lru_maxpages后终止写入批处理的次数,为了防止一次批量写入太大影响数据块IO性能,bgwriter每次都有写入的限制。不过这个参数的缺省值100太小,对于负载较高的数据库,需要加大;
buffers_backend       | 24491898                    #backend清理的脏块数量
buffers_backend_fsync | 2                           #backend被迫自己调用fsync来同步数据的计数,如果这个计数器不为零,说明当时的fsync队列已经满了,存储子系统肯定出现了性能问题;
buffers_alloc         | 51275374                    #buffer分配的次数
stats_reset           | 2021-01-29 14:41:48.97647+08 #上一次RESET这些统计值的时间

六、WalWrite预写日志写日志介绍

通过 postmaster forck 出来的几个核心主进程;另一个进程:WalWrite
WALWriter(WAL writer): 是为了保证数据的完整性;定期将WAL缓冲区中的数据写入到磁盘;其核心概念是数据的修改必须在这些动完成后记录到WAL日志中,也就是描述这些修改操做的日志记录被刷到磁盘中。若是咱们遵循这个过程,咱们不须要在每次事务提交时刷数据页到磁盘,因我们知道一旦发生崩溃,咱们可使用日志回复数据库,任何尚未被应用到数据页面的改变能够根据其日志记录重作(这是前滚恢复,也被称为REDO) 。

相关参数介绍:
控制wal存储的级别。wal_level确定有多少信息被写入到WAL。默认值是replica,它添加了WAL归档信息,包括只读服务器(流复制)所需的信息。还可以将其设置为minimal,即只写入从崩溃或立即关闭中恢复所需的信息。设置为Logical允许在逻辑解码场景中完成WAL流。

postgres=# show wal_level;
 wal_level
-----------
 replica
(1 行记录)

这个参数是控制日志是否先写到磁盘。默认值为ON(先写),这意味着系统应该通过发出wal_sync_method设置的fsync指令,来确保更改确实被刷新到磁盘。虽然关闭fsync通常可以提高性能,但在电源故障或系统崩溃时,这会导致不可恢复的数据损坏。因此,只有当您可以轻松地从外部数据重新创建整个数据库时,才建议关闭fsync。

postgres=# show fsync;
 fsync
-------
 on
(1 行记录)

此参数用于配置系统是否等待WAL完全完成后再将状态信息返回给用户事务。默认值为ON,表示必须等待WAL完成后才能返回事务状态信息;配置OFF可以更快地反馈事务状态。

postgres=# show synchronous_commit;
 synchronous_commit
--------------------
 on
(1 行记录)

这个参数控制WAL写入磁盘的fsync方法。默认值是fdatasync。可用的值包括open_datasync、fdatasync、fsync_writethrough、fsync、以及open_sync.open_datasync和open_sync。

postgres=# show wal_sync_method;
 wal_sync_method
-----------------
 fdatasync
(1 行记录)

是否将整个页面写入WAL;默认是打开状态;当这个参数为打开时,PostgreSQL服务器在一个检查点之后的页面的第一次修改期间将每个页面的全部内容写到 WAL 中。这么做是因为在操作系统崩溃期间正在处理的一次页写入可能只有部分完成,从而导致在一个磁盘页面中混合有新旧数据。在崩溃后的恢复期间,通常存储在 WAL 中的行级改变数据不足以完全恢复这样一个页面。存储完整的页面映像可以保证页面被正确存储,但代价是增加了必须被写入 WAL 的数据量(因为 WAL 重放总是从一个检查点开始,所以在检查点后每个页面的第一次改变时这样做就够了。因此,一种减小全页面写开销的方法是增加检查点间隔参数值)。
这个参数的关闭会加快正常操作,但是在系统失败后可能导致不可恢复的数据损坏,或者静默的数据损坏。其风险类似于关闭fsync, 但是风险较小。并且只有在可关闭fsync的情况下才应该关闭它。

关闭这个选项并不影响用于时间点恢复(PITR)的 WAL 归档使用(见continuous-archiving)。

这个参数只能在postgresql.conf文件中或在服务器命令行上设置。默认值是on。

postgres=# show full_page_writes;
 full_page_writes
------------------
 on
(1 行记录)

用于存储WAL数据的内存空间量。这个版本系统默认值为4MB,不同版本的默认值不一样,此参数还受wal_writer_delay和commit_delay这两个参数的影响。

postgres=# show wal_buffers;
wal_buffers
-------------
 4MB
(1 行记录)

WalWriter进程的写入间隔。默认值是200毫秒。如果时间过长,可能会导致WAL缓冲区内存不足;如果时间太短,会导致WAL不断写入,增加磁盘I/O负担。

postgres=# show wal_writer_delay;
 wal_writer_delay
------------------
 200ms
(1 行记录)

写WAL 的策略, 如果最近的刷写发生在wal_writer_delay之前,并且小于wal_writer_flush_after WAL的值产生之后,那么WAL只会被写入操作系统,而不会被刷写到磁盘。 如果wal_writer_flush_after被设置为0,则WAL数据总是会被立即刷写。 如果指定值时没有单位,则以WAL块作为单位,即为XLOG_BLCKSZ字节,通常为8kB。 默认是1MB

postgres=# show wal_writer_flush_after;
 wal_writer_flush_after
------------------------
 1MB
(1 行记录)

指示在WAL buffer中存储已提交的数据的时间。默认值为0毫秒,表示没有延迟;当它被设置为非零值时,在事务提交后,事务将不会被立即写入到WAL中,但它仍然存储在WAL buffer中,等待WalWriter进程定期写入磁盘。

postgres=# show commit_delay;
 commit_delay
--------------
 0
(1 行记录)

当事务发出提交请求时,如果数据库中的事务数量大于commit_sibling的值,事务将等待一段时间(commit_delay值);否则,事务将直接写入到WAL。系统默认值是5,这个参数还确定了commit_delay的有效性。

postgres=# show commit_siblings;
 commit_siblings
-----------------
 5
(1 行记录)

七、Auto Vacuum自动清理进程

Vacuum(AutoAcuum):vacuum是update,delete等语句commit完成后的历史版本回收进程;将这些update,delete的行重新标记成可以使用并且释放空间;因为频繁的清理更新和删除动作带来的副本数据,也叫做多版本中的历史版本,会带来严重的性能问题;所以合并这些操作产生的历史记录通过 vacuum 同一定时的清理是有利的。这个过程称为autovacuum。

是否启动系统自动清理功能,默认值为on。

postgres=# show autovacuum;
 autovacuum
------------
 on
(1 行记录)

这个参数用来记录 autovacuum 的执行时间,当 autovaccum 的执行时间超过 log_autovacuum_min_duration参数设置时,则autovacuum信息记录到日志里,默认为 “-1”, 表示不记录。

postgres=# show log_autovacuum_min_duration;
 log_autovacuum_min_duration
-----------------------------
 -1
(1 行记录)

设置系统自动清理工作进程的最大数量,建议值为CPU核数/3。CPU资源充足,I/O性能较好时,可以适当加大。

postgres=# show autovacuum_max_workers;
 autovacuum_max_workers
------------------------
 3
(1 行记录)

设置两次系统自动清理操作之间的间隔时间。

postgres=# show autovacuum_naptime;
 autovacuum_naptime
--------------------
 1min
(1 行记录)

autovacuum_vacuum_threshold和autovacuum_analyze_threshold:设置当表上被更新的元组数的阈值超过这些阈值时分别需要执行vacuum和analyze。

postgres=# show autovacuum_vacuum_threshold;
 autovacuum_vacuum_threshold
-----------------------------
 50
(1 行记录)
postgres=# show autovacuum_analyze_threshold;
 autovacuum_analyze_threshold
------------------------------
 50
(1 行记录)

autovacuum_vacuum_scale_factor和autovacuum_analyze_scale_factor:设置表大小的缩放系数。

postgres=# show autovacuum_vacuum_scale_factor;
 autovacuum_vacuum_scale_factor
--------------------------------
 0.2
(1 行记录)

postgres=# show autovacuum_analyze_scale_factor;
 autovacuum_analyze_scale_factor
---------------------------------
 0.1
(1 行记录)

设置需要强制对数据库进行清理的XID上限值。

postgres=# show autovacuum_freeze_max_age;
 autovacuum_freeze_max_age
---------------------------
 200000000
(1 行记录)

postgres=# show autovacuum_multixact_freeze_max_age;
 autovacuum_multixact_freeze_max_age
-------------------------------------
 400000000
(1 行记录)

postgres=# show autovacuum_multixact_freeze_max_age;
 autovacuum_multixact_freeze_max_age
-------------------------------------
 400000000
(1 行记录)

当autovacuum进程即将执行时,对 vacuum 执行 cost 进行评估,如果超过 autovacuum_vacuum_cost_limit设置值时,则延迟,这个延迟的时间即为 autovacuum_vacuum_cost_delay。如果值为 -1, 表示使用 vacuum_cost_delay 值,默认值为 20 ms。

postgres=# show autovacuum_vacuum_cost_delay;
 autovacuum_vacuum_cost_delay
------------------------------
 2ms
(1 行记录)

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

postgres=# show autovacuum_vacuum_cost_limit;
 autovacuum_vacuum_cost_limit
------------------------------
 -1
(1 行记录)

autovacuum会在两种情况下会被触发:

1、当update,delete的tuples数量超过 autovacuum_vacuum_scale_factor * table_size + autovacuum_vacuum_threshold
2、指定表上事务的最大年龄配置参数autovacuum_freeze_max_age,默认为2亿,达到这个阀值将触发 autovacuum进程,从而避免 wraparound。

建议:

1、autovacuum_max_workers的建议值为CPU核数/3。CPU资源充足,I/O性能较好时,可以适当加大。
2、对于更新频繁的交易系统,如果系统资源充足,可以缩小autovacuum_vacuum_scale_factor 与 autovacuum_vacuum_threshold,让vacuum清理频繁

更改系统的 autovacuum 相关参数方法:

ALTER SYSTEM SET autovacuum_vacuum_scale_factor = 0.1;

修改参数后执行如下重新加载让参数生效:

select pg_reload_conf ();

更改单表的autovacuum相关参数:

alter table tableA set (autovacuum_vacuum_scale_factor=0.1);

VACUUM 是 PostgreSQL 里面最重要的概念之一;

八、PgStat统计信息收集进程介绍

PgStat(statistics collector): 统计信息收集进程。主要用于查询优化时的代价估算,这些信息包含表,索引上进行的增,删,改更操作的统计信息,以及磁盘 IO ,数据行的读写次数等。这些信息存储在视图pg_statistic中。可以通过trank_开头参数的参数控制。包含track_activities,track_counts,track_io_timing,track_functions,track_activity_query_size ,stats_temp_directory这些参数。

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

postgres=# show track_activities;
 track_activities
------------------
 on
(1 行记录)

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

postgres=# show track_counts;
 track_counts
--------------
 on
(1 行记录)

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

postgres=# show track_io_timing;
 track_io_timing
-----------------
 off
(1 行记录)

表示是否开启函数的调用次数和调用耗时统计,默认是nong 为禁用;可以配置指定pl只跟踪过程语言函数,指定all还会跟踪 SQL 和 C 语言函数。

postgres=# show track_functions;
 track_functions
-----------------
 none
(1 行记录)

设置用于跟踪每一个活动会话的当前执行命令的字节数,默认值为1kb,只能在数据库启动后设置。

postgres=# show track_activity_query_size;
 track_activity_query_size
---------------------------
 1kB
(1 行记录)

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

postgres=# show stats_temp_directory;
 stats_temp_directory
----------------------
 pg_stat_tmp
(1 行记录)

                         文章推荐

PostgreSQL URL
《课程笔记:PostgreSQL深入浅出》之 初识PostgreSQL(一) https://www.modb.pro/db/475817
《课程笔记:PostgreSQL深入浅出》之 PostgreSQL源码安装(二) https://www.modb.pro/db/475933
《课程笔记:PostgreSQL深入浅出》之初始化PostgreSQL(三) https://www.modb.pro/db/479524
《课程笔记:PostgreSQL深入浅出》之PSQL管理工具-常用(四) https://www.modb.pro/db/479560
《课程笔记:PostgreSQL深入浅出》之PSQL管理工具-高级命令(四) https://www.modb.pro/db/479559
《课程笔记:PostgreSQL深入浅出》之内存与进程(五) https://www.modb.pro/db/489936
《《课程笔记:PostgreSQL深入浅出》之外存&永久存储(六) https://www.modb.pro/db/502267
Oracle: URL
《Oracle 自动收集统计信息机制》 https://www.modb.pro/db/403670
《Oracle_索引重建—优化索引碎片》 https://www.modb.pro/db/399543
《DBA_TAB_MODIFICATIONS表的刷新策略测试》 https://www.modb.pro/db/414692
《FY_Recover_Data.dbf》 https://www.modb.pro/doc/74682
《Oracle RAC 集群迁移文件操作.pdf》 https://www.modb.pro/doc/72985
《Oracle Date 字段索引使用测试.dbf》 https://www.modb.pro/doc/72521
《Oracle 诊断案例 :因应用死循环导致的CPU过高》 https://www.modb.pro/db/483047
《Oracle 慢SQL监控脚本》 https://www.modb.pro/db/479620
《Oracle 慢SQL监控测试及监控脚本.pdf》 https://www.modb.pro/doc/76068
《Oracle 脚本实现简单的审计功能》 https://www.modb.pro/db/450052
Greenplum: URL
《PL/Java.pdf》 https://www.modb.pro/doc/70867
《GP的资源队列.pdf》 https://www.modb.pro/doc/67644
《Greenplum psql客户端免交互执行SQL.pdf》 https://www.modb.pro/doc/69806
                       欢迎赞赏支持或留言指正
最后修改时间:2022-09-27 21:28:28
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论