PostgreSQL 核心架构

person 落叶    watch_later 2026-04-18 14:33:58
visibility 8    class postgresql,数据库    bookmark 专栏

一、PostgreSQL 整体架构概述

PostgreSQL 采用经典的 C/S 架构(客户端/服务器),是一个进程架构的数据库系统(区别于 MySQL 的线程架构)。当客户端发起连接请求时,Postmaster 主进程会 fork 出一个独立的 backend 进程来服务该连接。

deepseek_mermaid_20260418_ab4a9e.png


二、进程架构详解

1. Postmaster 主进程

Postmaster 是 PostgreSQL 的守护进程,是整个数据库实例的"总管"。

主要职责:

  • 初始化数据库实例
  • 监听端口(默认 5432),接受客户端连接请求
  • 为每个连接 fork 一个独立的 Backend 进程
  • 管理辅助进程的启动和停止
  • 处理参数配置重载(pg_ctl reload)
# 查看 Postmaster 进程
ps aux | grep postgres

# 输出示例:
# postgres  1234  0.0  0.1  ... /usr/local/pgsql/bin/postgres
# postgres  1235  0.0  0.0  ... postgres: checkpointer
# postgres  1236  0.0  0.0  ... postgres: background writer
# postgres  1237  0.0  0.0  ... postgres: walwriter
# postgres  1238  0.0  0.0  ... postgres: autovacuum launcher
# postgres  1239  0.0  0.0  ... postgres: stats collector
# postgres  1240  0.0  0.0  ... postgres: logical replication launcher
# postgres  1300  0.0  0.0  ... postgres: user postgres [local] idle

2. Backend 服务进程

每个客户端连接对应一个独立的 Backend 进程,负责处理该连接的所有请求。

sequenceDiagram participant Client as 客户端 participant Postmaster as Postmaster participant Backend as Backend进程 participant Shared as 共享内存 Client->>Postmaster: 1. 发起连接请求 Postmaster->>Postmaster: 2. 认证检查 Postmaster->>Backend: 3. Fork新进程 Backend->>Client: 4. 连接成功 Client->>Backend: 5. 发送SQL查询 Backend->>Shared: 6. 读取/写入数据 Backend->>Client: 7. 返回结果集 Client->>Backend: 8. 断开连接 Backend->>Backend: 9. 进程退出

Backend 进程的生命周期:

  1. Postmaster 接收连接请求
  2. 完成认证和权限检查
  3. Fork 新的 Backend 进程
  4. 进程处理该连接的所有 SQL 请求
  5. 客户端断开后,Backend 进程终止
-- 查看当前活动的 Backend 进程
SELECT pid, usename, application_name, client_addr, state, query 
FROM pg_stat_activity;

-- 查看连接数统计
SELECT count(*), state FROM pg_stat_activity GROUP BY state;

3. 辅助进程

进程名称 功能描述 配置参数
Background Writer 将共享缓冲区中的脏页写入磁盘 bgwriter_delay
bgwriter_lru_maxpages
WAL Writer 将 WAL 缓冲区写入 WAL 文件 wal_writer_delay
Checkpointer 执行检查点操作 checkpoint_timeout
checkpoint_completion_target
AutoVacuum Launcher 自动清理的调度进程 autovacuum
autovacuum_naptime
AutoVacuum Worker 执行具体的清理任务 autovacuum_max_workers
Stats Collector 收集数据库统计信息 track_counts
track_activities
Logger 处理系统日志 logging_collector
Archiver WAL 日志归档(可选) archive_mode
archive_command
-- 查看辅助进程状态
SELECT pid, backend_type, wait_event_type, wait_event
FROM pg_stat_activity
WHERE backend_type LIKE '%writer%' 
   OR backend_type LIKE '%checkpointer%'
   OR backend_type LIKE '%vacuum%';

三、内存架构详解

1. 共享内存(Shared Memory)

所有 Backend 进程和辅助进程共享的内存区域,在 PostgreSQL 启动时分配。

-- 查看共享内存使用情况
SELECT name, setting, unit, short_desc 
FROM pg_settings 
WHERE name LIKE '%shared%' OR name LIKE '%buffer%';

-- 查看共享内存命中率(重要性能指标)
SELECT 
    sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) * 100 AS cache_hit_ratio
FROM pg_statio_user_tables;

共享内存组件:

组件 说明 配置
Shared Buffers 数据页缓冲区,最关键的缓存区域 shared_buffers
建议:物理内存的 15%-25%
WAL Buffers WAL 日志缓冲区 wal_buffers
建议:16-64MB
Catalog Cache 系统表缓存 自动管理
Lock Space 锁管理空间 max_locks_per_transaction

2. 本地内存(Local Memory)

每个 Backend 进程独立分配的内存,在进程 fork 时分配。

组件 说明 配置
Work Mem 排序、哈希表等操作的内存 work_mem
建议:4-64MB
Maintenance Work Mem VACUUM、CREATE INDEX 等操作的内存 maintenance_work_mem
建议:64-1024MB
Temp Buffers 临时表缓冲区 temp_buffers
建议:8-16MB
-- 查看当前会话的内存配置
SHOW work_mem;
SHOW maintenance_work_mem;
SHOW temp_buffers;

-- 设置会话级内存(临时)
SET work_mem = '128MB';
SET maintenance_work_mem = '512MB';

四、存储架构详解

1. 物理存储结构

PostgreSQL 数据目录(PGDATA)结构:

PGDATA/
├── PG_VERSION                    # PostgreSQL 版本号
├── base/                         # 数据库目录
│   ├── 1/                        # 数据库 OID=1(template0)
│   │   ├── 1247                  # 表文件(OID=1247)
│   │   ├── 1247_fsm              # 空闲空间映射
│   │   ├── 1247_vm               # 可见性映射
│   │   └── ...
│   └── 16384/                    # 数据库 OID=16384(用户数据库)
├── global/                       # 全局系统表
│   ├── pg_control                # 控制文件
│   └── pg_database               # 数据库列表
├── pg_wal/                       # WAL 日志目录
│   ├── 000000010000000000000001  # WAL 段文件(16MB)
│   └── archive_status/           # 归档状态
├── pg_xact/                      # 事务状态(Commit Log)
├── pg_subtrans/                  # 子事务状态
├── pg_multixact/                 # 多事务状态
├── pg_logical/                   # 逻辑解码数据
├── pg_replslot/                  # 复制槽
├── pg_stat_tmp/                  # 统计信息临时文件
├── pg_tblspc/                    # 表空间符号链接
├── postgresql.conf               # 主配置文件
├── postgresql.auto.conf          # 自动生成的配置(ALTER SYSTEM)
├── pg_hba.conf                   # 客户端认证配置
├── pg_ident.conf                 # 用户映射配置
└── log/                          # 日志目录(如果配置)

2. 表文件内部结构

一个表在磁盘上对应多个文件:

graph LR subgraph Table["表: users (OID=16384)"] F1[users<br/>主文件<br/>1GB] F2[users.1<br/>扩展文件1<br/>1GB] F3[users.2<br/>扩展文件2<br/>1GB] end subgraph FSM["空闲空间映射"] FSM1[users_fsm] end subgraph VM["可见性映射"] VM1[users_vm] end F1 --> FSM1 F1 --> VM1 F2 --> FSM1 F3 --> FSM1

数据文件内部结构(页结构):

┌─────────────────────────────────────┐
│            Page Header              │  24 bytes
│  pd_lsn, pd_checksum, pd_flags,    │
│  pd_lower, pd_upper, pd_special     │
├─────────────────────────────────────┤
│          Item Pointer Array         │  4 bytes × 数量
│  (偏移量, 长度, 标志)                │
├─────────────────────────────────────┤
│                                     │
│          Free Space                 │  空闲区域
│                                     │
├─────────────────────────────────────┤
│          Heap Tuple Data            │  行数据(从下往上填)
│                                     │
├─────────────────────────────────────┤
│          Special Space              │  索引等特殊用途
└─────────────────────────────────────┘
-- 查看表文件信息
SELECT 
    relname,
    relpages,           -- 页数(每页8KB)
    reltuples,          -- 估算行数
    pg_relation_size(oid) / 8192 AS actual_pages,
    pg_total_relation_size(oid) AS total_size
FROM pg_class 
WHERE relname = 'users';

-- 查看表和索引的实际大小
SELECT 
    schemaname,
    tablename,
    pg_size_pretty(pg_table_size(schemaname||'.'||tablename)) AS table_size,
    pg_size_pretty(pg_indexes_size(schemaname||'.'||tablename)) AS index_size,
    pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS total_size
FROM pg_tables
WHERE schemaname = 'public';

3. WAL(预写日志)结构

WAL(Write-Ahead Logging)是 PostgreSQL 实现 ACID 持久性的核心机制。

sequenceDiagram participant App as 应用程序 participant Backend as Backend进程 participant WALBuffer as WAL Buffer participant WALFile as WAL File participant DataFile as Data File App->>Backend: UPDATE users SET name='Bob' WHERE id=1 Backend->>WALBuffer: 1. 写WAL记录 WALBuffer->>WALFile: 2. WAL Writer刷新到磁盘 Backend->>DataFile: 3. 在Shared Buffer中修改数据页 Backend->>App: 4. 返回成功 Note over WALFile,DataFile: 检查点发生时 WALFile->>DataFile: 5. 将脏页写入数据文件

WAL 段文件命名:

00000001 00000000 00000001
│        │        │
│        │        └── 段内序号(每段16MB)
│        └─────────── Timeline ID(时间线)
└──────────────────── 日志序号(Log ID)
-- 查看 WAL 配置
SHOW wal_level;              -- replica / logical
SHOW wal_buffers;            -- WAL 缓冲区大小
SHOW wal_writer_delay;       -- WAL Writer 延迟
SHOW checkpoint_timeout;     -- 检查点超时
SHOW min_wal_size;           -- 最小 WAL 大小
SHOW max_wal_size;           -- 最大 WAL 大小

-- 查看当前 WAL 位置
SELECT pg_current_wal_lsn();
SELECT pg_walfile_name(pg_current_wal_lsn());

-- 查看 WAL 统计
SELECT * FROM pg_stat_wal;

五、查询执行流程

flowchart TD Q[客户端发送SQL] --> Parser[解析器 Parser] Parser -->|语法分析| RawParseTree[原始解析树] RawParseTree --> Analyzer[分析器 Analyzer] Analyzer -->|语义分析| QueryTree[查询树] QueryTree --> Rewriter[重写器 Rewriter] Rewriter -->|应用规则| QueryTree2[查询树+规则] QueryTree2 --> Planner[规划器 Planner] Planner -->|生成执行计划| PlanTree[计划树] PlanTree --> Executor[执行器 Executor] Executor -->|执行| AccessMethods[访问方法] AccessMethods -->|返回结果| Result[结果集]

1. 解析器(Parser)

  • 检查 SQL 语法
  • 生成原始解析树
-- 查看解析后的查询树(原始格式)
SELECT * FROM users WHERE id = 1;

2. 分析器(Analyzer)

  • 语义分析:表是否存在、列是否存在
  • 生成查询树

3. 重写器(Rewriter)

  • 应用视图规则
  • 实现规则系统
-- 创建视图后,查询视图会被重写为对基表的查询
CREATE VIEW active_users AS SELECT * FROM users WHERE status = 'active';

-- 实际执行时会被重写
SELECT * FROM active_users;
-- 重写为:SELECT * FROM users WHERE status = 'active';

4. 规划器(Planner)

  • 生成多种可能的执行计划
  • 选择代价最低的计划
-- 查看执行计划(不实际执行)
EXPLAIN SELECT * FROM users WHERE email = 'alice@example.com';

-- 查看执行计划并执行
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'alice@example.com';

-- 查看执行计划的详细信息
EXPLAIN (ANALYZE, BUFFERS, TIMING, FORMAT JSON) 
SELECT * FROM users WHERE email = 'alice@example.com';

5. 执行器(Executor)

  • 执行计划树
  • 处理表扫描、索引扫描、连接操作
  • 返回结果

六、并发控制:MVCC

PostgreSQL 使用 MVCC(多版本并发控制) 实现高并发,避免读写阻塞。

MVCC 核心原理

sequenceDiagram participant T1 as 事务1 (UPDATE) participant T2 as 事务2 (SELECT) participant Table as 数据表 Note over Table: 原始行: xmin=100, xmax=0, name='Alice' T1->>Table: UPDATE name='Bob' WHERE id=1 Note over Table: 插入新版本: xmin=101, xmax=0, name='Bob'<br/>旧版本标记: xmin=100, xmax=101, name='Alice' T2->>Table: SELECT * FROM users WHERE id=1 Note over T2: 只能看到 xmin ≤ 当前事务ID<br/>且 xmax = 0 或 xmax > 当前事务ID Table-->>T2: 返回 name='Alice'(旧版本) T1->>T1: COMMIT Note over Table: 新版本可见性生效

关键字段:

  • xmin:插入该行的事务ID
  • xmax:删除/更新该行的事务ID(0表示未删除)
  • ctid:行的物理位置
-- 查看元组头信息(需要扩展)
CREATE EXTENSION IF NOT EXISTS pageinspect;

-- 查看数据页内容
SELECT * FROM heap_page_items(get_raw_page('users', 0));

-- 查看可见性映射
SELECT * FROM pg_visibility_map('users');

事务隔离级别

隔离级别 脏读 不可重复读 幻读 PostgreSQL行为
READ UNCOMMITTED 可能 可能 可能 同 READ COMMITTED
READ COMMITTED 不可能 可能 可能 默认级别
REPEATABLE READ 不可能 不可能 可能(PG中不可能) 同 SERIALIZABLE(PG中)
SERIALIZABLE 不可能 不可能 不可能 真正的可串行化
-- 查看当前隔离级别
SHOW transaction_isolation;

-- 设置隔离级别
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

BEGIN;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT * FROM users WHERE id = 1;
COMMIT;

七、配置文件体系

1. 配置文件层次

graph TD A[postgresql.conf<br/>主配置文件] --> B[include指令] B --> C[postgresql.auto.conf<br/>ALTER SYSTEM生成的配置] B --> D[自定义配置文件<br/>*.conf] A --> E[pg_hba.conf<br/>客户端认证] A --> F[pg_ident.conf<br/>用户映射]

2. 配置参数分类

-- 查看所有配置参数
SELECT name, setting, unit, context, vartype, short_desc 
FROM pg_settings 
ORDER BY name;

-- 查看修改需要重启的参数
SELECT name, setting, context 
FROM pg_settings 
WHERE context IN ('postmaster', 'sighup');

-- 动态修改参数(不需要重启)
ALTER SYSTEM SET work_mem = '32MB';
SELECT pg_reload_conf();

-- 恢复默认值
ALTER SYSTEM RESET work_mem;

参数上下文(context)说明:

Context 说明 示例
internal 只读,编译时确定 block_size
postmaster 修改需要重启 port, shared_buffers
sighup 修改后需要 SIGHUP 信号 work_mem, logging_collector
superuser 超级用户可动态修改 statement_timeout
user 普通用户可动态修改 search_path

3. 重要配置参数速查表

分类 参数 推荐值 说明
连接 max_connections 100-500 最大连接数
内存 shared_buffers RAM 的 15%-25% 共享缓冲区
work_mem 4-64MB 排序/哈希内存
maintenance_work_mem 64-1024MB 维护操作内存
effective_cache_size RAM 的 50%-75% 操作系统缓存估算
写入 wal_buffers 16-64MB WAL 缓冲区
checkpoint_timeout 5-15min 检查点间隔
max_wal_size 1-100GB 最大 WAL 大小
查询 enable_* - 查询优化开关
default_statistics_target 100-1000 统计信息精度
日志 log_min_duration_statement 100-1000ms 慢查询阈值
log_statement ddl/mod/none 记录语句类型
清理 autovacuum on 自动清理
autovacuum_naptime 1-5min 清理检查间隔

八、架构最佳实践

1. 单机优化配置模板

# postgresql.conf 生产环境配置示例

# ============================================
# 连接设置
# ============================================
listen_addresses = '*'
port = 5432
max_connections = 300
superuser_reserved_connections = 3

# ============================================
# 内存设置(假设服务器内存32GB)
# ============================================
shared_buffers = 8GB                    # 25% of RAM
work_mem = 32MB                         # 适合复杂查询
maintenance_work_mem = 1GB              # VACUUM/INDEX 操作
effective_cache_size = 24GB             # 75% of RAM
wal_buffers = 64MB

# ============================================
# 检查点设置
# ============================================
checkpoint_timeout = 15min
checkpoint_completion_target = 0.9
max_wal_size = 32GB
min_wal_size = 8GB

# ============================================
# 日志设置
# ============================================
log_destination = 'stderr'
logging_collector = on
log_directory = '/var/log/postgresql'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_rotation_age = 1d
log_rotation_size = 100MB
log_min_duration_statement = 1000      # 记录 >1秒的查询
log_statement = 'ddl'                  # 记录 DDL 语句
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '

# ============================================
# 统计信息
# ============================================
track_activities = on
track_counts = on
track_io_timing = on
track_functions = 'pl'
track_activity_query_size = 4096

# ============================================
# 自动清理
# ============================================
autovacuum = on
autovacuum_naptime = 1min
autovacuum_vacuum_threshold = 50
autovacuum_analyze_threshold = 50
autovacuum_vacuum_scale_factor = 0.05
autovacuum_analyze_scale_factor = 0.02
autovacuum_vacuum_cost_delay = 10ms
autovacuum_max_workers = 5

# ============================================
# 查询优化器
# ============================================
random_page_cost = 1.1                 # SSD 设置较低值
effective_io_concurrency = 200
enable_partitionwise_join = on
enable_partitionwise_aggregate = on
jit = on

2. 架构选择指南

场景 推荐架构 说明
开发/测试 单机 简单部署
中小型应用 单机 + 定时备份 成本低,维护简单
高可用要求 主从流复制 故障自动切换
读密集型 一主多从 + 读写分离 提升读吞吐量
写密集型 单机 + 优化写入 或使用 Citus 分片
数据仓库 列存扩展(Citus) 分析查询优化
地理信息 PostGIS 扩展 空间数据处理
评论区
评论列表
menu