AI时代首先数据库-PostgreSQL实战笔记 | 22 PostgreSQL实例与集群

上一篇我们拆解了 PostgreSQL 的进程与内存架构。这一篇,我们把视角从"进程内部"拉到"对象层级"。实例、集群、数据库、模式、表空间------这五个词在日常交流中经常被混用,但在 PostgreSQL 的语境里,它们指向的是不同层次、甚至不同性质 的东西。理清它们的关系,你才能理解一个实例下多个数据库如何共存、表空间到底在调什么、以及哪些隔离是逻辑的、哪些隔离才是物理的。

一、五个词,先对号入座

在 PostgreSQL 的官方文档中,层级关系写得非常明确:

cluster → database → schema → table(或其他对象)

但"cluster"这个词在这里需要特别小心:PostgreSQL 所说的"集群",通常指的是一个由 initdb 初始化的数据目录加上运行在其上的服务器进程,也就是一个实例,而不是多台机器组成的分布式集群。很多中文材料直接把 cluster 翻译为"集群",容易和"数据库集群(多节点)"混淆,阅读时需要结合上下文判断。

概念 本质 层级 关键特征
实例 / Cluster 一个数据目录 + 一组进程 最外层 共享 WAL、配置、内存、后台进程
数据库 逻辑容器,带独立权限体系 实例之下 连接时必选一个数据库,一个连接不能跨库访问
模式(Schema) 数据库内的命名空间 数据库之下 不同 schema 下可以有同名表;默认 public
表空间 物理存储位置 跨数据库、跨实例 一个表空间可以存放多个数据库的对象;一个数据库的对象可以分布在多个表空间

一个需要先记住的关键区分:数据库和模式是逻辑概念,表空间是物理概念,两者是"正交"的------它们回答的是不同的问题。数据库回答"数据属于谁、按什么权限组织",表空间回答"数据存在哪块磁盘上"。

二、一个实例下多个数据库:隔离了什么,共享了什么

这是本篇的核心问题之一。

从用户视角 看,多个数据库之间是隔离 的:你连接时必须指定一个数据库,一个连接不能同时访问两个数据库 ;每个数据库有自己的系统目录、权限和对象空间。如果两个项目或两组用户基本互不关心 ,官方建议把它们放进不同的数据库,并分别配置授权和访问控制。

但从管理员视角 看,它们又紧密绑定在一起。它们共享的是同一套底层资源:

  • 同一个 WAL 流 :这是最关键的共享点。所有数据库的变更写入同一个 WAL,备份和恢复的粒度是集群级的,而不是数据库级的。你不能对一个实例中的某个数据库单独做 PITR,也不能单独回滚它。
  • 同一组内存和进程 :shared_buffers、wal_buffers、checkpointer、background writer、walwriter 都由所有数据库共享。
  • 同一套配置 :postgresql.conf 中的参数对所有数据库生效(少数参数可以在数据库级别用 ALTER DATABASE ... SET 覆盖,但核心的资源参数是全局的)。
  • 同一个数据目录 :base/ 下按数据库 OID 分目录存放,但 WAL、事务状态、全局系统表都是共享的。

所以,"多数据库"提供的是逻辑隔离和权限隔离,而不是资源隔离或故障隔离。一个数据库里的长事务、锁竞争、大量写入产生的 WAL,都会对整个实例中的其他数据库产生影响。这也是官方提醒"多数据库的收益需要与风险和限制一起权衡"的原因。

什么时候用多个数据库,什么时候用多个 schema?

官方给出的判断标准很简洁:

  • 互不关心、需要强隔离 → 不同数据库,分别授权;
  • 互相关联、需要互相访问对方对象 → 同一个数据库,不同 schema,利用命名空间隔离和权限控制实现模块化。

用 schema 的好处是:可以在同一个连接中直接跨 schema 引用对象,事务边界统一,JOIN 和子查询不受阻碍 。用数据库的好处是:连接级隔离更彻底,权限边界更清晰 。但后者的代价是,你失去了跨库查询的能力,只能依赖 postgres_fdw 或 dblink 做代理访问,而且备份恢复仍然是全实例粒度。

三、表空间:唯一能改变"数据放在哪"的工具

如果说数据库和模式是在逻辑层面做划分,表空间就是 PostgreSQL 中唯一能直接控制物理存储位置的机制。

表空间的物理映射:软链接

当你执行 CREATE TABLESPACE fast_ssd LOCATION '/mnt/nvme/pg_fast' 时,PostgreSQL 会在数据目录的 pg_tblspc/ 下创建一个以表空间 OID 命名的符号链接,指向你指定的外部目录。

复制代码
$PGDATA/pg_tblspc/16385  →  /mnt/nvme/pg_fast

在这个外部目录内部,对象仍然按"数据库 OID / relfilenode"的方式组织。这意味着:一个表空间可以同时存放多个数据库的表和索引,一个数据库的对象也可以分散在多个表空间中。表空间不隶属于某个数据库,它是实例级别的物理容器。

这个设计带来一个重要的运维含义:备份时必须同时备份 pg_tblspc/ 中的软链接和软链接指向的实际目录 。只备份 $PGDATA 会丢失表空间中的数据,因为真正存放表文件的目录在 PGDATA 之外。

表空间如何用于性能隔离

表空间最实用的价值,是把 I/O 特征不同的数据放到不同的存储设备上。

一个典型的做法是热表隔离:把高频访问的小表放到 NVMe SSD 对应的表空间,把低频访问的大表或归档数据放到大容量 HDD 对应的表空间。索引和表也可以分离------把重度使用的索引放在最快的设备上,减少随机读延迟。

但仅仅把数据放到不同磁盘上还不够。PostgreSQL 的查询优化器默认假设所有表空间的 I/O 成本是一致的 。如果 SSD 表空间和 HDD 表空间共用同一套 seq_page_cost 和 random_page_cost,优化器可能会做出错误的成本估算。

从 PostgreSQL 的某个版本开始,表空间可以单独设置 I/O 成本参数:

sql 复制代码
ALTER TABLESPACE fast_ssd SET (
    random_page_cost = 1.1,
    seq_page_cost = 1.0,
    effective_io_concurrency = 200
);

这组参数会覆盖该表空间中表的全局默认成本估算,让优化器知道"这里的随机读并不昂贵"。对于位于不同存储介质的表空间,这是让优化器做出正确决策的必要步骤。

表空间的边界:它能做什么,不能做什么

表空间能做的:物理位置隔离、按设备设置 I/O 成本、把表/索引/物化视图分别放到不同卷上。

表空间不能做的:它不提供 CPU、内存或锁层面的隔离,也不改变"所有数据库共享同一个 WAL"这一事实 。一个表空间上的大量写入,仍然会产生全实例共享的 WAL 压力。表空间是存储层 的调优工具,不是实例资源的隔离工具。

四、连接管理:每个连接绑定一个数据库

PostgreSQL 的连接模型对这个层级结构有一个直接体现:客户端在连接时必须指定一个数据库名,连接建立后,这个会话就绑定在那个数据库上,不能中途"切换"到另一个数据库 。你可以对同一个数据库开多个连接,也可以对不同数据库分别开连接,但单个连接无法跨库 。跨库访问只能通过 postgres_fdw 或 dblink 这类外部数据包装器,让一个数据库中的对象"代理"另一个数据库中的对象。

这个约束和"process-per-connection"的进程模型是配套的:每个 backend 进程在 fork 时就已经确定了它所服务的数据库,私有内存和缓存都围绕那个数据库工作。这也是为什么"多数据库"在 PostgreSQL 中是一个连接级的划分,而不是一个可以在会话内自由穿越的逻辑边界。

五、总结

问题 结论
实例/集群是什么? 一个数据目录 + 一组共享 WAL、内存、配置的进程
多数据库隔离了什么? 逻辑与权限,不隔离 WAL、内存、故障域
多数据库共享什么? 同一个 WAL(备份恢复全实例粒度)、shared_buffers、后台进程、配置文件
数据库 vs 模式怎么选? 互不关心 → 不同数据库;互相关联 → 同库不同 schema
表空间的本质? 物理存储位置,跨数据库、跨实例,与逻辑数据库正交
表空间如何调优? 热表/索引分散到不同设备,并单独设置 I/O 成本参数让优化器感知差异
表空间的边界? 只做存储层调优,不解决 WAL 共享和资源竞争

一句话:PostgreSQL 的多数据库给你的是"逻辑上的独立王国",但它们仍然住在同一栋房子里,共享同一个水电总闸(WAL)和同一套承重结构。表空间是你唯一可以改变"房间朝向哪块地皮"的工具,但它改变不了"所有房间共用同一个总闸"这件事。

下一篇,我们进入数据库文件系统与数据页结构:8KB 的页里到底装了什么?TOAST 如何让大字段不拖垮主表?


思考题:

你的 PostgreSQL 实例目前是一个数据库承载所有业务,还是按业务拆成了多个数据库?如果拆了,你有没有遇到过"备份只能全实例做、一个库出问题影响所有库"的困扰?另外,你有没有用过表空间做冷热分离------实际效果符合预期吗?欢迎在评论区聊聊。

相关推荐
ss27334 分钟前
AI时代首先数据库-PostgreSQL实战笔记 | 21 PostgreSQL进程与内存架构介绍
数据库·笔记·postgresql
Henry-SAP2 小时前
SAP PP模块全景概览
数据库
喜欢吃豆2 小时前
Better Auth 深度解析:从用户认证到企业级身份基础设施
数据库·架构·权限·多租户
其实防守也摸鱼3 小时前
Cylab在线靶场——CTF中的通用技能
linux·数据库·学习·算法·靶场·ctf·学习网络安全
吹什么轩3 小时前
MySQL:数据库基础
数据库·mysql
内存漫游3 小时前
Undo、Redo 与事务回滚
数据库
FluxDB3 小时前
用 Rust + GPUI 重做数据库客户端
数据库·mysql
烬羽3 小时前
PostgreSQL:AI 时代原生的"隐型"向量数据库 — 用 pgvector 给消息表加上长期记忆
数据库·人工智能·程序员
摇滚侠3 小时前
《Java并发编程之美》第 4 章 Java 并发包中原子操作类原理剖析 阅读笔记 7
java·笔记·python