- PostgreSQL介绍
- 深入解析PostgreSQL的数据类型
- JavaScript在PostgreSQL中创建和应用存储过程
- PostgreSQL 从零到精通学习大纲
- PostgreSQL 概述
- PostgreSQL 安装部署
- 客户端工具与基本使用
- PostgreSQL 核心架构
- SQL 基础 - DDL 数据定义语言
- SQL 基础 - DML 数据操作语言
- 高级查询与数据分析
- PostgreSQL 数据类型详解
- 高级数据类型应用实战
- 数据库设计理论 - 规范化与反规范化
- 索引设计与优化策略
PostgreSQL 核心架构
class postgresql,数据库一、PostgreSQL 整体架构概述
PostgreSQL 采用经典的 C/S 架构(客户端/服务器),是一个进程架构的数据库系统(区别于 MySQL 的线程架构)。当客户端发起连接请求时,Postmaster 主进程会 fork 出一个独立的 backend 进程来服务该连接。

二、进程架构详解
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 进程的生命周期:
- Postmaster 接收连接请求
- 完成认证和权限检查
- Fork 新的 Backend 进程
- 进程处理该连接的所有 SQL 请求
- 客户端断开后,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_delaybgwriter_lru_maxpages |
| WAL Writer | 将 WAL 缓冲区写入 WAL 文件 | wal_writer_delay |
| Checkpointer | 执行检查点操作 | checkpoint_timeoutcheckpoint_completion_target |
| AutoVacuum Launcher | 自动清理的调度进程 | autovacuumautovacuum_naptime |
| AutoVacuum Worker | 执行具体的清理任务 | autovacuum_max_workers |
| Stats Collector | 收集数据库统计信息 | track_countstrack_activities |
| Logger | 处理系统日志 | logging_collector |
| Archiver | WAL 日志归档(可选) | archive_modearchive_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 扩展 | 空间数据处理 |
评论区
评论列表