【一文搞懂PGSQL】3.进程和关键文件介绍

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云原生内存数据库 Tair,内存型 2GB
简介: PostgreSQL采用C/S模型,拥有多种关键进程,如PM(连接管理)、SP(会话)、SysLogger(系统日志)、BgWriter(后台写)、WALWriter(预写式日志)、PgArch(归档)、AutoVacuum(自动清理)、PgStat(统计收集)和CheckPoint(检查点)。其中,PM负责连接管理,SP处理用户会话,SysLogger记录系统日志(需在`postgresql.conf`中启用),BgWriter负责脏页写盘,WALWriter处理预写式日志,PgArch负责WAL日志归

体系结构

C/S结构

PostgreSQL 是典型的 C/S 模型的关系型数据库。

进程简介

  • PM(连接)进程

postmaster进程,提供监听、连接协议、验证功能,fork其他进程。监听哪个IP是受到postgresql.conf影响的。默认提供sockte和TCP/IP方式连接。

  • SP(会话)进程

Session Processors,会话进程。用户验证成功就会fork一个新的进程。

  • SysLogger(系统日志)进程

需要在Postgres.conf 中 logging_collection设置为on,此使主进程才会启动Syslogger辅助进程。

  • BgWriter(后台写)进程

把共享内存中的脏页写到磁盘上的进程。主要是为了提高插入、更新和删除数据的性能。

  • WALWrite(预写式日志)进程

Write Ahead Log (预写式日志),在修改数据之前把修改操作记录到磁盘中,以便后面更新实时数据时不需要数据持久化到文件中。

  • PgArch(归档)进程

WAL日志会被循环使用,PgArch在归档前会把WAL日志备份出来。通过PITY (Pointin Time Recovery)技术,可以对数据库进行一次全量备份后,该技术将备份时间点之后的WAL日志通过归档进行备份,使用数据库的全量备份再加上后面产生的WAL日志,即可把数据库向前推到全量备份后的任意一个时间点。

  • AutoVacuum(系统自动清理)进程

在PostgreSQL数据库中,对表进行DELETE操作后,旧的数据并不会立即被删除,并且,在更新数据时,也并不会在旧的数据上做更新,而是新生成一行数据。

旧的数据只是被标识为删除状态,只有在没有并发的其他事务读到这些旧数据时,他们才会被清除。这个清除工作就由AutoVacuum进程完成。

  • Pgstat(统计收集)进程

做数据的统计收集工作。主要用于查询优化时的代价估算,包括一个表和索引进行了多少次的插入、更新、删除操作。磁盘块读写的次数、行的读次数。pg_statistic中存储了PgStat收集的各类信息。

  • CheckPoint(检查点)进程

checkpoint又名检查点,一般checkpoint会将某个时间点之前的脏数据全本刷新到磁盘,以实现数据的一致性与完整性。目前各个流行的关系型数据库都具备checkpoint功能,其主要目的是为了缩短崩溃恢复时间,以Oracle为例,在进行数据恢复时,会以最近的Checkpoint为参考点执行事务前滚。而在WAL机制的浅析中,也提过PostgreSQL在崩溃恢复时会以最近的Checkpoint为基础,不断应用之后的WAL日志。

  • control 文件

记录了pg服务器内部的信息,如最新检查点时间、服务器状态、WAL文件位置,总之和数据库可能损坏相关的信息这里都有维护,还包括LC_CTYPE/LC_COLLATE等信息,和oracle控制文件差不多的。如果该文件被删除,实例将无法启动。运行时,会在共享内存中维护一份pg_control的镜像。

关键文件介绍

日志文件种类

  • $PGDATA/log 运行日志(pg10之前为$PGDATA/pg_log)

  • PGDATA/pg_wal 重做日志(pg10之前为$PGDATA/pg_xlog)

  • PGDATA/pg_xact 事务提交日志(pg10之前为$PGDATA/pg_clog)

  • 服务器日志,可以在启动的时候指定,比如pg_ctl start -l ./alert.log

运行日志参数

参数 简介
log_destination = 'csvlog' 日志输出到哪 stderr, csvlog, syslog, and eventlog四选一,默认stderr
logging_collector = on 开启关闭日志 默认为off / 需要重启
log_directory = 'log' 该参数是配置日志的目录,可以是绝对目录,也可以是相对目录
log_file_mode = 0600 日志文件的权限,默认是600也不用更改
logfilename = 'postgresql-%Y-%m-%d%H%M%S.log' 该参数是配置log的名字,一般用这个就行了,不用修改
log_truncate_on_rotation = off 当日志文件轮转时,名字已存在时,该配置如果为off,新生成的日志将在文件尾部追加,如果为on,则会覆盖原来的日志。同时也需要注意该参数只是针对时间到期的切换,如果是因为大小或者系统重启发生切换时,并不会覆盖已有的文件。
log_rotation_age = 1d 单个日志文件的生命周期,默认1天,在日志文件大小没有达到log_rotation_size时,一天只生成一个日志文件
log_rotation_size = 10MB 单个日志文件的大小,如果时间没有超过log_rotation_age,一个日志文件最大只能到10M,否则将新生成一个日志文件。
log_min_messages=warning 控制PG 系统日志级别,log_min_error_statement 要大于等于 log_min_messages 时,SQL语句才会被记录(默认ERROR,足够)。默认是WARNING。
log_min_duration_statement = -1 -1 表示不可用记录任何慢查0 将记录所有SQL语句和它们的耗时 大于0时比如N,单位是ms,表示系统会记录 耗时大于等于N ms的SQL语句
log_checkpoints = on 记录发生检查点的日志
log_connections = off 记录客户端会话连接操作
log_disconnections = off 记录客户断开的日志
log_duration = off 记录每条SQL语句执行完成消耗的时间,将此配置设置为on,用于统计哪些SQL语句耗时较长。开启该参数会消耗IO性能,如果客户端使用扩展查询协议,则会记录解析、绑定、执行三个阶段的时间。
log_lock_waits = off 控制会话等待时间超过 deadlock_timeout而被锁时是否产生一个日志信息。在判断一个锁等待是否会影响性能时是有用的,缺省是off。
log_statement = 'ddl' 控制记录哪些SQL语句。none不记录,ddl 记录所有数据定义命令,比如CREATE,ALTER,和DROP 语句。mod 记录所有ddl语句,加上数据修改语句INSERT,UPDATE等,all记录所有执行的语句,将此配置设置为all可跟踪整个数据库执行的SQL语句。

CSV日志入库存储

-- 创建日志存储表
CREATE TABLE postgres_log
(
  log_time timestamp(3) with time zone,
  user_name text,
  database_name text,
  process_id integer,
  connection_from text,
  session_id text,
  session_line_num bigint,
  command_tag text,
  session_start_time timestamp with time zone,
  virtual_transaction_id text,
  transaction_id bigint,
  error_severity text,
  sql_state_code text,
  message text,
  detail text,
  hint text,
  internal_query text,
  internal_query_pos integer,
  context text,
  query text,
  query_pos integer,
  location text,
  application_name text,
  PRIMARY KEY (session_id, session_line_num)
);

-- 将日志导入表中
copy postgres.postgres_log from '/data/pg_log/postgresql-202-04-14_000000.csv' with csv;

postgresql.conf

参数 简介
listen_addresses = '*' 监听客户端的地址,默认是本地连接,需要需改为'*' 或者 0.0.0.0
port = 5432 pg连接端口,默认5432
max_connections = 1000 最大连接数 默认100
unix_socket_directories = '/tmp' sockte配置路径,默认 /tmp
shared_buffers 数据缓存区核心参数,建议值服务器内存的 1/4 - 1/2
maintenance_work_mem 维护工作内存。用于VACUUM、CREATE INDEX和ALTER TABLE ADD FOREIGN KEY等操作,建议 (服务器内存的 1/4)/autovacuum_max_workers
autovacuum_max_workers 设置能同时运行的最大的自动垃圾收集工作进程的数目。默认值是3。
max_worker_processes = 8 如果要使用 worker process,最多可以允许 fork多少个 worker进程
max_parallel_workers_per_gather 单条query 允许开启并行计算的worker数,默认2
wal_level = minimal 预写日志模式 11+默认是replica
wal_buffers 需重启/指定事务日志缓冲区中包含的数据块的个数,每个数据块的大小是8KB,所以默认的事务日志缓冲区的大小是8*8=64KB。
checkpoint_timeout checkpoint时间间隔
max_wal_size 控制wal的数量
min_wal_size 控制wal的数量
archive_command 开启归档
autovacuum 开启自动vacuum

控制文件

pg_controldata可以查看控制文件的内容

[postgres@test01 ~]$ pg_controldata $PGDATA
pg_control version number:            1201                # PostgreSQL 版本号
Catalog version number:               201909212           # 目录版本号
Database system identifier:           7356493727464752915 # 数据库系统标识符(DBSID)
Database cluster state:               in production       # 数据库集群状态
pg_control last modified:             Thu 11 Apr 2024 05:01:01 PM CST  # pg_control 最后修改时间
Latest checkpoint location:           0/6084AC0           # 最新检查点位置
Latest checkpoint's REDO location:    0/6084A88           # 最新检查点的 REDO 位置
Latest checkpoint's REDO WAL file:    000000010000000000000006  # 最新检查点的 REDO WAL 文件
Latest checkpoint's TimeLineID:       1      # 最新检查点的时间线 ID
Latest checkpoint's PrevTimeLineID:   1      # 最新检查点的上一个时间线 ID
Latest checkpoint's full_page_writes: on     # 最新检查点的全页写开关状态
Latest checkpoint's NextXID:          0:521  # 最新检查点的 NextXID
Latest checkpoint's NextOID:          24577  # 最新检查点的 NextOID
Latest checkpoint's NextMultiXactId:  1      # 最新检查点的 NextMultiXactId
Latest checkpoint's NextMultiOffset:  0      # 最新检查点的 NextMultiOffset
Latest checkpoint's oldestXID:        480    # 最新检查点的最旧事务 ID(oldestXID)
Latest checkpoint's oldestXID's DB:   1      # 最新检查点的最旧事务 ID 所属数据库
Latest checkpoint's oldestActiveXID:  521    # 最新检查点的最旧活跃事务 ID(oldestActiveXID)
Latest checkpoint's oldestMultiXid:   1      # 最新检查点的最旧多版本事务 ID(oldestMultiXid)
Latest checkpoint's oldestMulti's DB: 1      # 最新检查点的最旧多版本事务所属数据库
Latest checkpoint's oldestCommitTsXid:0      # 最新检查点的最旧提交时间戳事务 ID(oldestCommitTsXid)
Latest checkpoint's newestCommitTsXid:0      # 最新检查点的最新提交时间戳事务 ID(newestCommitTsXid)
Time of latest checkpoint:            Thu 11 Apr 2024 05:01:01 PM CST  # 最新检查点时间
Fake LSN counter for unlogged rels:   0/3E8  # 未记录关系的虚拟 LSN 计数器
Minimum recovery ending location:     0/0    # 最小恢复结束位置
Min recovery ending loc's timeline:   0      # 最小恢复结束位置的时间线
Backup start location:                0/0    # 备份开始位置
Backup end location:                  0/0    # 备份结束位置
End-of-backup record required:        no     # 是否需要备份结束记录
wal_level setting:                    replica  # WAL 日志级别设置
wal_log_hints setting:                on     # WAL 日志提示设置
max_connections setting:              2000   # 最大连接数设置
max_worker_processes setting:         8      # 最大工作进程数设置
max_wal_senders setting:              10     # 最大 WAL 发送者数设置
max_prepared_xacts setting:           0      # 最大预处理事务数设置
max_locks_per_xact setting:           64     # 每个事务的最大锁数设置
track_commit_timestamp setting:       off    # 跟踪提交时间戳设置
Maximum data alignment:               8      # 最大数据对齐大小
Database block size:                  8192   # 数据库块大小
Blocks per segment of large relation: 131072 # 大型关系的每个段的块数
WAL block size:                       8192   # WAL 块大小
Bytes per WAL segment:                16777216  # 每个 WAL 段的字节数
Maximum length of identifiers:        64     # 标识符的最大长度
Maximum columns in an index:          32     # 索引中的最大列数
Maximum size of a TOAST chunk:        1996   # TOAST 块的最大大小
Size of a large-object chunk:         2048   # 大对象块的大小
Date/time type storage:               64-bit integers  # 日期/时间类型存储方式
Float4 argument passing:              by value  # Float4 参数传递方式
Float8 argument passing:              by value  # Float8 参数传递方式
Data page checksum version:           0         # 数据页校验版本
Mock authentication nonce:            b1482276658b9aa5b638bad162d3d4fea064cbabd6889303f5d179131ad66c93  # 模拟认证 nonce

数据文件

pg中,每个索引和表都是一个单独的文件,pg中叫做page。默认是每个大于1G的page会被分割 pg_class.relfilenode.1这样的文件。page的的大小在initdb的时候指定 (--with.segsize)。

page物理位置

page的物理位置在 $PGDATA/BASE/DATABASE_OID/PG_CLASS.RELFILENODE

# 查看t1 表存储在哪个物理文件
select relfilenode from pg_class where relname='t1';

# 查看t1表存储在哪个路径下的物理文件
select pg_relation_filepath('t1');

# 查看数据目录路径
show data_directory;

# 查找文件是否存在
ll /pgdata/12/data/base/16384/16385

需要注意的是,pg_class.relfilenode类似dbaobjects.data_objectid,truncate表之后relfilenode会变。对应的物理文件名字也会变。

Online WAL 日志(redo)

关于Online WAL日志

  • 这个日志存在的目的是为了保证崩溃后的安全,如果系统崩溃,可以“重放“从最后一次检查点以来的日志项来恢复数据库的一致性。

  • 但是也存在日志膨胀的问题

设置Online WAL日志

pg提供如下參数控制wal日志的大小

max_wal_size = 1GB
min_wal_size = 80MB

max_wal_size (integerl)

在自动 WAL 检查点之间允许WAL 增长到的最大尺寸。这是一个软限制,在特殊的情况下 WAL 尺寸可能会超过max_waLsize,例如在重度负荷下、archive_command失败或者高的 wal_keep_segments设置。如果指定值时没有单位,则以兆字节为单位。默认为 1GB。增加这个参数 可能导致崩溃恢复所需的时间。这个参数只能在postgresql.conf 或者服务器命令行中设置。

min_wal_size (integer)

只要 WAL 磁盘用是保持在这个设置之下,在检查点时旧的 WAL 文件总是被回收以便未来使用,而不是直接被删除。这可以被用来确保有足够的 WAL 空间被保留来应付 WAL 使用的高峰,例如运行大型的批处理任务。如果指定估时没有单位,则以兆字节为单位。默认是80MB。这个参数只能在postgresql。conf 或者服务器命令行中设置。

wal 位置

wal在$PGDATA/pg_wal 下。10之前在pg_xlog

[postgres@pg-01 pg_wal]$ cd /pgdata/12/data/
[postgres@pg-01 data]$ cd pg_wal/
[postgres@pg-01 pg_wal]$ ll
total 16384
-rw-------. 1 postgres postgres 16777216 Apr 22 22:16 000000010000000000000001
drwx------. 2 postgres postgres        6 Apr 20 21:01 archive_status

wal 命名格式

文件名称为16进制的24个字符组成,每8个字符一组,每组的意义如下:

[postgres@pg-01 pg_wal]$ ll
-rw-------. 1 postgres postgres 16777216 Apr 22 22:16 000000010000000000000001
00000001 00000000 00000001
时间线     逻辑ID    物理ID

查看 wal 时间

postgres=# select pg_walfile_name(pg_current_wal_lsn());
     pg_walfile_name      
--------------------------
 000000010000000000000001
(1 row)

postgres=# select * from pg_ls_waldir() order by modification asc;
           name           |   size   |      modification      
--------------------------+----------+------------------------
 000000010000000000000001 | 16777216 | 2022-04-22 22:16:07+08
(1 row)

postgres=#

切换 wal 日志

postgres=# select pg_switch_wal();
 pg_switch_wal 
---------------
 0/3000000
(1 row)


postgres=# select * from pg_ls_waldir() order by modification asc;
           name           |   size   |      modification      
--------------------------+----------+------------------------
 000000010000000000000004 | 16777216 | 2022-04-22 22:54:41+08
 000000010000000000000005 | 16777216 | 2022-04-22 22:54:46+08
 000000010000000000000003 | 16777216 | 2022-04-22 22:56:03+08

pg_waldump 查看 wal 重做日志

pg_waldump 可以查看wal的具体内容

[postgres@pg-01 pg_wal]$ pg_waldump /pgdata/12/data/pg_wal/000000010000000000000003 
rmgr: Standby     len (rec/tot):     50/    50, tx:          0, lsn: 0/03000028, prev 0/02000060, desc: RUNNING_XACTS nextXid 527 latestCompletedXid 526 oldestRunningXid 527
rmgr: Standby     len (rec/tot):     50/    50, tx:          0, lsn: 0/03000060, prev 0/03000028, desc: RUNNING_XACTS nextXid 527 latestCompletedXid 526 oldestRunningXid 527
rmgr: XLOG        len (rec/tot):    114/   114, tx:          0, lsn: 0/03000098, prev 0/03000060, desc: CHECKPOINT_ONLINE redo 0/3000060; tli 1; prev tli 1; fpw true; xid 0:527; oid 16422; multi 1; offset 0; oldest xid 480 in DB 1; oldest multi 1 in DB 1; oldest/newest commit timestamp xid: 0/0; oldest running xid 527; online
rmgr: Standby     len (rec/tot):     50/    50, tx:          0, lsn: 0/03000110, prev 0/03000098, desc: RUNNING_XACTS nextXid 527 latestCompletedXid 526 oldestRunningXid 527
pg_waldump: fatal: error in WAL record at 0/3000110: invalid record length at 0/3000148: wanted 24, got 0

5.8 ARCH WAL log

重做日志是几个文件轮询使用的,当这几个文件被写满之后会覆盖掉之前的数据,而我们如果想要保存这些将要被覆盖掉的日志就需要ARCH进行归档。在数据库发生故障后可以将归档日志应用到数据库中进行数据恢复。

// wal_level = replica # pg11+ 默认开启replica
该参数的可选的值有minimal, replica和nlogical, wal的级别依次增高,在wal的信息也越多。由于minimal这一级别的wal不包含从基础的备份和wal日志重建数据的足够信息,在该模式下,无法开启wal日志归档。

// archive_mode = on # 开启归档
上述参数为on,表示打开归档备份,可选的参数为on,off,always 认值为off,所以要手动打开。

// archive. command = ’test !-f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f‘
该参数的默认信是—个空字符串,他的值可以是一条shell命令或者一个复杂的shell脚本.在shell脚本或命令中可以用"%p"表示将要归档的wal文件包含完整路径的信息的文件名,用"%f代表不包含路径信息的wal文件的文件名。
注意:wal_level和archive_mode参数修改都需要重新启动数据库才可以生效。而修改 archive_command 则不需要。所以一般配置新系统时,无论当时是否需要归档,都建议将这两个参数开启。

配置参数

# 开启归档
archive_mode = on

# 指定归档日志级别
wal_level = replica 

# 选择归档路径
archive_command = 'test ! -f /archive/%f && cp %p /archive/%f'

重启数据库

pg_ctl restart

切换日志

select pg_switch_wal();

# 查看归档文件
[postgres@pg-01 archive]$ ll /archive/
total 32768
-rw------- 1 postgres postgres 16777216 Apr 22 23:47 000000010000000000000003
-rw------- 1 postgres postgres 16777216 Apr 22 23:47 000000010000000000000004

归档的作用是防止数据库删除过期的 wal 日志,可以在数据库出现问题后使用归档的 wal 恢复数据。

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
3月前
|
存储 分布式数据库 API
技术好文:VisualC++查看文件被哪个进程占用
技术好文:VisualC++查看文件被哪个进程占用
|
24天前
|
NoSQL Redis
Redis AOFRW主进程问题之更新manifest文件如何解决
Redis AOFRW主进程问题之更新manifest文件如何解决
|
24天前
|
NoSQL 分布式数据库 Redis
Redis 进程问题之主进程更新manifest文件如何解决
Redis 进程问题之主进程更新manifest文件如何解决
|
22天前
|
Linux
在Linux中,如何查看某进程所打开的所有文件?
在Linux中,如何查看某进程所打开的所有文件?
|
2月前
|
JavaScript 前端开发 API
Chrome插件实现问题之 content_script.js能做什么
Chrome插件实现问题之 content_script.js能做什么
|
2月前
|
小程序 Linux
【编程小实验】利用Linux fork()与文件I/O:父进程与子进程协同实现高效cp命令(前半文件与后半文件并行复制)
这个小程序是在文件IO的基础上去结合父子进程的一个使用,利用父子进程相互独立的特点实现对数据不同的操作
|
3月前
|
Python Windows
在 Windows 平台下打包 Python 多进程代码为 exe 文件的问题及解决方案
在使用 Python 进行多进程编程时,在 Windows 平台下可能会出现将代码打包为 exe 文件后无法正常运行的问题。这个问题主要是由于在 Windows 下创建新的进程需要复制父进程的内存空间,而 Python 多进程机制需要先完成父进程的初始化阶段后才能启动子进程,所以在这个过程中可能会出现错误。此外,由于没有显式导入 Python 解释器,也会导致 Python 解释器无法正常工作。为了解决这个问题,我们可以使用函数。
54 5
|
2月前
|
Linux
c创建压缩文件,用于压缩模式,-v显示压缩进程,-x解压模式,-f创建的文件,解压文件,tar -cvf
c创建压缩文件,用于压缩模式,-v显示压缩进程,-x解压模式,-f创建的文件,解压文件,tar -cvf
有 3 个进程 P1、P2、P3 协作解决文件打印问题。P1 将文件记录从磁盘读入内存的缓冲区 1,每执行一次读一个记录 ;P2 将缓冲区 1 中的内容复制到缓冲区 2 中,每执行一次复制一个记录 ;
有 3 个进程 P1、P2、P3 协作解决文件打印问题。P1 将文件记录从磁盘读入内存的缓冲区 1,每执行一次读一个记录 ;P2 将缓冲区 1 中的内容复制到缓冲区 2 中,每执行一次复制一个记录 ;
|
2月前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能