这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

集群配置

根据需求场景选择合适的实例与集群类型,配置出满足需求的 PostgreSQL 数据库集群。

Pigsty 是一个“配置驱动”的 PostgreSQL 平台:所有行为都来自 ~/pigsty/conf/*.yml 清单与 PGSQL 参数 的组合。

只要写好配置,你就能在几分钟内复刻出一套包含实例、用户、数据库、访问控制、扩展与调优策略的定制集群。


配置入口

  1. 准备清单:复制 pigsty/conf/*.yml 模板或从零开始编写 Ansible Inventory,将集群分组(all.children.<cls>.hosts)与全局变量(all.vars)写入同一个文件。
  2. 定义参数:在 vars 区块中覆盖需要的 PGSQL 参数。全局 → 集群 → 主机的覆盖顺序决定了最终值。
  3. 应用配置:运行 ./configure -c <conf>bin/pgsql-add <cls> 等剧本让配置落地。Pigsty 会根据参数生成 Patroni/pgbouncer/pgbackrest 等服务所需的配置文件。

Pigsty 默认的 Demo 清单 conf/pgsql.yml 就是一份最小化示例:一个 pg-meta 集群、全局 pg_version: 18、少量业务用户与数据库定义。你可以在此基础上扩展更多集群。


关注点与文档索引

Pigsty 的 PostgreSQL 配置可以从以下几个维度组合,后续文档会逐一展开“如何配置”:

  • 集群实例:通过 pg_cluster / pg_role / pg_seq / pg_upstream 定义实例拓扑(单机、主从、备份集群、延迟集群、Citus 等)。
  • 内核版本:使用 pg_versionpg_modepg_packagespg_extensionspg_conf 等参数挑选核心版本、风味和调优模板。
  • 用户/角色:在 pg_default_rolespg_users 中声明系统角色、业务账号、密码策略以及连接池属性。
  • 数据库对象:借助 pg_databasesbaselineschemasextensionspool_* 字段按需创建数据库并自动接入 pgbouncer/Grafana。
  • 访问控制 (HBA):利用 pg_default_hba_rulespg_hba_rules 维护主机级认证策略,保证不同角色/网络的访问边界。
  • 权限模型 (ACL):通过 pg_default_privilegespg_default_rolespg_revoke_public 等参数收敛对象权限,开箱即用地提供分层角色体系。

理解这些参数之后,你就可以针对任意业务需求写出“配置即基础设施”的声明式清单,Pigsty 会负责执行并确保幂等。


一个典型示例

下面的片段展示了如何在同一个配置文件中同时控制实例拓扑、内核版本、扩展、用户以及数据库:

all:
  children:
    pg-analytics:
      hosts:
        10.10.10.11: { pg_seq: 1, pg_role: primary }
        10.10.10.12: { pg_seq: 2, pg_role: replica, pg_offline_query: true }
      vars:
        pg_cluster: pg-analytics
        pg_conf: olap.yml
        pg_extensions: [ postgis, timescaledb, pgvector ]
        pg_databases:
          - { name: bi, owner: dbuser_bi, schemas: [mart], extensions: [timescaledb], pool_mode: session }
        pg_users:
          - { name: dbuser_bi, password: DBUser.BI, roles: [dbrole_admin], pgbouncer: true }
  vars:
    pg_version: 17
    pg_packages: [ pgsql-main pgsql-common ]
    pg_hba_rules:
      - { user: dbuser_bi, db: bi, addr: intra, auth: ssl, title: 'BI 只允许内网 SSL 访问' }
  • pg-analytics 集群包含一个主库和一个离线副本。
  • 全局指定 pg_version: 17 与一套扩展示例,并加载 olap.yml 调优。
  • pg_databasespg_users 中声明业务对象,自动生成 schema/extension 与连接池条目。
  • 附加的 pg_hba_rules 限制了访问来源与认证方式。

修改并应用这份清单即可得到一套定制化的 PostgreSQL 集群,而无需手工逐项配置。

1 - 集群实例

根据需求场景选择合适的实例与集群类型,配置出满足需求的 PostgreSQL 数据库集群。

根据需求场景选择合适的实例与集群类型,配置出满足需求的 PostgreSQL 数据库集群。

您可以定义不同类型的实例和集群,下面是 Pigsty 中常见的几种 PostgreSQL 实例/集群类型:


读写主库

我们从最简单的情况开始:由一个主库(Primary)组成的单实例集群:

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-test

这段配置言简意赅,自我描述,仅由 身份参数 构成,请注意 Ansible Group 分组名应当与 pg_cluster 保持一致。

使用以下命令创建该集群:

bin/pgsql-add pg-test

Demo展示,开发测试,承载临时需求,进行无关紧要的计算分析任务时,使用单一数据库实例可能并没有太大问题。但这样的单机集群没有 高可用,当出现硬件故障时,您需要使用 PITR 或其他恢复手段来确保集群的 RTO / RPO。为此,您可以考虑为集群添加若干个 只读从库


只读从库

要添加一台只读从库(Replica)实例,您可以在 pg-test 中添加一个新节点,并将其 pg_role 设置为replica

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }  # <--- 新添加的从库
  vars:
    pg_cluster: pg-test

如果整个集群不存在,您可以直接 创建 这个完整的集群。 如果集群主库已经初始化好了,那么您可以向现有集群 添加 一个从库:

bin/pgsql-add pg-test               # 一次性初始化整个集群
bin/pgsql-add pg-test 10.10.10.12   # 添加从库到现有的集群

当集群主库出现故障时,只读实例(Replica)可以在高可用系统的帮助下接管主库的工作。除此之外,只读实例还可以用于执行只读查询:许多业务的读请求要比写请求多很多,而大部分只读查询负载都可以由从库实例承担。


离线从库

离线实例(Offline)是专门用于服务慢查询、ETL、OLAP流量和交互式查询等的专用只读从库。慢查询/长事务对在线业务的性能与稳定性有不利影响,因此最好将它们与在线业务隔离开来。

要添加离线实例,请为其分配一个新实例,并将 pg_role 设置为offline

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
    10.10.10.13: { pg_seq: 3, pg_role: offline }  # <--- 新添加的离线从库
  vars:
    pg_cluster: pg-test

专用离线实例的工作方式与常见的从库实例类似,但它在 pg-test-replica 服务中用作备份服务器。 也就是说,只有当所有replica实例都宕机时,离线和主实例才会提供此项只读服务。

许多情况下,数据库资源有限,单独使用一台服务器作为离线实例是不经济的做法。作为折中,您可以选择一台现有的从库实例,打上 pg_offline_query 标记,将其标记为一台可以承载"离线查询"的实例。在这种情况下,这台只读从库会同时承担在线只读请求与离线类查询。您可以使用 pg_default_hba_rulespg_hba_rules 对离线实例进行额外的访问控制。


同步备库

当启用同步备库(Sync Standby)时,PostgreSQL 将选择一个从库作为同步备库,其他所有从库作为候选者。 主数据库会等待备库实例刷新到磁盘,然后才确认提交,备库实例始终拥有最新的数据,没有复制延迟,主从切换至同步备库不会有数据丢失。

PostgreSQL 默认使用异步流复制,这可能会有小的复制延迟(10KB / 10ms 数量级)。当主库失败时,可能会有一个小的数据丢失窗口(可以使用 pg_rpo 来控制),但对于大多数场景来说,这是可以接受的。

但在某些关键场景中(例如,金融交易),数据丢失是完全不可接受的,或者,读取复制延迟是不可接受的。在这种情况下,您可以使用同步提交来解决这个问题。 要启用同步备库模式,您可以简单地使用 pg_conf 中的crit.yml模板。

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica }
    10.10.10.13: { pg_seq: 3, pg_role: replica }
  vars:
    pg_cluster: pg-test
    pg_conf: crit.yml   # <--- 使用 crit 模板

要在现有集群上启用同步备库,请 配置集群 并启用 synchronous_mode

$ pg edit-config pg-test    # 在管理员节点以管理员用户身份运行
+++
-synchronous_mode: false    # <--- 旧值
+synchronous_mode: true     # <--- 新值
 synchronous_mode_strict: false

应用这些更改?[y/N]: y

在这种情况下,PostgreSQL 配置项 synchronous_standby_names 由 Patroni 自动管理。 一台从库将被选拔为同步从库,它的 application_name 将被写入 PostgreSQL 主库配置文件中并应用生效。


法定人数提交

法定人数提交(Quorum Commit)提供了比同步备库更强大的控制能力:特别是当您有多个从库时,您可以设定提交成功的标准,实现更高/更低的一致性级别(以及可用性之间的权衡)。

如果想要最少两个从库来确认提交,可以通过 Patroni 配置集群,调整参数 synchronous_node_count 并应用生效

synchronous_mode: true          # 确保同步提交已经启用
synchronous_node_count: 2       # 指定“至少”有多少个从库提交成功,才算提交成功

如果你想要使用更多的同步从库,修改 synchronous_node_count 的取值即可。当集群的规模发生变化时,您应当确保这里的配置仍然是有效的,以避免服务不可用。

在这种情况下,PostgreSQL 配置项 synchronous_standby_names 由 Patroni 自动管理。

synchronous_standby_names = '2 ("pg-test-3","pg-test-2")'
示例:使用多个同步从库
$ pg edit-config pg-test
---
+synchronous_node_count: 2

Apply these changes? [y/N]: y

应用配置后,出现两个同步备库。

+ Cluster: pg-test (7080814403632534854) +---------+----+-----------+-----------------+
| Member    | Host        | Role         | State   | TL | Lag in MB | Tags            |
+-----------+-------------+--------------+---------+----+-----------+-----------------+
| pg-test-1 | 10.10.10.10 | Leader       | running |  1 |           | clonefrom: true |
| pg-test-2 | 10.10.10.11 | Sync Standby | running |  1 |         0 | clonefrom: true |
| pg-test-3 | 10.10.10.12 | Sync Standby | running |  1 |         0 | clonefrom: true |
+-----------+-------------+--------------+---------+----+-----------+-----------------+

另一种情景是,使用 任意n个 从库来确认提交。在这种情况下,配置的方式略有不同,例如,假设我们只需要任意一个从库确认提交:

synchronous_mode: quorum        # 使用法定人数提交
postgresql:
  parameters:                   # 修改 PostgreSQL 的配置参数 synchronous_standby_names ,使用 `ANY n ()` 语法
    synchronous_standby_names: 'ANY 1 (*)'  # 你可以指定具体的从库列表,或直接使用 * 通配所有从库。
示例:启用ANY法定人数提交
$ pg edit-config pg-test

+    synchronous_standby_names: 'ANY 1 (*)' # 在 ANY 模式下,需要使用此参数
- synchronous_node_count: 2  # 在 ANY 模式下, 不需要使用此参数

Apply these changes? [y/N]: y

应用后,配置生效,所有备库在 Patroni 中变为普通的 replica。但是在 pg_stat_replication 中可以看到 sync_state 会变为 quorum


备份集群

您可以克隆现有的集群,并创建一个备份集群(Standby Cluster),用于数据迁移、水平拆分、多区域部署,或灾难恢复。

在正常情况下,备份集群将追随上游集群并保持内容同步,您可以将备份集群提升,作为真正地独立集群。

备份集群的定义方式与正常集群的定义基本相同,除了在主库上额外定义了 pg_upstream 参数,备份集群的主库被称为 备份集群领导者 (Standby Leader)。

例如,下面定义了一个pg-test集群,以及其备份集群pg-test2,其配置清单可能如下所示:

# pg-test 是原始集群
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars: { pg_cluster: pg-test }

# pg-test2 是 pg-test 的备份集群
pg-test2:
  hosts:
    10.10.10.12: { pg_seq: 1, pg_role: primary , pg_upstream: 10.10.10.11 } # <--- pg_upstream 在这里定义
    10.10.10.13: { pg_seq: 2, pg_role: replica }
  vars: { pg_cluster: pg-test2 }

pg-test2 集群的主节点 pg-test2-1 将是 pg-test 的下游从库,并在pg-test2集群中充当备份集群领导者(Standby Leader)。

只需确保备份集群的主节点上配置了 pg_upstream 参数,以便自动从原始上游拉取备份。

bin/pgsql-add pg-test     # 创建原始集群
bin/pgsql-add pg-test2    # 创建备份集群
示例:更改复制上游

如有必要(例如,上游发生主从切换/故障转移),您可以通过 配置集群 更改备份集群的复制上游。

要这样做,只需将standby_cluster.host更改为新的上游IP地址并应用。

$ pg edit-config pg-test2

 standby_cluster:
   create_replica_methods:
   - basebackup
-  host: 10.10.10.13     # <--- 旧的上游
+  host: 10.10.10.12     # <--- 新的上游
   port: 5432

 Apply these changes? [y/N]: y
示例:提升备份集群

你可以随时将备份集群提升为独立集群,这样该集群就可以独立承载写入请求,并与原集群分叉。

为此,你必须 配置 该集群并完全擦除standby_cluster部分,然后应用。

$ pg edit-config pg-test2
-standby_cluster:
-  create_replica_methods:
-  - basebackup
-  host: 10.10.10.11
-  port: 5432

Apply these changes? [y/N]: y
示例:级联复制

如果您在一台从库上指定了 pg_upstream,而不是主库。那么可以配置集群的 级联复制(Cascade Replication)

在配置级联复制时,您必须使用集群中某一个实例的IP地址作为参数的值,否则初始化会报错。该从库从特定的实例进行流复制,而不是主库。

这台充当 WAL 中继器的实例被称为 桥接实例(Bridge Instance)。使用桥接实例可以分担主库发送 WAL 的负担,当您有几十台从库时,使用桥接实例级联复制是一个不错的注意。

pg-test:
  hosts: # pg-test-1 ---> pg-test-2 ---> pg-test-3
    10.10.10.11: { pg_seq: 1, pg_role: primary }
    10.10.10.12: { pg_seq: 2, pg_role: replica } # <--- 桥接实例
    10.10.10.13: { pg_seq: 3, pg_role: replica, pg_upstream: 10.10.10.12 }
    # ^--- 从 pg-test-2 (桥接)复制,而不是从 pg-test-1 (主节点) 
  vars: { pg_cluster: pg-test }

延迟集群

延迟集群(Delayed Cluster)是一种特殊类型的 备份集群,用于尽快恢复"意外删除"的数据。

例如,如果你希望有一个名为 pg-testdelay 的集群,其数据内容与一小时前的 pg-test 集群相同:

# pg-test 是原始集群
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars: { pg_cluster: pg-test }

# pg-testdelay 是 pg-test 的延迟集群
pg-testdelay:
  hosts:
    10.10.10.12: { pg_seq: 1, pg_role: primary , pg_upstream: 10.10.10.11, pg_delay: 1d }
    10.10.10.13: { pg_seq: 2, pg_role: replica }
  vars: { pg_cluster: pg-testdelay }

你还可以在现有的 备份集群配置 一个"复制延迟"。

$ pg edit-config pg-testdelay
 standby_cluster:
   create_replica_methods:
   - basebackup
   host: 10.10.10.11
   port: 5432
+  recovery_min_apply_delay: 1h    # <--- 在此处添加延迟时长,例如1小时

Apply these changes? [y/N]: y

当某些元组和表格被意外删除时,你可以通过修改此参数的方式,将此延迟集群推进到适当的时间点,并从中读取数据,快速修复原始集群。

延迟集群需要额外的资源,但比起 PITR 要快得多,并且对系统的影响也小得多,对于非常关键的集群,可以考虑搭建延迟集群。


Citus集群

Pigsty 原生支持 Citus。可以参考 files/pigsty/citus.ymlprod.yml 作为样例。

要定义一个 citus 集群,您需要指定以下参数:

此外,还需要额外的 hba 规则,允许从本地和其他数据节点进行 SSL 访问。如下所示:

all:
  children:
    pg-citus0: # citus 0号分片
      hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
      vars: { pg_cluster: pg-citus0 , pg_group: 0 }
    pg-citus1: # citus 1号分片
      hosts: { 10.10.10.11: { pg_seq: 1, pg_role: primary } }
      vars: { pg_cluster: pg-citus1 , pg_group: 1 }
    pg-citus2: # citus 2号分片
      hosts: { 10.10.10.12: { pg_seq: 1, pg_role: primary } }
      vars: { pg_cluster: pg-citus2 , pg_group: 2 }
    pg-citus3: # citus 3号分片
      hosts:
        10.10.10.13: { pg_seq: 1, pg_role: primary }
        10.10.10.14: { pg_seq: 2, pg_role: replica }
      vars: { pg_cluster: pg-citus3 , pg_group: 3 }
  vars:                               # 所有 Citus 集群的全局参数
    pg_mode: citus                    # pgsql 集群模式需要设置为: citus
    pg_shard: pg-citus                # citus 水平分片名称: pg-citus
    pg_primary_db: meta               # citus 数据库名称:meta
    pg_dbsu_password: DBUser.Postgres # 如果使用 dbsu ,那么需要为其配置一个密码
    pg_users: [ { name: dbuser_meta ,password: DBUser.Meta ,pgbouncer: true ,roles: [ dbrole_admin ] } ]
    pg_databases: [ { name: meta ,extensions: [ { name: citus }, { name: postgis }, { name: timescaledb } ] } ]
    pg_hba_rules:
      - { user: 'all' ,db: all  ,addr: 127.0.0.1/32 ,auth: ssl ,title: 'all user ssl access from localhost' }
      - { user: 'all' ,db: all  ,addr: intra        ,auth: ssl ,title: 'all user ssl access from intranet'  }

在协调者节点上,您可以创建分布式表和引用表,并从任何数据节点查询它们。从 11.2 开始,任何 Citus 数据库节点都可以扮演协调者的角色了。

SELECT create_distributed_table('pgbench_accounts', 'aid'); SELECT truncate_local_data_after_distributing_table($$public.pgbench_accounts$$);
SELECT create_reference_table('pgbench_branches')         ; SELECT truncate_local_data_after_distributing_table($$public.pgbench_branches$$);
SELECT create_reference_table('pgbench_history')          ; SELECT truncate_local_data_after_distributing_table($$public.pgbench_history$$);
SELECT create_reference_table('pgbench_tellers')          ; SELECT truncate_local_data_after_distributing_table($$public.pgbench_tellers$$);

2 - 内核版本

如何选择合适的 PostgreSQL 内核与大版本。

在 Pigsty 中选择"内核"意味着确定 PostgreSQL 大版本、模式/发行版、需要安装的包以及要加载的调优模板。

Pigsty 从 PostgreSQL 10 起提供支持,当前版本默认打包了 13 - 18 的核心软件,并在 17/18 上提供完整扩展集合。下方内容展示如何通过配置文件完成这些选择。


大版本与软件包

  • pg_version:指定 PostgreSQL 主版本(默认 18)。Pigsty 会根据版本自动映射到正确的包名前缀。
  • pg_packages:定义需要安装的核心包集合,支持使用 包别名(默认 pgsql-main pgsql-common,包含内核 + patroni/pgbouncer/pgbackrest 等常用工具)。
  • pg_extensions:额外需要安装的扩展包列表,同样支持别名;缺省为空表示只装核心依赖。
all:
  vars:
    pg_version: 18
    pg_packages: [ pgsql-main pgsql-common ]
    pg_extensions: [ postgis, timescaledb, pgvector, pgml ]

效果:Ansible 在安装阶段会拉取与 pg_version=18 对应的包,将扩展预装到系统中,随后数据库初始化脚本即可直接 CREATE EXTENSION

Pigsty 的离线仓库中不同版本的扩展支持范围不同:12/13 只提供核心与一级扩展,15/17/18 则涵盖全部扩展。若某扩展未预打包,可通过 repo_packages_extra 追加。


内核模式(pg_mode)

pg_mode 控制要部署的内核“风味”,默认 pgsql 表示标准 PostgreSQL。Pigsty 目前支持以下模式:

模式场景
pgsql标准 PostgreSQL,高可用 + 复制
citusCitus 分布式集群,需要额外的 pg_shard / pg_group
gpsqlGreenplum / MatrixDB
mssqlBabelfish for PostgreSQL
mysqlOpenGauss/HaloDB 兼容 MySQL 协议
polar阿里 PolarDB(基于 pg polar 发行)
ivoryIvorySQL(Oracle 兼容语法)
orioleOrioleDB 存储引擎
oraclePostgreSQL + ora 兼容(pg_mode: oracle

选择模式后,Pigsty 会自动加载对应的模板、依赖包与 Patroni 配置。以部署 Citus 为例:

all:
  children:
    pg-citus0:
      hosts: { 10.10.10.11: { pg_seq: 1, pg_role: primary } }
      vars: { pg_cluster: pg-citus0, pg_group: 0 }
    pg-citus1:
      hosts: { 10.10.10.12: { pg_seq: 1, pg_role: primary } }
      vars: { pg_cluster: pg-citus1, pg_group: 1 }
  vars:
    pg_mode: citus
    pg_shard: pg-citus
    patroni_citus_db: meta

效果:所有成员会安装 Citus 相关包,Patroni 以分片模式写入 etcd,并自动在 meta 数据库内 CREATE EXTENSION citus


扩展与预置对象

除了系统包,你还可以通过以下参数控制数据库启动后自动加载的组件:

  • pg_libs:写入 shared_preload_libraries 的列表。例如 pg_libs: 'timescaledb, pg_stat_statements, auto_explain'
  • pg_default_extensions / pg_default_schemas:控制初始化脚本对 template1postgres 预创建的 schema、扩展。
  • pg_parameters:为所有实例附加 ALTER SYSTEM SET(写入 postgresql.auto.conf)。

示例:启用 TimescaleDB、pgvector 并自定义一些系统参数。

pg-analytics:
  vars:
    pg_cluster: pg-analytics
    pg_libs: 'timescaledb, pg_stat_statements, pgml'
    pg_default_extensions:
      - { name: timescaledb }
      - { name: pgvector }
    pg_parameters:
      timescaledb.max_background_workers: 8
      shared_preload_libraries: "'timescaledb,pg_stat_statements,pgml'"

效果:初始化时 template1 会创建扩展、Patroni 的 postgresql.conf 注入对应参数,所有业务库继承这些设置。


调优模板 (pg_conf)

pg_conf 指向 roles/pgsql/templates/*.yml 中的 Patroni 模板。Pigsty内置四套通用模板:

模板适用场景
oltp.yml默认模板,面向 4–128 核的 TP 负载
olap.yml针对分析场景优化
crit.yml强调同步提交/最小延迟,适合金融等零丢失场景
tiny.yml轻量机 / 边缘场景 / 资源受限环境

你可以直接替换模板或自定义一个 YAML 文件放在 templates/ 下,然后在集群 vars 里指定。

pg-ledger:
  hosts: { 10.10.10.21: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-ledger
    pg_conf: crit.yml
    pg_parameters:
      synchronous_commit: 'remote_apply'
      max_wal_senders: 16
      wal_keep_size: '2GB'

效果:拷贝 crit.yml 作为 Patroni 配置,叠加 pg_parameters 写入 postgresql.auto.conf,使实例立即以同步提交模式运行。


组合实例:一个完整示例

pg-rag:
  hosts:
    10.10.10.31: { pg_seq: 1, pg_role: primary }
    10.10.10.32: { pg_seq: 2, pg_role: replica }
  vars:
    pg_cluster: pg-rag
    pg_version: 18
    pg_mode: pgsql
    pg_conf: olap.yml
    pg_packages: [ pgsql-main pgsql-common ]
    pg_extensions: [ pgvector, pgml, postgis ]
    pg_libs: 'pg_stat_statements, pgvector, pgml'
    pg_parameters:
      max_parallel_workers: 8
      shared_buffers: '32GB'
  • 第一台主库 + 一台 replica,使用 olap.yml 调优。
  • 安装 PG18 + RAG 常用扩展,自动在系统级加载 pgvector/pgml
  • Patroni/pgbouncer/pgbackrest 由 Pigsty 生成,无需手工干预。

根据业务需要替换上述参数即可完成内核层的全部定制。

3 - 别名翻译

Pigsty 提供软件包别名翻译机制,可以屏蔽底层操作系统的二进制包细节差异,让安装更简易。

PostgreSQL 在不同操作系统上的软件包命名规则存在显著差异:

  • EL 系统(RHEL/Rocky/Alma/…)使用 pgvector_17postgis36_17* 这样的格式
  • Debian/Ubuntu 系统使用 postgresql-17-pgvectorpostgresql-17-postgis-3 这样的格式

这种差异给用户带来了额外的认知负担:您需要记住不同系统的包名规则,还要处理 PostgreSQL 版本号嵌入的问题。

软件包别名

Pigsty 通过 软件包别名(Package Alias) 机制解决了这个问题:您只需使用统一的别名,Pigsty 会处理好所有细节:

# 使用别名 —— 简单、统一、跨平台
pg_extensions: [ postgis, pgvector, timescaledb ]

# 等效于 EL9 + PG17 上的实际包名
pg_extensions: [ postgis36_17*, pgvector_17*, timescaledb-tsl_17* ]

# 等效于 Ubuntu 24 + PG17 上的实际包名
pg_extensions: [ postgresql-17-postgis-3, postgresql-17-pgvector, postgresql-17-timescaledb-tsl ]

别名翻译

别名还可以将一组软件包归类为一个整体,例如 Pigsty 默认安装的软件包 —— pg_packages 的默认值是:

pg_packages:                      # pg packages to be installed, alias can be used
  - pgsql-main pgsql-common

Pigsty 将查询当前的操作系统别名清单(假设为 el10.x86_64),将其翻译为 PGSQL 内核,扩展,以及工具包:

pgsql-main:    "postgresql$v postgresql$v-server postgresql$v-libs postgresql$v-contrib postgresql$v-plperl postgresql$v-plpython3 postgresql$v-pltcl postgresql$v-llvmjit pg_repack_$v* wal2json_$v* pgvector_$v*"
pgsql-common:  "patroni patroni-etcd pgbouncer pgbackrest pg_exporter pgbackrest_exporter vip-manager"

接下来,Pigsty 又进一步通过当前指定的 PG 大版本(假设 pg_version = 18 ),将 pgsql-main 翻译为:

pg18-main:   "postgresql18 postgresql18-server postgresql18-libs postgresql18-contrib postgresql18-plperl postgresql18-plpython3 postgresql18-pltcl postgresql18-llvmjit pg_repack_18* wal2json_18* pgvector_18*"

通过这种方式,Pigsty 屏蔽了软件包的复杂性,让用户可以简单的指定自己想要的功能组件。


哪些变量可以使用别名?

您可以在以下四个参数中使用包别名,别名会根据翻译流程自动转换为实际的软件包名称:


别名列表

你可以在 Pigsty 项目源代码的 roles/node_id/vars/ 目录下,找到各操作系统与架构对应的别名映射文件:


工作原理

别名翻译流程

用户配置别名 --> 检测操作系统 -->  查找别名映射表 ---> 替换$v占位符 ---> 安装实际软件包
     ↓              ↓               ↓                               ↓
  postgis      el9.x86_64      postgis36_$v*                postgis36_17*
  postgis      u24.x86_64      postgresql-$v-postgis-3      postgresql-17-postgis-3

版本占位符

Pigsty 的别名系统使用 $v 作为 PostgreSQL 版本号的占位符。当您使用 pg_version 指定了 PostgreSQL 版本后,所有别名中的 $v 都会被替换为实际版本号。

例如,当 pg_version: 17 时:

别名定义 (EL)展开结果
postgresql$v*postgresql17*
pgvector_$v*pgvector_17*
timescaledb-tsl_$v*timescaledb-tsl_17*
别名定义 (Debian/Ubuntu)展开结果
postgresql-$vpostgresql-17
postgresql-$v-pgvectorpostgresql-17-pgvector
postgresql-$v-timescaledb-tslpostgresql-17-timescaledb-tsl

通配符匹配

在 EL 系统上,许多别名使用 * 通配符来匹配相关的子包。例如:

  • postgis36_17* 会匹配 postgis36_17postgis36_17-clientpostgis36_17-utils
  • postgresql17* 会匹配 postgresql17postgresql17-serverpostgresql17-libspostgresql17-contrib

这种设计确保您无需逐一列出每个子包,一个别名即可安装完整的扩展。

4 - 用户/角色

如何通过配置来定制所需 PostgreSQL 用户与角色?

在本文中,“用户”(User) 指的是使用 SQL 命令 CREATE USER/ROLE 创建的,数据库集簇内的逻辑对象。

在 PostgreSQL 中,用户直接隶属于数据库集簇而非某个具体的数据库。因此在创建业务数据库和业务用户时,应当遵循"先用户,后数据库"的原则。

Pigsty 通过两个配置参数定义数据库集群中的角色与用户:

  • pg_default_roles:定义全局统一使用的角色和用户
  • pg_users:在数据库集群层面定义业务用户和角色

前者用于定义整套环境中共用的角色与用户,后者定义单个集群中特有的业务角色与用户。二者形式相同,均为用户定义对象的数组。 用户/角色按数组顺序逐一创建,因此后定义的用户可以属于先定义的角色。

默认情况下,所有带有 pgbouncer: true 标记的用户都会被添加到 Pgbouncer 连接池用户列表中。


定义用户

下面是 Pigsty 演示环境中默认集群 pg-meta 中的业务用户定义:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_users:
      - {name: dbuser_meta     ,password: DBUser.Meta     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: pigsty admin user }
      - {name: dbuser_view     ,password: DBUser.Viewer   ,pgbouncer: true ,roles: [dbrole_readonly] ,comment: read-only viewer for meta database }
      - {name: dbuser_grafana  ,password: DBUser.Grafana  ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for grafana database    }
      - {name: dbuser_bytebase ,password: DBUser.Bytebase ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for bytebase database   }
      - {name: dbuser_kong     ,password: DBUser.Kong     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for kong api gateway    }
      - {name: dbuser_gitea    ,password: DBUser.Gitea    ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for gitea service       }
      - {name: dbuser_wiki     ,password: DBUser.Wiki     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for wiki.js service     }
      - {name: dbuser_noco     ,password: DBUser.Noco     ,pgbouncer: true ,roles: [dbrole_admin]    ,comment: admin user for nocodb service      }
      - {name: dbuser_remove   ,state: absent }  # 使用 state: absent 删除用户

每个用户/角色定义都是一个复杂对象,可能包括以下字段,除了 name 字段外,其他字段均为可选字段:

- name: dbuser_meta               # 必选,`name` 是用户定义的唯一必选字段
  state: create                   # 可选,用户状态:create(创建,默认)、absent(删除)
  password: DBUser.Meta           # 可选,密码,可以是 scram-sha-256 哈希字符串或明文
  login: true                     # 可选,默认为 true,是否可以登录
  superuser: false                # 可选,默认为 false,是否是超级用户
  createdb: false                 # 可选,默认为 false,是否可以创建数据库
  createrole: false               # 可选,默认为 false,是否可以创建角色
  inherit: true                   # 可选,默认为 true,是否自动继承所属角色权限
  replication: false              # 可选,默认为 false,是否可以发起流复制连接
  bypassrls: false                # 可选,默认为 false,是否可以绕过行级安全
  connlimit: -1                   # 可选,用户连接数限制,默认 -1 不限制
  expire_in: 3650                 # 可选,从创建时起 N 天后过期(优先级比 expire_at 高)
  expire_at: '2030-12-31'         # 可选,过期日期,使用 YYYY-MM-DD 格式(优先级没 expire_in 高)
  comment: pigsty admin user      # 可选,用户备注信息
  roles: [dbrole_admin]           # 可选,所属角色数组
  parameters:                     # 可选,角色级配置参数
    search_path: public
  pgbouncer: true                 # 可选,是否加入连接池用户列表,默认 false
  pool_mode: transaction          # 可选,用户级别的池化模式,默认 transaction
  pool_connlimit: -1              # 可选,用户级别的连接池最大连接数,默认 -1 不限制

参数总览

所有参数中唯一 必选 的字段是 name,它应该是当前 PostgreSQL 集群中有效且唯一的用户名,其他参数都有合理的默认值,均为可选项。

字段分类类型属性说明
name基本string必选用户名,必须是有效且唯一的标识符
state基本enum可选用户状态:create(默认)、absent
password基本string可变用户密码,明文或哈希
comment基本string可变用户备注信息
login权限bool可变是否允许登录,默认 true
superuser权限bool可变是否为超级用户,默认 false
createdb权限bool可变是否可创建数据库,默认 false
createrole权限bool可变是否可创建角色,默认 false
inherit权限bool可变是否继承所属角色权限,默认 true
replication权限bool可变是否可进行复制,默认 false
bypassrls权限bool可变是否可绕过行级安全,默认 false
connlimit权限int可变连接数限制,-1 表示不限制
expire_in有效期int可变从当前日期起 N 天后过期(优先级高于 expire_at
expire_at有效期string可变过期日期,YYYY-MM-DD 格式
roles角色array增量所属角色数组,支持字符串或对象格式
parameters参数object可变角色级参数
pgbouncer连接池bool可变是否加入连接池,默认 false
pool_mode连接池enum可变池化模式:transaction(默认)
pool_connlimit连接池int可变连接池用户最大连接数

参数详情

name

字符串,必选参数,表示用户的名称,在一个数据库集群内必须唯一。

用户名必须是有效的 PostgreSQL 标识符,必须匹配正则表达式 ^[a-z_][a-z0-9_]{0,62}$: 以小写字母或下划线开头,只能包含小写字母、数字、下划线,最长 63 个字符。

- name: dbuser_app         # 标准命名
- name: app_readonly       # 下划线分隔
- name: _internal          # 下划线开头(用于内部角色)

state

枚举值,用于指定要对用户执行的操作,可以是 createabsent,默认值为 create

状态说明
create默认,创建用户,如果已存在则更新属性
absent删除用户,使用 DROP ROLE
- name: dbuser_app             # state 默认为 create
- name: dbuser_old
  state: absent                # 删除用户

以下系统用户无法通过 state: absent 删除,这是为了防止误删关键系统用户导致集群故障:

password

字符串,可变参数,用于设置用户密码,不指定则用户无法使用密码登录。

密码可以是以下格式之一:

格式示例说明
明文密码DBUser.Meta不推荐,会被记录到配置文件和日志
SCRAM-SHA-256SCRAM-SHA-256$4096:xxx$yyy:zzz推荐,PostgreSQL 10+ 默认认证方式
MD5 哈希md5...兼容旧版本,不推荐新项目使用
# 明文密码(不推荐,会被记录到配置和日志中)
- name: dbuser_app
  password: MySecretPassword

# SCRAM-SHA-256 哈希(推荐)
- name: dbuser_app
  password: 'SCRAM-SHA-256$4096:xxx$yyy:zzz'

设置密码时,Pigsty 会临时屏蔽当前会话的日志记录以避免密码泄露:

SET log_statement TO 'none';
ALTER USER "dbuser_app" PASSWORD 'xxx';
SET log_statement TO DEFAULT;

如果你不希望在配置文件中记录明文密码,可以使用 SCRAM-SHA-256 哈希字符串代替明文密码。生成 SCRAM-SHA-256 哈希的方法:

# 使用 PostgreSQL 生成(需要先连接到数据库,数据库有 pgcrypto 扩展)
psql -c "SELECT encode(digest('password' || 'username', 'sha256'), 'hex')"

comment

字符串,可变参数,用于设置用户的备注信息,如果不指定,默认值为 business user {name}

用户备注信息通过 COMMENT ON ROLE 语句设置,支持中文和特殊字符(Pigsty 会自动转义单引号)。

- name: dbuser_app
  comment: '业务应用主账号'
COMMENT ON ROLE "dbuser_app" IS '业务应用主账号';

login

布尔值,可变参数,用于控制用户是否可以登录,默认值为 true

设置为 false 则创建的是无法登陆的 角色(Role)而非用户(User),通常用于权限分组。

在 PostgreSQL 中,CREATE USER 等价于 CREATE ROLE ... LOGIN

# 创建可登录用户
- name: dbuser_app
  login: true

# 创建角色(不可登录,用于权限分组)
- name: dbrole_custom
  login: false
  comment: 自定义权限角色
CREATE USER "dbuser_app" LOGIN;
CREATE USER "dbrole_custom" NOLOGIN;

superuser

布尔值,可变参数,用于指定用户是否为超级用户,默认值为 false

超级用户拥有数据库的全部权限,可以绕过所有权限检查。

- name: dbuser_admin
  superuser: true            # 危险:拥有全部权限
ALTER USER "dbuser_admin" SUPERUSER;

Pigsty 已经提供了默认的超级用户 pg_admin_usernamedbuser_dba) 除非绝对必要,否则不应创建额外的超级用户。

createdb

布尔值,可变参数,用于指定用户是否可以创建数据库,默认值为 false

- name: dbuser_dev
  createdb: true             # 允许创建数据库
ALTER USER "dbuser_dev" CREATEDB;

一些应用软件可能会要求自己创建数据库,例如 GiteaOdoo 等,因此您可能需要为这些应用的管理员用户启用 CREATEDB 权限。

createrole

布尔值,可变参数,用于指定用户是否可以创建其他角色,默认值为 false

拥有 CREATEROLE 权限的用户可以创建、修改、删除其他非超级用户角色。

- name: dbuser_admin
  createrole: true           # 允许管理其他角色
ALTER USER "dbuser_admin" CREATEROLE;

inherit

布尔值,可变参数,用于控制用户是否自动继承所属角色的权限,默认值为 true

设置为 false 时,用户需要通过 SET ROLE 显式切换角色才能使用所属角色的权限。

# 自动继承角色权限(默认)
- name: dbuser_app
  inherit: true
  roles: [dbrole_readwrite]

# 需要显式切换角色
- name: dbuser_special
  inherit: false
  roles: [dbrole_admin]
ALTER USER "dbuser_special" NOINHERIT;
-- 用户需要执行 SET ROLE dbrole_admin 才能获得该角色权限(必要但不充分)

replication

布尔值,可变参数,用于指定用户是否可以发起流复制连接,默认值为 false

通常只有复制用户(如 replicator)需要此权限。普通业务用户不应该拥有此权限,除非这是一个逻辑解码订阅者。

- name: replicator
  replication: true          # 允许流复制连接
  roles: [pg_monitor, dbrole_readonly]
ALTER USER "replicator" REPLICATION;

bypassrls

布尔值,可变参数,用于指定用户是否可以绕过行级安全(RLS)策略,默认值为 false

启用此权限后,用户可以访问所有行,即使表上定义了行级安全策略。此权限通常只授予管理员用户。

- name: dbuser_myappadmin
  bypassrls: true            # 绕过行级安全策略
ALTER USER "dbuser_myappadmin" BYPASSRLS;

connlimit

整数,可变参数,用于限制用户的最大并发连接数,默认值为 -1,表示不限制。

设置为正整数时,会限制该用户同时建立的最大数据库连接数。此限制不影响超级用户。

- name: dbuser_app
  connlimit: 100             # 最多 100 个并发连接

- name: dbuser_batch
  connlimit: 10              # 批处理用户限制连接数
ALTER USER "dbuser_app" CONNECTION LIMIT 100;

expire_in

整数,可变参数,用于指定用户从当前日期起多少天后过期。

此参数优先级高于 expire_at,如果同时指定两者,只有 expire_in 生效。

每次执行剧本时会根据当前日期重新计算过期时间,适合用于临时用户或需要定期续期的场景。

- name: temp_user
  expire_in: 30              # 30 天后过期

- name: contractor_user
  expire_in: 90              # 90 天后过期

执行时会计算实际过期日期并生成对应的 SQL:

-- expire_in: 30, 假设当前日期为 2025-01-01
ALTER USER "temp_user" VALID UNTIL '2025-01-31';

expire_at

字符串,可变参数,用于指定用户的过期日期,格式为 YYYY-MM-DD 或特殊值 infinity

此参数优先级低于 expire_in。使用 infinity 表示用户永不过期。

- name: contractor_user
  expire_at: '2024-12-31'    # 指定日期过期

- name: permanent_user
  expire_at: 'infinity'      # 永不过期
ALTER USER "contractor_user" VALID UNTIL '2024-12-31';
ALTER USER "permanent_user" VALID UNTIL 'infinity';

roles

数组,增量参数,用于定义用户所属的角色。数组元素可以是字符串或对象。

简单格式使用字符串直接指定角色名:

- name: dbuser_app
  roles:
    - dbrole_readwrite
    - pg_read_all_data
GRANT "dbrole_readwrite" TO "dbuser_app";
GRANT "pg_read_all_data" TO "dbuser_app";

完整格式使用对象定义,支持更精细的角色成员关系控制:

- name: dbuser_app
  roles:
    - dbrole_readwrite                            # 简单字符串:GRANT 角色
    - { name: dbrole_admin, admin: true }         # 带 ADMIN OPTION
    - { name: pg_monitor, set: false }            # PG16+: 不允许 SET ROLE
    - { name: pg_signal_backend, inherit: false } # PG16+: 不自动继承权限
    - { name: old_role, state: absent }           # 撤销角色成员关系

对象格式参数说明

参数类型说明
namestring角色名称(必选)
stateenumgrant(默认)或 absent/revoke:控制授予或撤销
adminbooltrue:WITH ADMIN OPTION,false:REVOKE ADMIN
setboolPG16+:true:WITH SET TRUE,false:REVOKE SET
inheritboolPG16+:true:WITH INHERIT TRUE,false:REVOKE INHERIT

PostgreSQL 16+ 新特性

PostgreSQL 16 引入了更细粒度的角色成员关系控制:

  • ADMIN OPTION:允许将角色授予其他用户
  • SET OPTION:允许使用 SET ROLE 切换到该角色
  • INHERIT OPTION:是否自动继承该角色的权限
# PostgreSQL 16+ 完整示例
- name: dbuser_app
  roles:
    # 普通成员关系
    - dbrole_readwrite

    # 可以将 dbrole_admin 授予其他用户
    - { name: dbrole_admin, admin: true }

    # 不能 SET ROLE 到 pg_monitor(只能通过继承使用权限)
    - { name: pg_monitor, set: false }

    # 不自动继承 pg_execute_server_program 的权限(需要显式 SET ROLE)
    - { name: pg_execute_server_program, inherit: false }

    # 撤销 old_role 的成员关系
    - { name: old_role, state: absent }

setinherit 选项仅在 PostgreSQL 16+ 中有效,在早期版本会被忽略并在生成的 SQL 中添加警告注释。

parameters

对象,可变参数,用于设置角色级别的配置参数。参数通过 ALTER ROLE ... SET 设置,会对该用户的所有会话生效。

- name: dbuser_analyst
  parameters:
    work_mem: '256MB'
    statement_timeout: '5min'
    search_path: 'analytics,public'
    log_statement: 'all'
ALTER USER "dbuser_analyst" SET "work_mem" = '256MB';
ALTER USER "dbuser_analyst" SET "statement_timeout" = '5min';
ALTER USER "dbuser_analyst" SET "search_path" = 'analytics,public';
ALTER USER "dbuser_analyst" SET "log_statement" = 'all';

使用特殊值 DEFAULT(大小写不敏感)可以将参数重置为 PostgreSQL 默认值:

- name: dbuser_app
  parameters:
    work_mem: DEFAULT          # 重置为默认值
    statement_timeout: '30s'   # 设置新值
ALTER USER "dbuser_app" SET "work_mem" = DEFAULT;
ALTER USER "dbuser_app" SET "statement_timeout" = '30s';

常用角色级参数:

参数说明示例值
work_mem查询工作内存'64MB'
statement_timeout语句超时时间'30s'
lock_timeout锁等待超时'10s'
idle_in_transaction_session_timeout空闲事务超时'10min'
search_pathSchema 搜索路径'app,public'
log_statement日志记录级别'ddl'
temp_file_limit临时文件大小限制'10GB'

您可以从数据库的 pg_db_role_setting 系统视图查询用户级别的参数设置。

pgbouncer

布尔值,可变参数,用于控制是否将用户添加到 Pgbouncer 连接池用户列表,默认值为 false

对于需要通过连接池访问数据库的生产用户,必须显式设置 pgbouncer: true。 默认为 false 是为了避免意外将内部用户暴露给连接池。

# 生产用户:需要连接池
- name: dbuser_app
  password: DBUser.App
  pgbouncer: true

# 内部用户:不需要连接池
- name: dbuser_internal
  password: DBUser.Internal
  pgbouncer: false           # 默认值,可省略

设置 pgbouncer: true 的用户会被添加到 /etc/pgbouncer/userlist.txt 文件中。

pool_mode

枚举值,可变参数,用于设置用户级别的池化模式,可选值为 transactionsessionstatement,默认值为 transaction

模式说明适用场景
transaction事务结束后归还连接大多数 OLTP 应用,默认推荐
session会话结束后归还连接需要会话状态的应用(如 SET 命令)
statement每条语句后归还连接简单无状态查询,极致复用
# DBA 用户使用 session 模式(可能需要 SET 命令等会话状态)
- name: dbuser_dba
  pgbouncer: true
  pool_mode: session

# 普通业务用户使用 transaction 模式
- name: dbuser_app
  pgbouncer: true
  pool_mode: transaction

用户级别的连接池参数通过 /etc/pgbouncer/useropts.txt 文件配置:

dbuser_dba      = pool_mode=session max_user_connections=16
dbuser_monitor  = pool_mode=session max_user_connections=8

pool_connlimit

整数,可变参数,用于设置用户级别的连接池最大连接数,默认值为 -1,表示不限制。

- name: dbuser_app
  pgbouncer: true
  pool_connlimit: 50         # 此用户最多使用 50 个连接池连接

ACL 系统

Pigsty 提供了一套内置的、开箱即用的访问控制 / ACL 系统,您只需将以下四个默认角色分配给业务用户即可轻松使用:

角色权限说明典型使用场景
dbrole_readwrite全局读写访问主属业务的生产账号
dbrole_readonly全局只读访问其他业务的只读访问
dbrole_admin拥有 DDL 权限业务管理员,需要建表的场景
dbrole_offline受限只读访问(仅离线实例)个人用户,ETL/分析任务
# 典型业务用户配置
pg_users:
  - name: dbuser_app
    password: DBUser.App
    pgbouncer: true
    roles: [dbrole_readwrite]    # 生产账号,读写权限

  - name: dbuser_readonly
    password: DBUser.Readonly
    pgbouncer: true
    roles: [dbrole_readonly]     # 只读账号

  - name: dbuser_admin
    password: DBUser.Admin
    pgbouncer: true
    roles: [dbrole_admin]        # 管理员,可执行 DDL

  - name: dbuser_etl
    password: DBUser.ETL
    roles: [dbrole_offline]      # 离线分析账号

如果您希望重新设计您自己的 ACL 系统,可以考虑定制以下参数和模板:


Pgbouncer 用户

默认情况下启用 Pgbouncer 作为连接池中间件。Pigsty 默认将 pg_users 中显式带有 pgbouncer: true 标志的所有用户添加到 Pgbouncer 用户列表中。

Pgbouncer 连接池中的用户在 /etc/pgbouncer/userlist.txt 中列出:

"postgres" ""
"dbuser_wiki" "SCRAM-SHA-256$4096:+77dyhrPeFDT/TptHs7/7Q==$KeatuohpKIYzHPCt/tqBu85vI11o9mar/by0hHYM2W8=:X9gig4JtjoS8Y/o1vQsIX/gY1Fns8ynTXkbWOjUfbRQ="
"dbuser_view" "SCRAM-SHA-256$4096:DFoZHU/DXsHL8MJ8regdEw==$gx9sUGgpVpdSM4o6A2R9PKAUkAsRPLhLoBDLBUYtKS0=:MujSgKe6rxcIUMv4GnyXJmV0YNbf39uFRZv724+X1FE="
"dbuser_monitor" "SCRAM-SHA-256$4096:fwU97ZMO/KR0ScHO5+UuBg==$CrNsmGrx1DkIGrtrD1Wjexb/aygzqQdirTO1oBZROPY=:L8+dJ+fqlMQh7y4PmVR/gbAOvYWOr+KINjeMZ8LlFww="
"dbuser_meta" "SCRAM-SHA-256$4096:leB2RQPcw1OIiRnPnOMUEg==$eyC+NIMKeoTxshJu314+BmbMFpCcspzI3UFZ1RYfNyU=:fJgXcykVPvOfro2MWNkl5q38oz21nSl1dTtM65uYR1Q="

用户级别的连接池参数使用另一个单独的文件 /etc/pgbouncer/useropts.txt 进行维护:

dbuser_dba      = pool_mode=session max_user_connections=16
dbuser_monitor  = pool_mode=session max_user_connections=8

当您 创建用户 时,Pgbouncer 的用户列表定义文件将会被刷新,并通过在线重载配置的方式生效,不会影响现有的连接。

Pgbouncer 使用和 PostgreSQL 相同的 dbsu 运行,默认为 postgres 操作系统用户。您可以使用 pgb 别名,使用 dbsu 访问 Pgbouncer 管理功能。

pgbouncer_auth_query 参数允许您使用动态查询来完成连接池用户认证,当您不想手动管理连接池中的用户时,这是一种便捷的方案。


相关资源

关于用户管理操作,请参考 用户管理 一节。

关于用户的访问权限,请参考 ACL:角色权限 一节。

5 - 数据库

如何通过配置来定制所需 PostgreSQL 数据库?

在本文中,“数据库”(Database) 指的是使用 SQL 命令 CREATE DATABASE 创建的,数据库集簇内的逻辑对象。

一组 PostgreSQL 服务器可以同时服务于多个 数据库 (Database)。在 Pigsty 中,你可以在集群配置中 定义 好所需的数据库。

Pigsty会对默认模板数据库template1进行修改与定制,创建默认模式,安装默认扩展,配置默认权限,新创建的数据库默认会从template1继承这些设置。 您也可以通过 template 参数指定其他模板数据库,实现瞬间 数据库克隆

默认情况下,所有业务数据库都会被 1:1 添加到 Pgbouncer 连接池 中;pg_exporter 默认会通过 自动发现 机制查找所有业务数据库并进行库内对象监控。 所有数据库也会添加到所有 INFRA节点 上的 Grafana 中, 注册为 PostgreSQL 数据源供 PGCAT 监控面板使用。


定义数据库

业务数据库定义在数据库集群参数 pg_databases 中,这是一个数据库定义构成的对象数组。 在集群初始化时,数组内的数据库按照 定义顺序 依次创建,因此后面定义的数据库可以使用先前定义的数据库作为模板

下面是 Pigsty 演示环境中默认集群 pg-meta 中的数据库定义:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_databases:
      - { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [{name: postgis, schema: public}, {name: timescaledb}]}
      - { name: grafana  ,owner: dbuser_grafana  ,revokeconn: true ,comment: grafana primary database }
      - { name: bytebase ,owner: dbuser_bytebase ,revokeconn: true ,comment: bytebase primary database }
      - { name: kong     ,owner: dbuser_kong     ,revokeconn: true ,comment: kong the api gateway database }
      - { name: gitea    ,owner: dbuser_gitea    ,revokeconn: true ,comment: gitea meta database }
      - { name: wiki     ,owner: dbuser_wiki     ,revokeconn: true ,comment: wiki meta database }
      - { name: noco     ,owner: dbuser_noco     ,revokeconn: true ,comment: nocodb database }

每个数据库定义都是一个复杂对象,可能包括以下字段,除了 name 字段外,其他字段均为可选字段:

- name: meta                      # 必选,`name` 是数据库定义的唯一必选字段
  state: create                   # 可选,数据库状态:create(创建,默认)、absent(删除)、recreate(重建)
  baseline: cmdb.sql              # 可选,数据库 sql 的基线定义文件路径(ansible 搜索路径中的相对路径,如 files/)
  pgbouncer: true                 # 可选,是否将此数据库添加到 pgbouncer 数据库列表?默认为 true
  schemas: [pigsty]               # 可选,要创建的附加模式,由模式名称字符串组成的数组
  extensions:                     # 可选,要安装的附加扩展: 扩展对象的数组
    - { name: postgis , schema: public }  # 可以指定将扩展安装到某个模式中,也可以不指定(不指定则安装到 search_path 首位模式中)
    - { name: timescaledb }               # 例如有的扩展会创建并使用固定的模式,就不需要指定模式。
  comment: pigsty meta database   # 可选,数据库的说明与备注信息
  owner: postgres                 # 可选,数据库所有者,不指定则为当前用户
  template: template1             # 可选,要使用的模板,默认为 template1,目标必须是一个模板数据库
  strategy: FILE_COPY             # 可选,克隆策略:FILE_COPY 或 WAL_LOG(PG15+),不指定使用 PG 默认
  encoding: UTF8                  # 可选,不指定则继承模板/集群配置(UTF8)
  locale: C                       # 可选,不指定则继承模板/集群配置(C)
  lc_collate: C                   # 可选,不指定则继承模板/集群配置(C)
  lc_ctype: C                     # 可选,不指定则继承模板/集群配置(C)
  locale_provider: libc           # 可选,本地化提供者:libc、icu、builtin(PG15+)
  icu_locale: en-US               # 可选,ICU 本地化规则(PG15+)
  icu_rules: ''                   # 可选,ICU 排序规则(PG16+)
  builtin_locale: C.UTF-8         # 可选,内置本地化提供者规则(PG17+)
  tablespace: pg_default          # 可选,默认表空间,默认为 'pg_default'
  is_template: false              # 可选,是否标记为模板数据库,允许任何有 CREATEDB 权限的用户克隆
  allowconn: true                 # 可选,是否允许连接,默认为 true。显式设置 false 将完全禁止连接到此数据库
  revokeconn: false               # 可选,撤销公共连接权限。默认为 false,设置为 true 时,属主和管理员之外用户的 CONNECT 权限会被回收
  register_datasource: true       # 可选,是否将此数据库注册到 grafana 数据源?默认为 true,显式设置为 false 会跳过注册
  connlimit: -1                   # 可选,数据库连接限制,默认为 -1 ,不限制,设置为正整数则会限制连接数。
  parameters:                     # 可选,数据库级参数,通过 ALTER DATABASE SET 设置
    work_mem: '64MB'
    statement_timeout: '30s'
  pool_auth_user: dbuser_meta     # 可选,连接到此 pgbouncer 数据库的所有连接都将使用此用户进行验证(启用 pgbouncer_auth_query 才有用)
  pool_mode: transaction          # 可选,数据库级别的 pgbouncer 池化模式,默认为 transaction
  pool_size: 64                   # 可选,数据库级别的 pgbouncer 默认池子大小,默认为 64
  pool_reserve: 32                # 可选,数据库级别的 pgbouncer 池子保留空间,默认为 32,当默认池子不够用时,最多再申请这么多条突发连接。
  pool_size_min: 0                # 可选,数据库级别的 pgbouncer 池的最小大小,默认为 0
  pool_connlimit: 100             # 可选,数据库级别的最大数据库连接数,默认为 100

参数总览

所有参数中唯一 必选 的字段是 name,它应该是当前 PostgreSQL 集群中有效且唯一的数据库名称,其他参数都有合理的默认值,均为可选项。 带有 “不可变” 标记的参数仅在数据库创建时生效,创建后无法修改,若需更改则必须删除并重建数据库。

字段分类类型属性说明
name基本string必选数据库名称,必须是有效且唯一的标识符
state基本enum可选数据库状态:create(默认)、absentrecreate
owner基本string可变数据库属主,不指定则为 postgres
comment基本string可变数据库备注信息
template模板string不可变创建时使用的模板数据库,默认 template1
strategy模板enum不可变克隆策略:FILE_COPYWAL_LOG(PG15+)
encoding编码string不可变字符编码,默认继承模板(UTF8
locale编码string不可变本地化规则,默认继承模板(C
lc_collate编码string不可变排序规则,默认继承模板(C
lc_ctype编码string不可变字符分类,默认继承模板(C
locale_provider编码enum不可变本地化提供者:libcicubuiltin(PG15+)
icu_locale编码string不可变ICU 本地化规则(PG15+)
icu_rules编码string不可变ICU 排序定制规则(PG16+)
builtin_locale编码string不可变内置本地化规则(PG17+)
tablespace存储string可变默认表空间,修改会触发数据迁移
is_template权限bool可变是否标记为模板数据库
allowconn权限bool可变是否允许连接,默认 true
revokeconn权限bool可变是否回收 PUBLIC 的 CONNECT 权限
connlimit权限int可变连接数限制,-1 表示不限制
baseline初始化string可变SQL 基线文件路径,仅首次创建时执行
schemas初始化(string|object)[]可变要创建的模式定义数组
extensions初始化(string|object)[]可变要安装的扩展定义数组
parameters初始化object可变数据库级参数
pgbouncer连接池bool可变是否加入连接池,默认 true
pool_mode连接池enum可变池化模式:transaction(默认)
pool_size连接池int可变默认池大小,默认 64
pool_size_min连接池int可变最小池大小,默认 0
pool_reserve连接池int可变保留池大小,默认 32
pool_connlimit连接池int可变最大数据库连接数,默认 100
pool_auth_user连接池string可变认证查询用户
register_datasource监控bool可变是否注册到 Grafana 数据源,默认 true

参数详情

name

字符串,必选参数,表示数据库的名称,在一个数据库集群内集群内必须唯一。

数据库名称必须是有效的 PostgreSQL 标识符,长度不超过 63 个字符,不得使用 SQL 关键字, 形式上以字母或下划线开头,后续字符可以是字母、数字或下划线,不能包含空格或特殊字符。 形式应当满足正则表达式:^[A-Za-z_][A-Za-z0-9_$]{0,62}$

- name: myapp              # 简单命名
- name: my_application     # 下划线分隔
- name: app_v2             # 包含版本号

state

枚举值,用于指定要对数据库执行的操作,可以是 createabsentrecreate,默认值为 create

状态说明
create默认,创建或修改数据库,如果已经存在,则将可变参数调整到描述的状态
absent删除数据库,使用 DROP DATABASE WITH (FORCE)
recreate先删除再创建,用于重置数据库
- name: myapp                # state 默认为 create
- name: olddb
  state: absent              # 删除数据库
- name: testdb
  state: recreate            # 重建数据库

owner

字符串,指定数据库的属主用户,默认不指定,不指定则为数据库 pg_dbsu,即 postgres 用户。

要指定数据库的 owner,被指定的用户必须已存在。修改 owner 会执行:旧 Owner 在数据库上的权限不会被撤回。

数据库属主具有对数据库的完全控制权限,包括创建模式、表、扩展等对象的权限,对于多租户场景尤为有用。

ALTER DATABASE "myapp" OWNER TO "new_owner";
GRANT ALL PRIVILEGES ON DATABASE "myapp" TO "new_owner";

comment

字符串,用于设置数据库的备注信息,如果不指定,默认值为 business database {name}

数据库备注信息通过 COMMENT ON DATABASE 语句设置,支持中文和特殊字符(Pigsty 会自动转义单引号)。 备注信息会存储在系统目录 pg_database.datacl 中,可以通过 \l+ 命令查看。

COMMENT ON DATABASE "myapp" IS '我的应用主数据库';
- name: myapp
  comment: 我的应用主数据库

template

字符串,不可变参数,用于指定创建数据库时使用的模板数据库,默认值为 template1

PostgreSQL 的 CREATE DATABASE 本质上是对模板数据库进行复制,新数据库会继承模板中的所有对象、扩展、模式、权限设置等。 Pigsty 会在集群初始化阶段对 template1 进行定制配置,因此新建数据库默认会继承这些设置。

模板说明
template1默认模板,包含 Pigsty 预配置的扩展、模式和权限设置
template0干净模板,使用不同于集群默认的本地化提供者时,必须使用此模板
自定义数据库可以使用已有数据库作为模板进行克隆

使用 icubuiltin 本地化提供者时,必须指定 template: template0,因为 template1 已有本地化设置无法覆盖。 使用其他

- name: myapp_icu
  template: template0        # 使用 ICU 时必须指定 template0
  locale_provider: icu
  icu_locale: zh-Hans

使用 template0 时,监控所需的扩展与 Schema,以及角色的默认权限都不再自动创建,这允许你从一个完全干净的模板开始定制数据库。

strategy

枚举值,不可变参数,用于指定从模板克隆数据库的策略,可选值为 FILE_COPYWAL_LOG,此参数在 PostgreSQL 15 及以上版本可用。

策略说明适用场景
FILE_COPY直接复制数据文件,PG15+ 默认大模板,通用场景
WAL_LOG通过 WAL 日志记录复制小模板,不阻塞模板上的连接

WAL_LOG 策略的优势是复制过程中不会阻塞模板数据库上的连接,但对于较大的模板效率不如 FILE_COPY。 在 PostgreSQL 14 及更早版本中,此参数会被忽略。

- name: cloned_db
  template: source_db
  strategy: WAL_LOG          # 使用 WAL 日志方式克隆

encoding

字符串,不可变参数,用于指定数据库的字符编码,如果不指定则继承模板数据库的编码设置,通常为 UTF8

如果没有特殊原因,强烈建议使用 UTF8 编码。字符编码在数据库创建后无法修改,如需更改必须重建数据库。

- name: legacy_db
  template: template0        # 指定非默认编码时使用 template0
  encoding: LATIN1

locale

字符串,不可变参数,用于指定数据库的本地化规则,相当于同时设置 lc_collatelc_ctype,如果不指定则继承模板数据库的设置,通常为 C

本地化规则决定了字符串的排序顺序和字符分类行为。使用 CPOSIX 可获得最佳性能和跨平台一致性, 使用特定语言的本地化规则(如 zh_CN.UTF-8)可以获得符合该语言习惯的排序结果。

- name: chinese_db
  template: template0
  locale: zh_CN.UTF-8        # 中文本地化
  encoding: UTF8

lc_collate

字符串,不可变参数,用于指定字符串的排序规则,如果不指定则继承模板数据库的设置,通常为 C

排序规则决定了 ORDER BY 和比较操作的结果。常用值包括:C(字节序,最快)、C.UTF-8en_US.UTF-8zh_CN.UTF-8。 此参数在数据库创建后无法修改。

- name: myapp
  template: template0
  lc_collate: en_US.UTF-8    # 英文排序规则
  lc_ctype: en_US.UTF-8

lc_ctype

字符串,不可变参数,用于指定字符分类规则,决定字符的大小写、数字、字母等分类,如果不指定则继承模板数据库的设置,通常为 C

字符分类规则影响 upper()lower()、正则表达式中的 \w 等函数的行为。此参数在数据库创建后无法修改。

locale_provider

枚举值,不可变参数,用于指定本地化的实现提供者,可选值为 libcicubuiltin,此参数在 PostgreSQL 15 及以上版本可用,默认值为 libc

提供者版本说明
libc-使用操作系统 C 库,传统默认方式,行为因系统而异
icuPG15+使用 ICU 库,跨平台一致,支持更多语言
builtinPG17+PostgreSQL 内置实现,最高效,仅支持 C/C.UTF-8

使用 icubuiltin 提供者时,必须指定 template: template0,并配合相应的 icu_localebuiltin_locale 参数。

- name: fast_db
  template: template0
  locale_provider: builtin   # 使用内置提供者,最高效
  builtin_locale: C.UTF-8

icu_locale

字符串,不可变参数,用于指定 ICU 本地化规则标识符,此参数在 PostgreSQL 15 及以上版本、且 locale_providericu 时可用。

ICU 本地化标识符遵循 BCP 47 标准,常用值包括:

说明
en-US美式英语
en-GB英式英语
zh-Hans简体中文
zh-Hant繁体中文
ja-JP日语
ko-KR韩语
- name: chinese_app
  template: template0
  locale_provider: icu
  icu_locale: zh-Hans        # 简体中文 ICU 排序
  encoding: UTF8

icu_rules

字符串,不可变参数,用于自定义 ICU 排序规则,此参数在 PostgreSQL 16 及以上版本可用。

ICU 规则允许对默认排序行为进行微调,使用 ICU 排序规则语法

- name: custom_sort_db
  template: template0
  locale_provider: icu
  icu_locale: en-US
  icu_rules: '&V << w <<< W'  # 自定义 V/W 排序顺序

builtin_locale

字符串,不可变参数,用于指定内置本地化提供者的规则,此参数在 PostgreSQL 17 及以上版本、且 locale_providerbuiltin 时可用,可选值为 CC.UTF-8

builtin 提供者是 PostgreSQL 17 新增的内置本地化实现,比 libc 更快,且行为跨平台完全一致。 适合只需要 CC.UTF-8 排序规则的场景。

- name: fast_db
  template: template0
  locale_provider: builtin
  builtin_locale: C.UTF-8    # 内置 UTF-8 支持
  encoding: UTF8

tablespace

字符串,可变参数,用于指定数据库的默认表空间,默认值为 pg_default

修改现有数据库的表空间会触发数据物理迁移,PostgreSQL 会将数据库中的所有对象移动到新表空间,对于大数据库可能需要较长时间,慎用。

- name: archive_db
  tablespace: slow_hdd       # 归档数据使用慢速存储
ALTER DATABASE "archive_db" SET TABLESPACE "slow_hdd";

is_template

布尔值,可变参数,用于指定是否将数据库标记为模板数据库,默认值为 false

设置为 true 后,任何拥有 CREATEDB 权限的用户都可以使用此数据库作为模板克隆新数据库。 模板数据库通常用于预装标准模式、扩展和数据,方便快速创建具有相同配置的新数据库。

- name: app_template
  is_template: true          # 标记为模板,允许普通用户克隆
  schemas: [core, api]
  extensions: [postgis, pg_trgm]

删除标记为 is_template: true 的数据库时,Pigsty 会先执行 ALTER DATABASE ... IS_TEMPLATE false 取消模板标记,然后再删除。

allowconn

布尔值,可变参数,用于控制是否允许连接到此数据库,默认值为 true

设置为 false 会在数据库层面完全禁止连接,任何用户(包括超级用户)都无法连接到此数据库。 此参数通常用于维护或归档用途。

- name: archive_db
  allowconn: false           # 禁止任何连接
ALTER DATABASE "archive_db" ALLOW_CONNECTIONS false;

revokeconn

布尔值,可变参数,用于控制是否回收 PUBLIC 角色的 CONNECT 权限,默认值为 false

设置为 true 时,Pigsty 会执行以下权限变更:

  • 回收 PUBLIC 的 CONNECT 权限,普通用户将无法连接
  • 授予复制用户(replicator)和监控用户(dbuser_monitor)连接权限
  • 授予管理员用户(dbuser_dba)和数据库属主连接权限,并附带 WITH GRANT OPTION

设置为 false 时,会恢复 PUBLIC 的 CONNECT 权限。

- name: secure_db
  owner: dbuser_secure
  revokeconn: true           # 回收公共连接权限,只有指定用户可连接

connlimit

整数,可变参数,用于限制数据库的最大并发连接数,默认值为 -1,表示不限制。

设置为正整数时,会限制同时连接到此数据库的最大会话数。此限制不影响超级用户。

- name: limited_db
  connlimit: 50              # 最多允许 50 个并发连接
ALTER DATABASE "limited_db" CONNECTION LIMIT 50;

baseline

字符串,一次性参数,用于指定数据库创建后要执行的 SQL 基线文件路径。

基线文件通常包含表结构定义、初始数据、存储过程等,用于初始化新数据库。 路径是相对于 Ansible 搜索路径的相对路径,通常放在 files/ 目录下。

基线文件仅在首次创建数据库时执行;如果数据库已存在则跳过。使用 state: recreate 重建数据库时会重新执行基线文件。

- name: myapp
  baseline: myapp_schema.sql  # 会查找 files/myapp_schema.sql

schemas

数组,可变参数(支持增删),用于定义要在数据库中创建或删除的模式。数组元素可以是字符串或对象。

简单格式使用字符串直接指定模式名,仅支持创建操作:

schemas:
  - app
  - api
  - core

完整格式使用对象定义,支持指定模式属主和删除操作:

schemas:
  - name: app                # 模式名(必选)
    owner: dbuser_app        # 模式属主(可选),生成 AUTHORIZATION 子句
  - name: deprecated
    state: absent            # 删除模式(使用 CASCADE)

创建模式时使用 IF NOT EXISTS,已存在则跳过;删除模式时使用 CASCADE,会同时删除模式内的所有对象。

CREATE SCHEMA IF NOT EXISTS "app" AUTHORIZATION "dbuser_app";
DROP SCHEMA IF EXISTS "deprecated" CASCADE;

extensions

数组,可变参数(支持增删),用于定义要在数据库中安装或卸载的扩展。数组元素可以是字符串或对象。

简单格式使用字符串直接指定扩展名,仅支持安装操作:

extensions:
  - postgis
  - pg_trgm
  - vector

完整格式使用对象定义,支持指定安装模式、版本和卸载操作:

extensions:
  - name: vector             # 扩展名(必选)
    schema: public           # 安装到指定模式(可选)
    version: '0.5.1'         # 指定版本(可选)
  - name: old_extension
    state: absent            # 卸载扩展(使用 CASCADE)

安装扩展时使用 CASCADE,如果已存在则会报错但跳过,同时自动安装依赖扩展;卸载扩展时使用 CASCADE,会同时删除依赖此扩展的对象。

CREATE EXTENSION IF NOT EXISTS "vector" WITH SCHEMA "public" VERSION '0.5.1' CASCADE;
DROP EXTENSION IF EXISTS "old_extension" CASCADE;

parameters

对象,可变参数,用于设置数据库级别的配置参数。参数通过 ALTER DATABASE ... SET 设置,会对连接到此数据库的所有会话生效。

- name: analytics
  parameters:
    work_mem: '256MB'
    maintenance_work_mem: '512MB'
    statement_timeout: '5min'
    search_path: 'analytics,public'

使用特殊值 DEFAULT(大小写不敏感)可以将参数重置为 PostgreSQL 默认值:

parameters:
  work_mem: DEFAULT          # 重置为默认值
  statement_timeout: '30s'   # 设置新值
ALTER DATABASE "myapp" SET "work_mem" = DEFAULT;
ALTER DATABASE "myapp" SET "statement_timeout" = '30s';

pgbouncer

布尔值,可变参数,用于控制是否将数据库添加到 Pgbouncer 连接池列表,默认值为 true

设置为 false 时,数据库不会出现在 Pgbouncer 的数据库列表中,客户端无法通过连接池访问此数据库。 适用于内部管理数据库或需要直连的特殊场景。

- name: internal_db
  pgbouncer: false           # 不通过连接池访问

pool_mode

枚举值,可变参数,用于设置此数据库在 Pgbouncer 中的池化模式,可选值为 transactionsessionstatement,默认值为 transaction

模式说明适用场景
transaction事务结束后归还连接大多数 OLTP 应用,默认推荐
session会话结束后归还连接需要会话级状态的应用
statement每条语句后归还连接简单无状态查询,极致复用
- name: session_app
  pool_mode: session         # 使用会话级池化

pool_size

整数,可变参数,用于设置此数据库在 Pgbouncer 中的默认连接池大小,默认值为 64

连接池大小决定了 Pgbouncer 为此数据库预留的后端连接数量。根据应用负载调整此值。

- name: high_load_db
  pool_size: 128             # 高负载应用使用更大的池

pool_size_min

整数,可变参数,用于设置此数据库在 Pgbouncer 中的最小连接池大小,默认值为 0

设置大于 0 的值会让 Pgbouncer 预先创建指定数量的后端连接,用于连接预热,减少首次请求的延迟。

- name: latency_sensitive
  pool_size_min: 10          # 预热 10 个连接

pool_reserve

整数,可变参数,用于设置此数据库在 Pgbouncer 中的保留连接数,默认值为 32

当默认池不够用时,Pgbouncer 最多可以额外申请 pool_reserve 个连接来处理突发流量。

- name: bursty_db
  pool_size: 64
  pool_reserve: 64           # 允许突发到 128 个连接

pool_connlimit

整数,可变参数,用于设置通过 Pgbouncer 连接池访问此数据库的最大连接数,默认值为 100

此限制是 Pgbouncer 层面的限制,与数据库本身的 connlimit 参数独立。

- name: limited_pool_db
  pool_connlimit: 50         # 连接池最多 50 个连接

pool_auth_user

字符串,可变参数,用于指定 Pgbouncer 认证查询使用的用户。

此参数需要配合 pgbouncer_auth_query 参数启用才生效。 设置后,所有通过 Pgbouncer 连接到此数据库的请求都会使用指定用户执行认证查询来验证密码。

- name: myapp
  pool_auth_user: dbuser_monitor  # 使用监控用户执行认证查询

register_datasource

布尔值,可变参数,用于控制是否将此数据库注册到 Grafana 作为 PostgreSQL 数据源,默认值为 true

设置为 false 可以跳过 Grafana 数据源注册。适用于临时数据库、测试数据库,或不希望在监控系统中出现的内部数据库。

- name: temp_db
  register_datasource: false  # 不注册到 Grafana

模板继承

许多参数如果不显式指定,会从模板数据库继承。默认模板是 template1,其编码设置由集群初始化参数决定:

集群参数默认值说明
pg_encodingUTF8集群默认字符编码
pg_localeC / C-UTF-8 (如果支持)集群默认本地化
pg_lc_collateC / C-UTF-8 (如果支持)集群默认排序规则
pg_lc_ctypeC / C-UTF-8 (如果支持)集群默认字符分类

新创建的数据库默认会从 template1 数据库 Fork 出来,这个模版数据库会在 PG_PROVISION 阶段进行定制修改: 配置好扩展、模式以及默认权限,因此新创建的数据库也会继承这些配置,除非您显式使用一个其他的数据库作为模板。


深度定制

Pigsty 提供了丰富的定制参数与配置旋钮,如果你想定制模板数据库,请参考以下资源:

如果上面这些配置仍然无法满足您的需求,您可以使用 pg_init 指定自定义的集群初始化脚本进行定制:


本地化提供者

PostgreSQL 15+ 引入了 locale_provider 参数,支持不同的本地化实现。这些属性只能在数据库创建时指定,之后无法修改。

Pigsty 在 configure 配置向导中会根据 PG 与操作系统版本,优先使用 PG 内置的 C.UTF-8/C 本地化提供者。 数据库在默认情况下继承集群的本地化设置。如果您要为数据库指定一个不同于集群默认的本地化提供者,则必须使用 template0 作为模板数据库。

使用 ICU 提供者(PG15+)

- name: myapp_icu
  template: template0        # ICU 必须使用 template0
  locale_provider: icu
  icu_locale: en-US          # ICU 本地化规则
  encoding: UTF8

使用内置提供者(PG17+)

- name: myapp_builtin
  template: template0
  locale_provider: builtin
  builtin_locale: C.UTF-8    # 内置本地化规则
  encoding: UTF8

提供者对比libc(传统方式,依赖操作系统)、icu(PG15+,跨平台一致,功能丰富)、builtin(PG17+,最高效的 C/C.UTF-8 排序)。


连接池

Pgbouncer 连接池可以优化短连接性能,降低并发征用,以避免过高的连接数冲垮数据库,并在数据库迁移时提供额外的灵活处理空间。

Pigsty 会默认为 PostgreSQL 实例 1:1 配置启用一个连接池, 使用和 PostgreSQL 同样的 pg_dbsu 运行,默认为 postgres 操作系统用户。 连接池与数据库使用 /var/run/postgresql Unix Socket 通信。

Pigsty 默认将 pg_databases 中的所有数据库都添加到 pgbouncer 的数据库列表中。 您可以通过在数据库定义中显式设置 pgbouncer: false 来禁用特定数据库的 pgbouncer 连接池支持。 pgbouncer 数据库列表与其配置参数在 /etc/pgbouncer/database.txt 中定义。

meta                        = host=/var/run/postgresql mode=session
grafana                     = host=/var/run/postgresql mode=transaction
bytebase                    = host=/var/run/postgresql auth_user=dbuser_meta
kong                        = host=/var/run/postgresql pool_size=32 reserve_pool=64
gitea                       = host=/var/run/postgresql min_pool_size=10
wiki                        = host=/var/run/postgresql
noco                        = host=/var/run/postgresql
mongo                       = host=/var/run/postgresql

当您 创建数据库时,Pgbouncer 的数据库列表定义文件将会被刷新,并通过在线重载配置的方式生效,正常不会影响现有的连接。

6 - HBA 规则

Pigsty 中 PostgreSQL 与 Pgbouncer 的 HBA(Host-Based Authentication)规则配置详解。

概述

HBA(Host-Based Authentication)控制"谁可以从哪里、以什么方式连接到数据库"。 Pigsty 通过 pg_default_hba_rulespg_hba_rules 让 HBA 规则也能以声明式配置形式管理。

Pigsty 在集群初始化或 HBA 刷新时渲染以下配置文件:

配置文件路径说明
PostgreSQL HBA/pg/data/pg_hba.confPostgreSQL 服务器的 HBA 规则
Pgbouncer HBA/etc/pgbouncer/pgb_hba.conf连接池 Pgbouncer 的 HBA 规则

HBA 规则由以下参数控制:

参数层级说明
pg_default_hba_rulesGPostgreSQL 全局默认 HBA 规则
pg_hba_rulesG/C/IPostgreSQL 集群/实例级追加规则
pgb_default_hba_rulesGPgbouncer 全局默认 HBA 规则
pgb_hba_rulesG/C/IPgbouncer 集群/实例级追加规则

规则支持以下特性:

  • 按角色过滤:规则支持 role 字段,根据实例的 pg_role 自动筛选生效
  • 按顺序排序:规则支持 order 字段,控制规则在最终配置文件中的位置
  • 两种写法:支持别名形式(简化语法)和原始形式(直接 HBA 文本)

刷新 HBA

修改配置后,需要重新渲染配置文件并让服务重载:

bin/pgsql-hba <cls>                   # 刷新整个集群的 HBA 规则(推荐)
bin/pgsql-hba <cls> <ip>...           # 刷新集群中指定实例的 HBA 规则

脚本内部执行以下剧本命令:

./pgsql.yml -l <cls> -t pg_hba,pg_reload,pgbouncer_hba,pgbouncer_reload -e pg_reload=true

仅刷新 PostgreSQL./pgsql.yml -l <cls> -t pg_hba,pg_reload -e pg_reload=true

仅刷新 Pgbouncer./pgsql.yml -l <cls> -t pgbouncer_hba,pgbouncer_reload


参数详解

pg_default_hba_rules

PostgreSQL 全局默认 HBA 规则列表,通常定义在 all.vars 中,为所有 PostgreSQL 集群提供基础访问控制。

  • 类型:rule[],层级:全局 (G)
pg_default_hba_rules:
  - {user: '${dbsu}'    ,db: all         ,addr: local     ,auth: ident ,title: 'dbsu access via local os user ident'  ,order: 100}
  - {user: '${dbsu}'    ,db: replication ,addr: local     ,auth: ident ,title: 'dbsu replication from local os ident' ,order: 150}
  - {user: '${repl}'    ,db: replication ,addr: localhost ,auth: pwd   ,title: 'replicator replication from localhost',order: 200}
  - {user: '${repl}'    ,db: replication ,addr: intra     ,auth: pwd   ,title: 'replicator replication from intranet' ,order: 250}
  - {user: '${repl}'    ,db: postgres    ,addr: intra     ,auth: pwd   ,title: 'replicator postgres db from intranet' ,order: 300}
  - {user: '${monitor}' ,db: all         ,addr: localhost ,auth: pwd   ,title: 'monitor from localhost with password' ,order: 350}
  - {user: '${monitor}' ,db: all         ,addr: infra     ,auth: pwd   ,title: 'monitor from infra host with password',order: 400}
  - {user: '${admin}'   ,db: all         ,addr: infra     ,auth: ssl   ,title: 'admin @ infra nodes with pwd & ssl'   ,order: 450}
  - {user: '${admin}'   ,db: all         ,addr: world     ,auth: ssl   ,title: 'admin @ everywhere with ssl & pwd'    ,order: 500}
  - {user: '+dbrole_readonly',db: all    ,addr: localhost ,auth: pwd   ,title: 'pgbouncer read/write via local socket',order: 550}
  - {user: '+dbrole_readonly',db: all    ,addr: intra     ,auth: pwd   ,title: 'read/write biz user via password'     ,order: 600}
  - {user: '+dbrole_offline' ,db: all    ,addr: intra     ,auth: pwd   ,title: 'allow etl offline tasks from intranet',order: 650}

pg_hba_rules

PostgreSQL 集群/实例级 HBA 追加规则,可在集群或实例级别覆盖,与默认规则合并后按 order 排序。

  • 类型:rule[],层级:全局/集群/实例 (G/C/I),默认值:[]
pg_hba_rules:
  - {user: app_user, db: app_db, addr: intra, auth: pwd, title: 'app user access'}

pgb_default_hba_rules

Pgbouncer 全局默认 HBA 规则列表,通常定义在 all.vars 中。

  • 类型:rule[],层级:全局 (G)
pgb_default_hba_rules:
  - {user: '${dbsu}'    ,db: pgbouncer   ,addr: local     ,auth: peer  ,title: 'dbsu local admin access with os ident',order: 100}
  - {user: 'all'        ,db: all         ,addr: localhost ,auth: pwd   ,title: 'allow all user local access with pwd' ,order: 150}
  - {user: '${monitor}' ,db: pgbouncer   ,addr: intra     ,auth: pwd   ,title: 'monitor access via intranet with pwd' ,order: 200}
  - {user: '${monitor}' ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other monitor access addr' ,order: 250}
  - {user: '${admin}'   ,db: all         ,addr: intra     ,auth: pwd   ,title: 'admin access via intranet with pwd'   ,order: 300}
  - {user: '${admin}'   ,db: all         ,addr: world     ,auth: deny  ,title: 'reject all other admin access addr'   ,order: 350}
  - {user: 'all'        ,db: all         ,addr: intra     ,auth: pwd   ,title: 'allow all user intra access with pwd' ,order: 400}

pgb_hba_rules

Pgbouncer 集群/实例级 HBA 追加规则。

  • 类型:rule[],层级:全局/集群/实例 (G/C/I),默认值:[]

注意:Pgbouncer HBA 不支持 db: replication


规则字段

每条 HBA 规则是一个 YAML 字典,支持以下字段:

字段类型必需默认值说明
userstringall用户名,支持 all、变量占位符、+rolename
dbstringall数据库名,支持 allreplication、具体库名
addrstring是*-地址别名或 CIDR,见 地址别名
authstringpwd认证方式别名,见 认证方式
titlestring-规则说明/注释,会渲染为配置文件中的注释
rolestringcommon实例角色过滤,见 角色过滤
orderint1000排序权重,数字小的排前面,见 排序机制
ruleslist是*-原始 HBA 文本行列表,与 addr 二选一

addrrules 必须指定其一。使用 rules 时可以直接写原始 HBA 格式。


地址别名

Pigsty 提供地址别名,简化 HBA 规则编写:

别名展开为说明
localUnix socket本地 Unix 套接字连接
localhostUnix socket + 127.0.0.1/32 + ::1/128本地回环地址
admin${admin_ip}/32管理员 IP 地址
infra所有 infra 组节点 IP基础设施节点列表
cluster当前集群所有成员 IP同一集群内的所有实例
intra / intranet10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16内网 CIDR 网段
world / all0.0.0.0/0 + ::/0任意地址(IPv4 + IPv6)
<CIDR>直接使用192.168.1.0/2410.1.1.100/32

内网 CIDR 可通过 node_firewall_intranet 参数自定义:

node_firewall_intranet:
  - 10.0.0.0/8
  - 172.16.0.0/12
  - 192.168.0.0/16

认证方式

Pigsty 提供认证方式别名,简化配置:

别名实际方式连接类型说明
pwdscram-sha-256md5host根据 pg_pwd_enc 自动选择
sslscram-sha-256md5hostssl强制 SSL + 密码
ssl-shascram-sha-256hostssl强制 SSL + SCRAM-SHA-256
ssl-md5md5hostssl强制 SSL + MD5
certcerthostssl客户端证书认证
trusttrusthost无条件信任(危险)
deny / rejectrejecthost拒绝连接
identidenthostOS 用户映射(PostgreSQL)
peerpeerlocalOS 用户映射(Pgbouncer/本地)

pg_pwd_enc 默认为 scram-sha-256,可设为 md5 以兼容老客户端。


用户变量

HBA 规则支持以下用户占位符,渲染时自动替换为实际用户名:

占位符默认值对应参数
${dbsu}postgrespg_dbsu
${repl}replicatorpg_replication_username
${monitor}dbuser_monitorpg_monitor_username
${admin}dbuser_dbapg_admin_username

角色过滤

HBA 规则的 role 字段控制规则在哪些实例上生效:

角色说明
common默认值,所有实例都生效
primary仅主库实例生效
replica仅从库实例生效
offline仅离线实例生效(pg_role: offlinepg_offline_query: true
standby备库实例
delayed延迟从库实例

角色过滤基于实例的 pg_role 变量进行匹配,不匹配的规则会被注释掉(以 # 开头)。

pg_hba_rules:
  # 仅在主库生效:写入用户只能连主库
  - {user: writer, db: all, addr: intra, auth: pwd, role: primary, title: 'writer only on primary'}

  # 仅在离线实例生效:ETL 任务专用网络
  - {user: '+dbrole_offline', db: all, addr: '172.20.0.0/16', auth: ssl, role: offline, title: 'offline dedicated'}

排序机制

PostgreSQL HBA 是 首条匹配生效,规则顺序至关重要。Pigsty 通过 order 字段控制规则渲染顺序。

Order 区间约定

区间用途
0 - 99用户高优先规则(在所有默认规则之前)
100 - 650默认规则区(间隔 50,便于插入)
1000+用户规则默认值(不填 order 时追加到最后)

PostgreSQL 默认规则 Order 分配

Order规则说明
100dbsu local ident
150dbsu replication local
200replicator localhost
250replicator intra replication
300replicator intra postgres
350monitor localhost
400monitor infra
450admin infra ssl
500admin world ssl
550dbrole_readonly localhost
600dbrole_readonly intra
650dbrole_offline intra

Pgbouncer 默认规则 Order 分配

Order规则说明
100dbsu local peer
150all localhost pwd
200monitor pgbouncer intra
250monitor world deny
300admin intra pwd
350admin world deny
400all intra pwd

写法示例

别名形式:使用 Pigsty 提供的简化语法

pg_hba_rules:
  - title: allow grafana view access
    role: primary
    user: dbuser_view
    db: meta
    addr: infra
    auth: ssl

渲染结果:

# allow grafana view access [primary]
hostssl  meta               dbuser_view        10.10.10.10/32     scram-sha-256

原始形式:直接使用 PostgreSQL HBA 语法

pg_hba_rules:
  - title: allow intranet password access
    role: common
    rules:
      - host all all 10.0.0.0/8 scram-sha-256
      - host all all 172.16.0.0/12 scram-sha-256
      - host all all 192.168.0.0/16 scram-sha-256

渲染结果:

# allow intranet password access [common]
host all all 10.0.0.0/8 scram-sha-256
host all all 172.16.0.0/12 scram-sha-256
host all all 192.168.0.0/16 scram-sha-256

常见配置场景

黑名单 IP:使用 order: 0 确保最先匹配

pg_hba_rules:
  - {user: all, db: all, addr: '10.1.1.100/32', auth: deny, order: 0, title: 'block bad ip'}

白名单应用服务器:高优先级允许特定 IP

pg_hba_rules:
  - {user: app_user, db: app_db, addr: '192.168.1.10/32', auth: ssl, order: 50, title: 'app server'}

管理员强制证书:覆盖默认的 SSL 密码认证

pg_hba_rules:
  - {user: '${admin}', db: all, addr: world, auth: cert, order: 10, title: 'admin cert only'}

离线实例专用网络:仅在 offline 实例生效

pg_hba_rules:
  - {user: '+dbrole_offline', db: all, addr: '172.20.0.0/16', auth: ssl-sha, role: offline, title: 'etl network'}

按数据库限制访问:敏感库仅允许特定网段

pg_hba_rules:
  - {user: fin_user, db: finance_db, addr: '10.20.0.0/16', auth: ssl, title: 'finance only'}
  - {user: hr_user, db: hr_db, addr: '10.30.0.0/16', auth: ssl, title: 'hr only'}

Pgbouncer 专用规则:注意不支持 db: replication

pgb_hba_rules:
  - {user: '+dbrole_readwrite', db: all, addr: world, auth: ssl, title: 'app via pgbouncer'}

完整集群示例

pg-prod:
  hosts:
    10.10.10.11: {pg_seq: 1, pg_role: primary}
    10.10.10.12: {pg_seq: 2, pg_role: replica}
    10.10.10.13: {pg_seq: 3, pg_role: offline}
  vars:
    pg_cluster: pg-prod

    pg_hba_rules:
      # 黑名单:已知恶意 IP(最高优先级)
      - {user: all, db: all, addr: '10.1.1.100/32', auth: deny, order: 0, title: 'blacklist'}

      # 应用服务器白名单(高优先级)
      - {user: app_user, db: app_db, addr: '192.168.1.0/24', auth: ssl, order: 50, title: 'app servers'}

      # ETL 任务:仅离线实例
      - {user: etl_user, db: all, addr: '172.20.0.0/16', auth: pwd, role: offline, title: 'etl tasks'}

      # 集群内监控访问
      - {user: '${monitor}', db: all, addr: cluster, auth: pwd, order: 380, title: 'cluster monitor'}

    pgb_hba_rules:
      # 应用通过连接池
      - {user: '+dbrole_readwrite', db: all, addr: '192.168.1.0/24', auth: ssl, title: 'app via pgbouncer'}

验证与排查

查看当前 HBA 规则

psql -c "TABLE pg_hba_file_rules"         # 通过 SQL 查看(推荐)
cat /pg/data/pg_hba.conf                  # 查看 PostgreSQL HBA 文件
cat /etc/pgbouncer/pgb_hba.conf           # 查看 Pgbouncer HBA 文件
grep '^#' /pg/data/pg_hba.conf | head -20 # 查看规则标题(验证 order)

测试连接认证

psql -h <host> -p 5432 -U <user> -d <db> -c "SELECT 1"

常见问题排查

错误信息可能原因解决方案
no pg_hba.conf entry for host...没有匹配的 HBA 规则添加对应规则并刷新
password authentication failed密码错误或加密方式不兼容检查密码和 pg_pwd_enc
规则不生效未刷新或 order 被覆盖执行 bin/pgsql-hba 并检查顺序

注意事项

  1. 顺序敏感:PostgreSQL HBA 首条匹配生效,善用 order 字段
  2. 角色匹配:确保 role 字段与目标实例的 pg_role 一致
  3. 地址格式:CIDR 必须正确,如 10.0.0.0/8 而非 10.0.0.0/255.0.0.0
  4. Pgbouncer 限制:不支持 db: replication
  5. SSL 前提:使用 sslcert 认证前确保 SSL 已正确配置
  6. 测试优先:修改 HBA 前建议先在测试环境验证
  7. 扩缩容刷新:使用 addr: cluster 的规则在集群成员变化后需要刷新

相关文档

7 - 参数配置

如何配置集群、实例、用户和数据库级别的 PostgreSQL 参数

PostgreSQL 参数可以在多个层级进行配置,不同层级的参数设置具有不同的作用范围和优先级。 Pigsty 支持在四个层级配置 PostgreSQL 参数,从全局到局部依次为:

层级作用范围配置方式存储位置
集群级整个集群所有实例Patroni DCS / 调优模板etcd + postgresql.conf
实例级单个 PostgreSQL 实例pg_parameters / ALTER SYSTEMpostgresql.auto.conf
数据库级特定数据库的所有会话pg_databases[].parameterspg_db_role_setting
用户级特定用户的所有会话pg_users[].parameterspg_db_role_setting

参数优先级从低到高:集群级 < 实例级 < 数据库级 < 用户级 < 会话级SET 命令)。 高优先级的设置会覆盖低优先级的设置。

关于 PostgreSQL 参数的完整说明,请参阅 PostgreSQL 官方文档:服务器配置


集群级参数

集群级参数是整个 PostgreSQL 集群共享的配置,所有实例(主库和从库)都会使用相同的参数值。 在 Pigsty 中,集群级参数通过 Patroni 管理,存储在分布式配置存储(DCS,默认为 etcd)中。

Pigsty 提供了四种预置的 Patroni 参数优化模板,针对不同的使用场景进行了优化,通过 pg_conf 参数指定:

模板适用场景特点
oltp.yml在线事务处理低延迟、高并发,默认推荐
olap.yml在线分析处理大查询、高吞吐,适合数仓
crit.yml核心金融业务最大持久性,牺牲部分性能换取安全
tiny.yml微型实例资源受限环境,适合开发测试

调优模板文件位于 Pigsty 安装目录的 roles/pgsql/templates/ 目录下,包含了根据硬件规格自动计算的参数值。 这些模板会在集群初始化时渲染为 Patroni 配置文件 /etc/patroni/patroni.yml。更多详情请参阅 场景模板

在集群创建前,您可以通过调整这些 Patroni 配置模板来修改集群的 初始化参数。 一旦集群初始化完成,后续的参数修改应通过 Patroni 的 配置管理 机制进行。

Patroni DCS 配置

Patroni 将集群配置存储在 DCS(分布式配置存储,默认为 etcd)中,确保集群所有成员使用一致的配置。

配置存储结构

/pigsty/                          # 命名空间(patroni_namespace)
  └── pg-meta/                    # 集群名称(pg_cluster)
      ├── config                  # 集群配置(所有成员共享)
      ├── leader                  # 当前主库信息
      ├── members/                # 成员注册信息
      │   ├── pg-meta-1
      │   └── pg-meta-2
      └── ...

配置渲染流程

  1. 初始化阶段:调优模板(如 oltp.yml)通过 Jinja2 渲染为 /etc/patroni/patroni.yml
  2. 启动阶段:Patroni 读取本地配置,将 PostgreSQL 参数写入 DCS
  3. 运行阶段:Patroni 定期从 DCS 同步配置到本地 PostgreSQL

本地缓存机制

每个 Patroni 实例会在本地缓存 DCS 配置,位于 /pg/conf/<instance>.yml

  • 启动时:从 DCS 加载配置,缓存到本地
  • 运行时:定期同步 DCS 配置到本地缓存
  • DCS 不可用时:使用本地缓存继续运行(但无法进行主从切换)

配置文件层次

Patroni 会将 DCS 中的配置渲染到本地 PostgreSQL 配置文件,形成以下层次结构:

/pg/data/
├── postgresql.conf          # 主配置文件(由 Patroni 动态管理)
├── postgresql.base.conf     # 基础配置(通过 include 指令加载)
├── postgresql.auto.conf     # 实例级覆盖配置(ALTER SYSTEM 写入)
├── pg_hba.conf              # 客户端认证配置
└── pg_ident.conf            # 用户映射配置

配置加载顺序(优先级从低到高):

  1. postgresql.conf:Patroni 动态生成,包含 DCS 中的集群参数
  2. postgresql.base.conf:通过 include 指令加载,包含静态基础配置
  3. postgresql.auto.conf:PostgreSQL 自动加载,用于实例级参数覆盖

由于 postgresql.auto.conf 最后加载,其中的参数会覆盖前面文件中的同名参数。


实例级参数

实例级参数仅对单个 PostgreSQL 实例生效,用于覆盖集群级配置或设置实例特定的参数。 实例级参数会写入 postgresql.auto.conf 文件,由于该文件最后加载,可以覆盖集群级的任何参数。

这是一项非常有用的技术:您可以为特定实例设置不同于集群的参数值,例如:

  • 为从库设置 hot_standby_feedback = on
  • 为特定实例调整 work_memmaintenance_work_mem
  • 为延迟从库设置 recovery_min_apply_delay

使用 pg_parameters

在 Pigsty 配置中,使用 pg_parameters 参数定义实例级配置:

pg-meta:
  hosts:
    10.10.10.10:
      pg_seq: 1
      pg_role: primary
      pg_parameters:                              # 实例级参数
        log_statement: all                        # 仅此实例记录所有 SQL
  vars:
    pg_cluster: pg-meta
    pg_parameters:                                # 集群默认的实例参数
      log_timezone: Asia/Shanghai
      log_min_duration_statement: 1000

使用 ./pgsql.yml -l <cls> -t pg_param 子任务,可以将参数配置应用生效,这些参数会被渲染到 postgresql.auto.conf 文件中。

参数覆盖层次

pg_parameters 可以在 Ansible 配置的不同层次定义,优先级从低到高:

all:
  vars:
    pg_parameters:                    # 全局默认
      log_statement: none

  children:
    pg-meta:
      vars:
        pg_parameters:                # 集群级覆盖
          log_statement: ddl
      hosts:
        10.10.10.10:
          pg_parameters:              # 实例级覆盖(最高优先级)
            log_statement: all

使用 ALTER SYSTEM

除了通过配置文件,还可以在运行时使用 SQL 命令 ALTER SYSTEM 修改实例级参数:

-- 设置参数
ALTER SYSTEM SET work_mem = '256MB';
ALTER SYSTEM SET log_min_duration_statement = 1000;

-- 重置为默认值
ALTER SYSTEM RESET work_mem;
ALTER SYSTEM RESET ALL;  -- 重置所有 ALTER SYSTEM 设置

-- 重新加载配置使其生效
SELECT pg_reload_conf();

ALTER SYSTEM 会将参数写入 postgresql.auto.conf 文件。

注意:在 Pigsty 管理的集群中,postgresql.auto.conf 由 Ansible 通过 pg_parameters 管理。 手动使用 ALTER SYSTEM 修改的参数可能会在下次执行 playbook 时被覆盖。 建议通过修改 pigsty.yml 中的 pg_parameters 来管理实例级参数。

列表类型参数

PostgreSQL 中有一类特殊的参数接受逗号分隔的列表值。在 YAML 配置文件中配置这类参数时, 整个值必须用引号包裹,否则 YAML 解析器会将其解释为数组而导致错误:

# ✓ 正确:用引号包裹整个值
pg_parameters:
  shared_preload_libraries: 'timescaledb, pg_stat_statements'
  search_path: '"$user", public, app'

# ✗ 错误:不加引号会导致 YAML 解析错误
pg_parameters:
  shared_preload_libraries: timescaledb, pg_stat_statements   # YAML 会解析为数组!

Pigsty 会自动识别以下列表类型参数,在渲染到配置文件时不添加外层引号

参数说明示例值
shared_preload_libraries预加载共享库'timescaledb, pg_stat_statements'
search_pathSchema 搜索路径'"$user", public, app'
local_preload_libraries本地预加载库'auto_explain'
session_preload_libraries会话预加载库'pg_hint_plan'
log_destination日志输出目标'csvlog, stderr'
unix_socket_directoriesUnix Socket 目录'/var/run/postgresql, /tmp'
temp_tablespaces临时表空间'ssd_space, hdd_space'
debug_io_direct直接 I/O 模式(PG16+)'data, wal'

渲染示例

# pigsty.yml 配置(YAML 中需要引号)
pg_parameters:
  shared_preload_libraries: 'timescaledb, pg_stat_statements'
  search_path: '"$user", public, app'
  work_mem: 64MB
# 渲染后的 postgresql.auto.conf(列表参数无外层引号)
shared_preload_libraries = timescaledb, pg_stat_statements
search_path = "$user", public, app
work_mem = '64MB'

数据库级参数

数据库级参数针对特定数据库生效,连接到该数据库的所有会话都会应用这些参数设置。 通过 ALTER DATABASE ... SET 实现,存储在系统表 pg_db_role_setting 中。

配置方式

pg_databases 中使用 parameters 字段定义:

pg_databases:
  - name: analytics
    owner: dbuser_analyst
    parameters:
      work_mem: 256MB                              # 分析库需要更多内存
      maintenance_work_mem: 1GB                    # 大表维护操作
      statement_timeout: 10min                     # 允许长查询
      search_path: '"$user", public, mart'         # 列表参数需要引号

与实例级参数相同,列表类型参数值在 YAML 中需要用引号包裹。

参数渲染规则

数据库级参数通过 ALTER DATABASE ... SET 语句设置。Pigsty 会根据参数类型自动选择正确的语法:

列表类型参数search_pathtemp_tablespaceslocal_preload_librariessession_preload_librarieslog_destination)不加外层引号:

ALTER DATABASE "analytics" SET "search_path" = "$user", public, mart;

标量参数 使用引号包裹值:

ALTER DATABASE "analytics" SET "work_mem" = '256MB';
ALTER DATABASE "analytics" SET "statement_timeout" = '10min';

注意:虽然 log_destination 在数据库级参数白名单中,但由于其 contextsighup, 实际上无法在数据库级别生效。此参数应在实例级(pg_parameters)配置。

查看数据库参数

-- 查看特定数据库的参数设置
SELECT datname, unnest(setconfig) AS setting
FROM pg_db_role_setting drs
JOIN pg_database d ON d.oid = drs.setdatabase
WHERE drs.setrole = 0 AND datname = 'analytics';

手动管理

-- 设置参数
ALTER DATABASE analytics SET work_mem = '256MB';
ALTER DATABASE analytics SET search_path = "$user", public, myschema;

-- 重置参数
ALTER DATABASE analytics RESET work_mem;
ALTER DATABASE analytics RESET ALL;

用户级参数

用户级参数针对特定数据库用户生效,该用户的所有会话都会应用这些参数设置。 通过 ALTER USER ... SET 实现,同样存储在系统表 pg_db_role_setting 中。

配置方式

pg_userspg_default_roles 中使用 parameters 字段定义:

pg_users:
  - name: dbuser_analyst
    password: DBUser.Analyst
    parameters:
      work_mem: 256MB                              # 分析查询需要更多内存
      statement_timeout: 5min                      # 允许较长的查询时间
      search_path: '"$user", public, analytics'    # 列表参数需要引号
      log_statement: all                           # 记录所有 SQL

参数渲染规则

用户级参数的渲染规则与数据库级参数相同:

列表类型参数search_pathtemp_tablespaceslocal_preload_librariessession_preload_libraries)不加外层引号:

ALTER USER "dbuser_analyst" SET "search_path" = "$user", public, analytics;

标量参数 使用引号包裹:

ALTER USER "dbuser_analyst" SET "work_mem" = '256MB';
ALTER USER "dbuser_analyst" SET "statement_timeout" = '5min';

特殊值 DEFAULT

使用 DEFAULT(大小写不敏感)可以将参数重置为 PostgreSQL 默认值:

parameters:
  work_mem: DEFAULT          # 重置为默认值
  statement_timeout: 30s     # 设置具体值
ALTER USER "dbuser_app" SET "work_mem" = DEFAULT;
ALTER USER "dbuser_app" SET "statement_timeout" = '30s';

查看用户参数

-- 查看特定用户的参数设置
SELECT rolname, unnest(setconfig) AS setting
FROM pg_db_role_setting drs
JOIN pg_roles r ON r.oid = drs.setrole
WHERE rolname = 'dbuser_analyst';

手动管理

-- 设置参数
ALTER USER dbuser_app SET work_mem = '128MB';
ALTER USER dbuser_app SET search_path = "$user", public, myschema;

-- 重置参数
ALTER USER dbuser_app RESET work_mem;
ALTER USER dbuser_app RESET ALL;

参数优先级

当同一参数在多个层级设置时,PostgreSQL 按以下优先级应用(从低到高):

postgresql.conf           ← 集群级参数(Patroni DCS)
       ↓
postgresql.auto.conf      ← 实例级参数(pg_parameters / ALTER SYSTEM)
       ↓
数据库级                    ← ALTER DATABASE SET
       ↓
用户级                      ← ALTER USER SET
       ↓
会话级                      ← SET 命令

关于数据库级与用户级的优先级

当用户连接到特定数据库时,如果同一参数在数据库级和用户级都有设置, PostgreSQL 会使用 用户级参数,因为用户级优先级更高。

示例场景

# 数据库级:analytics 数据库 work_mem = 256MB
pg_databases:
  - name: analytics
    parameters:
      work_mem: 256MB

# 用户级:analyst 用户 work_mem = 512MB
pg_users:
  - name: analyst
    parameters:
      work_mem: 512MB
  • analyst 用户连接到 analytics 数据库时:work_mem = 512MB(用户级优先)
  • 当其他用户连接到 analytics 数据库时:work_mem = 256MB(数据库级生效)
  • analyst 用户连接到其他数据库时:work_mem = 512MB(用户级生效)

8 - 访问控制

Pigsty 提供的默认角色系统与权限模型

访问控制由“角色体系 + 权限模板 + HBA”共同决定。本节聚焦于如何通过配置参数声明角色与对象权限。

Pigsty 预置了一套精简的 ACL 模型,全部通过以下参数描述:

  • pg_default_roles:系统角色与系统用户。
  • pg_users:业务用户与角色。
  • pg_default_privileges:管理员/属主新建对象时的默认权限。
  • pg_revoke_publicpg_default_schemaspg_default_extensions:控制 template1 的默认行为。

理解这些参数后,你就可以写出完全可复现的权限配置。


默认角色体系(pg_default_roles)

默认包含 4 个业务角色 + 4 个系统用户:

名称类型说明
dbrole_readonlyNOLOGIN所有业务共用,拥有 SELECT/USAGE
dbrole_readwriteNOLOGIN继承只读角色,并拥有 INSERT/UPDATE/DELETE
dbrole_adminNOLOGIN继承 pg_monitor + 读写角色,可建对象和触发器
dbrole_offlineNOLOGIN受限只读角色,仅允许访问离线实例
postgres用户系统超级用户,与 pg_dbsu 同名
replicator用户用于流复制与备份,继承监控与只读权限
dbuser_dba用户主要管理员账号,同时同步到 pgbouncer
dbuser_monitor用户监控账号,具备 pg_monitor 权限,默认记录慢 SQL

这些定义位于 pg_default_roles,理论上可以自定义,但若要替换名称,必须同步更新 HBA/ACL/脚本中的引用。

示例:为离线任务额外加一个 dbrole_etl

pg_default_roles:
  - { name: dbrole_etl, login: false, roles: [dbrole_offline], comment: 'etl read-only role' }
  - { name: dbrole_admin, login: false, roles: [pg_monitor, dbrole_readwrite, dbrole_etl] }

效果:所有继承 dbrole_admin 的用户自动拥有 dbrole_etl 权限,可访问 offline 实例并执行 ETL。


默认用户与凭据参数

系统用户的用户名/密码由以下参数控制:

参数默认值作用
pg_dbsupostgres数据库/系统超级用户
pg_dbsu_password空字符串dbsu 密码(默认不启用)
pg_replication_usernamereplicator复制用户名称
pg_replication_passwordDBUser.Replicator复制用户密码
pg_admin_usernamedbuser_dba管理员用户名
pg_admin_passwordDBUser.DBA管理员密码
pg_monitor_usernamedbuser_monitor监控用户
pg_monitor_passwordDBUser.Monitor监控用户密码

如果修改这些参数,请同步在 pg_default_roles 中更新对应用户的定义,以避免角色属性不一致。


业务角色与授权(pg_users)

业务用户通过 pg_users 声明(详细字段见 用户配置),其中 roles 字段控制授予的业务角色。

示例:创建只读/读写用户各一名:

pg_users:
  - { name: app_reader,  password: DBUser.Reader,  roles: [dbrole_readonly],  pgbouncer: true }
  - { name: app_writer,  password: DBUser.Writer,  roles: [dbrole_readwrite], pgbouncer: true }

通过继承 dbrole_* 来控制访问权限,无需为每个库单独 GRANT。配合 pg_hba_rules 即可区分访问来源。

若需要更细粒度的 ACL,可在 baseline SQL 中或后续剧本里使用标准 GRANT/REVOKE。Pigsty 不会阻止你额外授予权限。


默认权限模板(pg_default_privileges)

pg_default_privileges 会在 postgresdbuser_dbadbrole_admin(业务管理员 SET ROLE 后)上设置 DEFAULT PRIVILEGE。默认模板如下:

pg_default_privileges:
  - GRANT USAGE      ON SCHEMAS   TO dbrole_readonly
  - GRANT SELECT     ON TABLES    TO dbrole_readonly
  - GRANT SELECT     ON SEQUENCES TO dbrole_readonly
  - GRANT EXECUTE    ON FUNCTIONS TO dbrole_readonly
  - GRANT USAGE      ON SCHEMAS   TO dbrole_offline
  - GRANT SELECT     ON TABLES    TO dbrole_offline
  - GRANT SELECT     ON SEQUENCES TO dbrole_offline
  - GRANT EXECUTE    ON FUNCTIONS TO dbrole_offline
  - GRANT INSERT     ON TABLES    TO dbrole_readwrite
  - GRANT UPDATE     ON TABLES    TO dbrole_readwrite
  - GRANT DELETE     ON TABLES    TO dbrole_readwrite
  - GRANT USAGE      ON SEQUENCES TO dbrole_readwrite
  - GRANT UPDATE     ON SEQUENCES TO dbrole_readwrite
  - GRANT TRUNCATE   ON TABLES    TO dbrole_admin
  - GRANT REFERENCES ON TABLES    TO dbrole_admin
  - GRANT TRIGGER    ON TABLES    TO dbrole_admin
  - GRANT CREATE     ON SCHEMAS   TO dbrole_admin

只要对象由上述管理员创建,就会自动携带对应权限,无需人为执行 GRANT。若业务需要自定义模板,直接替换该数组即可。

额外提示:

  • pg_revoke_public 默认为 true,意味着自动撤销 PUBLIC 在数据库和 public schema 上的 CREATE 权限。
  • pg_default_schemaspg_default_extensions 控制在 template1/postgres 中预创建的 schema/扩展,通常用于监控对象(monitor schema、pg_stat_statements 等)。

常见配置场景

为合作方提供只读账号

pg_users:
  - name: partner_ro
    password: Partner.Read
    roles: [dbrole_readonly]
pg_hba_rules:
  - { user: partner_ro, db: analytics, addr: 203.0.113.0/24, auth: ssl }

效果:合作方账号登录后只具备默认只读权限,并且只能通过 TLS 从指定网段访问 analytics 库。

为业务管理员赋予 DDL 能力

pg_users:
  - name: app_admin
    password: DBUser.AppAdmin
    roles: [dbrole_admin]

业务管理员通过 SET ROLE dbrole_admin 或直接以 app_admin 登录,即可继承默认的 DDL 权限模板。

自定义默认权限

pg_default_privileges:
  - GRANT INSERT,UPDATE,DELETE ON TABLES TO dbrole_admin
  - GRANT SELECT,UPDATE ON SEQUENCES TO dbrole_admin
  - GRANT SELECT ON TABLES TO reporting_group

替换默认模板后,所有由管理员创建的对象都会携带新的权限定义,避免逐对象授权。


与其他组件的协同

  • HBA 规则:使用 pg_hba_rules 将角色与来源进行绑定(例如只让 dbrole_offline 访问离线实例)。
  • Pgbouncerpgbouncer: true 的用户会被写入 userlist.txtpool_mode/pool_connlimit 可以控制连接池层面的配额。
  • Grafana/监控dbuser_monitor 的权限来自 pg_default_roles,如果你新增监控用户,记得赋予 pg_monitor + monitor schema 的访问权。

通过这些参数,可以让权限体系与代码一起版本化,真正做到“配置即策略”。