PostgreSQL 架构
PostgreSQL 是多进程架构,和 MySQL 的线程模型完全不同:每个客户端连接对应一个独立的后端进程,进程间通过共享内存通信。进程崩溃互不影响,这是 PG 架构稳定性的根基。
进程模型
PostgreSQL 进程模型
- postmaster:所有进程的父进程,监听端口,接受连接时 fork 出后端进程
- 后端进程(backend):每个客户端连接一个,处理该连接的所有查询,连接断开即退出
- 后台进程:checkpointer(检查点)、bgwriter(脏页刷盘)、WAL writer(日志刷盘)、autovacuum launcher(自动清理)、stats collector(统计信息)、archiver(WAL 归档)
对比 MySQL 的线程加连接池模型:PG 的进程模型让每个连接的内存开销更大(连接数高时明显),所以生产常用 PgBouncer 连接池。好处是隔离性好,一个进程崩溃不影响其他连接。
内存架构
共享内存区(所有进程共享):
- shared buffers:数据页和索引页缓存,类似 MySQL 的 Buffer Pool,建议设为物理内存的 25% 左右(PG 官方建议,与 MySQL 的 60-80% 不同)
- WAL buffer:WAL 日志写盘前的缓冲
- CLOG(提交日志):记录事务提交状态,MVCC 可见性判断要用
本地内存区(每个后端进程私有):
- work_mem:排序、哈希连接、DISTINCT 等操作的内存,用完会落盘(临时文件),是慢查询常见瓶颈
- maintenance_work_mem:VACUUM、CREATE INDEX 等维护操作
- temp_buffers:临时表缓冲
一条查询的执行链路
- 客户端连接被 postmaster 接受,fork 后端进程
- 解析器做词法和语法分析,生成解析树
- 重写器处理视图和规则
- 规划器(planner):基于统计信息生成执行计划,估算每种路径的代价(代价优化器,见查询优化篇)
- 执行器按计划执行,从 shared buffers 或磁盘读页
- 结果返回客户端
面试追问
- PG 为什么用多进程? 进程隔离性好,一个崩溃不影响其他;代价是每个连接内存开销大,需要连接池。MySQL 用线程模型,连接更轻量
- shared buffers 配多大? 官方建议物理内存的 25% 左右,和 MySQL 的 Buffer Pool(60-80%)策略不同
- work_mem 是什么? 排序和哈希连接的工作内存,用完落盘。设置过小导致频繁落临时文件,是慢查询常见原因
- CLOG 的作用? 记录事务提交状态,配合 xmin/xmax 判断可见性;MySQL 则靠 Read View + undo log 里的事务 ID。职责不同,别混
- PG 有连接池吗? 内核没有内置连接池,生产用 PgBouncer 等外部连接池,因为进程模型下每个连接开销大