PostgreSQL 作为最先进的开源关系数据库系统,其内部实现原理体现了数据库领域的前沿设计与工程智慧。本文将深入探讨 PostgreSQL 的架构设计、存储机制、并发控制和优化器原理,并通过与 MySQL 的对比展示其独特优势

视频养活国内大半自研数据库团队的PostgreSQL是什么?

I. PostgreSQL 整体架构

PostgreSQL 采用多进程架构 (Process-based),每个客户端连接对应一个独立的服务进程。这种设计虽然比线程模型消耗更多内存,但提供了极高的隔离性和稳定性——一个查询的崩溃绝不会拖垮整个数据库。

graph TD
    Client[客户端应用] -->|TCP/IP| Postmaster[Postmaster 主守护进程]
    
    subgraph "进程模型"
        Postmaster -->|fork| Backend1[服务进程 1: Backend]
        Postmaster -->|fork| Backend2[服务进程 2: Backend]
        Postmaster -->|fork| Backend3[服务进程 3: Backend]
    end

    subgraph "共享内存区域"
        SharedBuffer[Shared Buffer<br/>共享缓冲区]
        WALBuffer[WAL Buffer<br/>日志缓冲区]
        
        Backend1 <--> SharedBuffer
        Backend2 <--> SharedBuffer
        Backend3 <--> SharedBuffer
        SharedBuffer <--> WALBuffer
    end
    
    subgraph "关键后台进程"
        BgWriter[BgWriter<br/>后台写入器]
        Checkpointer[Checkpointer<br/>检查点进程]
        WALWriter[WAL Writer<br/>日志写入器]
        Autovacuum[Autovacuum<br/>自动清理进程]
    end
    
    SharedBuffer --> BgWriter
    WALBuffer --> WALWriter
    SharedBuffer --> Checkpointer
    SharedBuffer --> Autovacuum
    
    BgWriter -->|写入脏页| Storage[持久化存储<br/>数据文件]
    WALWriter -->|写入WAL| WALStorage[WAL文件]
    Checkpointer -->|检查点| Storage
    Autovacuum -->|清理| Storage

核心组件交互流程:

  1. Postmaster:主守护进程 (PID 1 of PG),负责监听端口 (5432)、管理连接请求、恢复系统。
  2. Server Process (Backend):每个客户端连接对应一个 postgres 子进程,负责执行 SQL、排序、计算。
  3. Shared Buffer:所有进程共享的内存池,用于缓存数据页 (Page)。Postgres 依赖 OS Cache 形成双重缓存架构。
  4. 后台进程 (Background Processes)
    • BgWriter:将脏页 (Dirty Pages) 缓慢刷盘,减轻 Checkpoint 压力。
    • Checkpointer:定期执行检查点,确保数据落盘,缩短恢复时间。
    • WAL Writer:将 WAL Buffer 中的日志条目刷入磁盘。
    • Autovacuum:自动发现并清理死元组,更新统计信息。

II. 存储引擎与数据组织

PostgreSQL 的存储层设计精妙,采用 堆表 (Heap Table) 结构,并辅以多种辅助文件。

2.1 页面与元组结构 (Page & Tuple)

Postgres 的标准页面大小为 8KB

classDiagram
    class PageHeaderData {
        +uint16 pd_lower (空闲空间起始)
        +uint16 pd_upper (空闲空间结束)
        +uint16 pd_special (特殊空间起始)
    }

    class LinePointer {
        +uint32 IpId (行指针: 偏移量+长度)
    }

    class HeapTupleData {
        +uint32 t_xmin (创建事务ID)
        +uint32 t_xmax (删除事务ID)
        +ItemPointerData t_ctid (物理位置)
        +uint16 t_infomask (标志位/Hint Bits)
        +data fields[] (实际数据)
    }

    class TablePage {
        PageHeaderData header
        LinePointer[] pointers
        FreeSpace 空闲空间
        HeapTupleData[] tuples
    }

    TablePage "1" *-- "1" PageHeaderData : 包含
    TablePage "1" *-- "n" LinePointer : 从前向后生长
    TablePage "1" *-- "n" HeapTupleData : 从后向前生长

关键机制

  • 行指针 (ItemPointer):索引不直接指向数据行,而是指向 Page 里的行指针。这使得 Page 内部进行碎片整理(移动 Tuple)时,无需修改外部索引,只需更新行指针即可。
  • TOAST 机制:当行大小超过页面的 1/4 (约 2KB) 时,超长字段(如 JSONB, Text)会被压缩并切片存储到专门的 TOAST 表中,主表只留一个指针。

2.2 关键辅助文件

Postgres 除了主数据文件,还维护着两个至关重要的位图文件:

  1. FSM (Free Space Map):
    • 作用: 快速定位哪个页面有足够的空闲空间来插入新数据,避免全表扫描寻找空位。
  2. VM (Visibility Map):
    • 作用: 标记某个页面上的所有元组是否对“所有活跃事务”可见。
    • 核心优化: Index-Only Scan。如果 VM 显示页面全可见,索引扫描可以直接返回数据,无需回表 (Heap Fetch)。

III. 多版本并发控制 (MVCC)

PostgreSQL 的 MVCC 通过保留数据旧版本来实现,而不是像 MySQL (InnoDB) 那样使用 Undo Log 回滚段。

3.1 元组生命周期

stateDiagram-v2
    [*] --> Active : INSERT (创建新行)
    Active --> Committed : COMMIT (事务提交)
    Active --> Aborted : ROLLBACK (事务回滚)
    
    Committed --> Updating : UPDATE (被新事务更新)
    Updating --> Dead : COMMIT (更新提交,旧行失效)
    
    Committed --> Deleting : DELETE (被新事务删除)
    Deleting --> Dead : COMMIT (删除提交)
    
    Dead --> Reusable : VACUUM (清理死元组)
    Reusable --> [*] : 空间重用

3.2 版本链与可见性

当一行数据被更新时,新旧版本通过 ctid 指针连接形成版本链。

graph TB
    Query[查询事务 Snapshot<br/>Xmin=250]
    
    subgraph VersionChain [元组版本链]
        V1["<b>版本 1</b><br/>xmin=100 (Committed)<br/>xmax=200 (Committed)"]
        V2["<b>版本 2</b><br/>xmin=200 (Committed)<br/>xmax=300 (Running)"]
        V3["<b>版本 3</b><br/>xmin=300 (Running)<br/>xmax=0"]
    end

    Query --> V1
    Query --> V2
    Query --> V3
    
    V1 -->|ctid| V2
    V2 -->|ctid| V3
    
    %% 添加可见性标签
    V1_Label[不可见: xmax已提交]
    V2_Label["<b>可见</b>: xmin已提交 & xmax未提交"]
    V3_Label[不可见: xmin未提交]
    
    V1 -.-> V1_Label
    V2 -.-> V2_Label  
    V3 -.-> V3_Label
    
    class V2 highlight
    classDef highlight fill:#d5f5e3,stroke:#2ecc71,stroke-width:2px

可见性规则的核心

  • xmin < 当前快照 && (xmax == 0 || xmax > 当前快照)
  • 简而言之:我只能看到在我开始之前已经提交的数据,且这些数据在我开始之前没有被删除。

IV. 查询处理与优化器

PostgreSQL 拥有极其强大的查询优化器,支持遗传算法 (GEQO) 和复杂代价模型。

4.1 查询执行流水线

sequenceDiagram
    participant Client
    participant Parser as 解析器 (Parser)
    participant Analyzer as 分析器 (Analyzer)
    participant Rewriter as 重写器 (Rewriter)
    participant Planner as 规划器 (Planner)
    participant Executor as 执行器 (Executor)
    
    Client->>Parser: 发送 SQL 查询
    Parser->>Analyzer: 生成原始解析树 (Parse Tree)
    Analyzer->>Rewriter: 语义分析 & 生成查询树 (Query Tree)
    Rewriter->>Planner: 应用规则 (如视图展开)
    Planner->>Planner: 逻辑优化 & 物理优化
    Note right of Planner: 成本估算 (CBO)<br/>遗传算法 (GEQO)<br/>连接顺序选择
    Planner->>Executor: 生成最优执行计划 (Plan Tree)
    Executor->>Executor: 递归执行节点 (Scan/Join/Sort)
    Executor-->>Client: 返回结果集

4.2 优化器黑科技

  1. 遗传查询优化 (GEQO): 当连接的表数量非常多(默认 >= 12)时,穷举所有连接顺序太慢,PG 会自动切换到遗传算法来搜索近似最优解。
  2. JIT (即时编译): 对于复杂的大型 OLAP 查询,PG 可以利用 LLVM 将 SQL 表达式动态编译为机器码,加速执行。
  3. 并行查询: 自动利用多核 CPU 并行执行扫描、连接和聚合操作。

V. 索引机制详解

PG 的索引是开放接口的,支持极其丰富的数据结构。

5.1 B-tree 索引结构 (Lehman & Yao 算法)

graph TD
    Root[Root Node] --> I1[Internal Node]
    Root --> I2[Internal Node]
    I1 --> L1[Leaf Node 1<br/>Data: 1..10]
    I1 --> L2[Leaf Node 2<br/>Data: 11..20]
    I2 --> L3[Leaf Node 3<br/>Data: 21..30]
    
    L1 -.->|Right Link| L2
    L2 -.->|Right Link| L3
    
    classDef leaf fill:#e8f8f5,stroke:#1abc9c
    class L1,L2,L3 leaf
  • Right-Link 机制: 允许读操作在节点分裂 (Split) 时无需加锁,极大提升并发性能。

5.2 索引类型全景

索引类型原理杀手级应用场景
B-tree平衡树绝大多数常规查询 (=, >, <, BETWEEN)
GIN倒排索引 (Inverted)JSONB 包含查询、数组搜索、全文检索
GiST通用搜索树GIS 地理数据 (PostGIS)、几何图形重叠判断
SP-GiST空间分区树非平衡数据集,如 URL 路由、分区数据
BRIN块范围索引时序数据、超大数据集的日志表 (极省空间)

VI. 事务管理与 WAL

6.1 ACID 的基石:WAL

sequenceDiagram
    participant Tx as 事务
    participant WALBuf as WAL Buffer
    participant WALFile as 磁盘 WAL 文件
    participant SharedBuf as Shared Buffer
    participant DataFile as 磁盘数据文件

    Note over Tx, WALFile: 预写日志原则 (Write-Ahead Logging)

    Tx->>WALBuf: 1. 写入变更日志 (XLogRecord)
    Tx->>SharedBuf: 2. 修改内存中的数据页 (Dirty Page)
    
    Tx->>Tx: 3. 提交事务 (COMMIT)
    Tx->>WALBuf: 4. 写入 Commit Record
    WALBuf->>WALFile: 5. 刷盘 (fsync/fdatasync)
    WALFile-->>Tx: 6. 提交成功确认

    Note over SharedBuf, DataFile: 此时数据页可能还没写入磁盘!
    
    loop Checkpoint / BgWriter
        SharedBuf->>DataFile: 7. 异步将脏页写入数据文件
    end
  • Full Page Write (全页写入): 在 Checkpoint 后,第一次修改页面会记录整个页面内容,防止 OS 崩溃导致的“半页写入”损坏。

VII. 扩展性与高级特性

7.1 强大的分区表

graph TD
    Parent[主表: Sales] -->|Partition Key: Date| P1[分区: Sales_Jan]
    Parent --> P2[分区: Sales_Feb]
    Parent --> P3[分区: Sales_Mar]
    
    Client[查询: WHERE date='Jan-01'] -.->|Partition Pruning| P1
    Client -.->|忽略| P2
    Client -.->|忽略| P3
  • Partition Pruning (分区剪枝): 查询优化器能自动跳过不需要扫描的分区。

7.2 物理复制 vs 逻辑复制

graph TB
    subgraph "物理流复制 (HA)"
        P1[主库] -->|WAL Stream| P2[备库]
    end

    subgraph "逻辑复制 (ETL/微服务)" 
        L1[发布端] -->|Logical Decoding| L2[订阅端]
    end

    %% 为两个子图添加描述性文本
    P_Desc[整实例复制<br/>只读副本<br/>故障切换] 
    L_Desc[表级粒度<br/>跨版本/跨OS<br/>数据汇聚]

VIII. PostgreSQL vs MySQL 核心对比

8.1 功能与理念对比

特性PostgreSQLMySQL (InnoDB)核心差异点
架构多进程多线程PG 隔离性强,连接开销大 (需连接池);MySQL 连接轻量。
MVCCappend-only (新旧版本共存)undo log (回滚段)PG 写不阻塞读,清理依赖 VACUUM;MySQL 空间回收由 Purge 线程自动处理。
Join 算法Nested Loop, Hash Join, Merge Join长期仅 Nested Loop (8.0+ 加入 Hash Join)PG 处理复杂多表关联性能极强 (OLAP 能力更优)。
数据类型JSONB (二进制+索引), GIS, 数组JSON (文本), GIS 较弱PG 是 NoSQL + SQL 的完美结合体。
许可证PostgreSQL (类 BSD)GPLPG 商业化更自由。

8.2 选型建议图谱

journey
    title 数据库选型决策路径
    section 业务场景分析
      简单 CRUD, 互联网高并发: 5: MySQL
      复杂 SQL, 数据分析, 报表: 5: PostgreSQL
      需要 GIS 地理信息: 5: PostgreSQL (PostGIS)
      需要 JSON 文档存储: 4: PostgreSQL (JSONB)
    section 运维考量
      DBA 人才储备充足: 5: MySQL
      需要极致的数据一致性: 5: PostgreSQL
      需要 Oracle 迁移: 4: PostgreSQL

总结

PostgreSQL 能够成为当今最流行的数据库之一,归功于其学院派的严谨工程派的实用的完美结合:

  1. 真正的 MVCC 实现:提供无阻塞读取和严格的快照隔离。
  2. 可扩展架构:通过 Extension (如 PostGIS, TimescaleDB) 让数据库能力无限延伸。
  3. 强大的优化器:能够驾驭极其复杂的查询逻辑,不仅仅是简单的 Key-Value 查询。

专家建议:如果你的业务涉及复杂的数据模型、混合负载 (HTAP) 或地理空间数据,PostgreSQL 是不二之选;如果是纯粹的高并发简单点查询 (Point Select),MySQL 依然表现优异。

参考&致谢

系列教程

全部文章RSS订阅

数据库系列


作者: 夜法之书
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 夜法之书 !
评论
数据加载中 ...
 本篇

阅读全文

PostgreSQL 实现原理深度剖析:高性能数据库引擎的核心机制
PostgreSQL 实现原理深度剖析:高性能数据库引擎的核心机制 PostgreSQL 实现原理深度剖析:高性能数据库引擎的核心机制
PostgreSQL 作为最先进的开源关系数据库系统,其内部实现原理体现了数据库领域的前沿设计与工程智慧。本文将深入探讨 PostgreSQL 的架构设计、存储机制、并发控制和优化器原理,并通过与 MySQL 的对比展示其独特优势。
2025-11-22
下一篇 

阅读全文

PostgreSQL 使用全面指南:从入门到企业级应用
PostgreSQL 使用全面指南:从入门到企业级应用 PostgreSQL 使用全面指南:从入门到企业级应用
PostgreSQL 是世界上最先进的开源关系型数据库,以其强大的功能、高度的扩展性和严格的 SQL 标准兼容性著称。本教程将带你从基础到高级全面掌握 PostgreSQL 的使用技巧,涵盖安装配置、核心操作、高级特性和性能优化等各个方面。
2025-11-22
  目录