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

返回本页常规视图.

模块:PGSQL

如何使用 Pigsty 部署并管理世界上最先进的开源关系型数据库 —— PostgreSQL,按需定制,开箱即用!

世界上最先进的开源关系型数据库!

而 Pigsty 帮它进入全盛状态:开箱即用、可靠、可观测、可维护、可伸缩! 配置 | 管理 | 剧本 | 监控 | 参数


概览

了解关于 PostgreSQL 的重要主题与概念。


配置

描述 你想要的 PostgreSQL 集群

  • 身份参数:定义PostgreSQL集群的身份参数
  • 读写主库:创建由单一主库构成的单实例“集群“
  • 只读从库:创建一主一从的两节点基础高可用集群
  • 离线从库:创建专用于OLAP/ETL/交互式查询的特殊只读实例
  • 同步备库:启用同步提交,以确保没有数据丢失
  • 法定人数:使用法定人数同步提交以获得更高的一致性级别
  • 备份集群:克隆现有集群,并保持同步(异地灾备集群)
  • 延迟集群:克隆现有集群,并延迟重放,用于紧急数据恢复
  • Citus集群:定义并创建 Citus 水平分布式数据库集群
  • 大版本切换:使用不同的PostgreSQL大版本部署集群

管理

管理 您所创建的 PostgreSQL 集群。


剧本

使用幂等的 剧本,将您的描述变为现实。


监控

在 Grafana 仪表盘 中查阅 PostgreSQL 的详情状态。

在 Pigsty 中共有 26 个与 PostgreSQL 相关的监控面板:

总览集群实例数据库
PGSQL OverviewPGSQL ClusterPGSQL InstancePGSQL Database
PGSQL AlertPGRDS ClusterPGRDS InstancePGCAT Database
PGSQL ShardPGSQL ActivityPGCAT InstancePGSQL Tables
PGSQL ReplicationPGSQL PersistPGSQL Table
PGSQL ServicePGSQL ProxyPGCAT Table
PGSQL DatabasesPGSQL PgbouncerPGSQL Query
PGSQL PatroniPGSQL SessionPGCAT Query
PGSQL PITRPGSQL XactsPGCAT Locks
PGSQL ExporterPGCAT Schema

参数

PGSQL 模块的配置参数列表

  • PG_ID : 计算和校验 PostgreSQL 实例身份
  • PG_BUSINESS : PostgreSQL业务对象定义
  • PG_INSTALL : 安装 PostgreSQL 内核,支持软件包与扩展插件
  • PG_BOOTSTRAP : 使用 Patroni 初始化高可用 PostgreSQL 集群
  • PG_PROVISION : 创建 PostgreSQL 用户、数据库和其他数据库内对象
  • PG_BACKUP : 使用 pgbackrest 设置备份仓库
  • PG_ACCESS : 暴露 PostgreSQL 服务,绑定 VIP (可选),以及注册DNS
  • PG_MONITOR : 为 PostgreSQL 实例添加监控,并注册至基础设施中。
  • PG_REMOVE : 移除 PostgreSQL 集群,实例和相关资源。

教程

一些使用/管理 Pigsty中 PostgreSQL 数据库的教程。

  • 克隆一套现有的 PostgreSQL 集群
  • 创建一套现有 PostgreSQL 集群的在线备份集群。
  • 创建一套现有 PostgreSQL 集群的延迟备份集群
  • 监控一个已有的 postgres 实例?
  • 使用逻辑复制从外部 PostgreSQL 迁移至 Pigsty 托管的 PostgreSQL 实例?
  • 使用 MinIO 作为集中的 pgBackRest 备份仓库。
  • 使用专门的 etcd 集群作为 PostgreSQL / Patroni 的 DCS ?
  • 使用专用的 haproxy 负载均衡器集群对外暴露暴露 PostgreSQL 服务。
  • 使用 pg-meta CMDB 替代 pigsty.yml 作为配置清单源。
  • 使用 PostgreSQL 作为 Grafana 的后端存储数据库?
  • 使用 PostgreSQL 作为 Prometheus 后端存储数据库?

1 - 配置指南

2 - 集群配置

根据需求场景选择合适的实例与集群类型,配置出满足需求的 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 集群,而无需手工逐项配置。

2.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.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 生成,无需手工干预。

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

2.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

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

2.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:角色权限 一节。

2.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 的数据库列表定义文件将会被刷新,并通过在线重载配置的方式生效,正常不会影响现有的连接。

2.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 的规则在集群成员变化后需要刷新

相关文档

2.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(用户级生效)

2.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 的访问权。

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

3 - 服务/接入

分离读写操作,正确路由流量,稳定可靠地交付 PostgreSQL 集群提供的能力。

分离读写操作,正确路由流量,稳定可靠地交付 PostgreSQL 集群提供的能力。

服务 是一种抽象:它是数据库集群对外提供能力的形式,并封装了底层集群的细节。

服务对于生产环境中的 稳定接入 至关重要,在 高可用 集群自动故障时方显其价值,单机用户 通常不需要操心这个概念。


单机用户

“服务” 的概念是给生产环境用的,个人用户/单机集群可以不折腾,直接拿实例名/IP地址访问数据库。

例如,Pigsty 默认的单节点 pg-meta.meta 数据库,就可以直接用下面三个不同的用户连接上去。

psql postgres://dbuser_dba:DBUser.DBA@10.10.10.10/meta     # 直接用 DBA 超级用户连上去
psql postgres://dbuser_meta:DBUser.Meta@10.10.10.10/meta   # 用默认的业务管理员用户连上去
psql postgres://dbuser_view:DBUser.View@pg-meta/meta       # 用默认的只读用户走实例域名连上去

服务概述

在真实世界生产环境中,我们会使用基于复制的主从数据库集群。集群中有且仅有一个实例作为领导者(主库)可以接受写入。 而其他实例(从库)则会从持续从集群领导者获取变更日志,与领导者保持一致。同时,从库还可以承载只读请求,在读多写少的场景下可以显著分担主库的负担, 因此对集群的写入请求与只读请求进行区分,是一种十分常见的实践。

此外对于高频短连接的生产环境,我们还会通过连接池中间件(Pgbouncer)对请求进行池化,减少连接与后端进程的创建开销。但对于ETL与变更执行等场景,我们又需要绕过连接池,直接访问数据库。 同时,高可用集群在故障时会出现故障切换(Failover),故障切换会导致集群的领导者出现变更。因此高可用的数据库方案要求写入流量可以自动适配集群的领导者变化。 这些不同的访问需求(读写分离,池化与直连,故障切换自动适配)最终抽象出 服务 (Service)的概念。

通常来说,数据库集群都必须提供这种最基础的服务:

  • 读写服务(primary) :可以读写数据库

对于生产数据库集群,至少应当提供这两种服务:

  • 读写服务(primary) :写入数据:只能由主库所承载。
  • 只读服务(replica) :读取数据:可以由从库承载,没有从库时也可由主库承载

此外,根据具体的业务场景,可能还会有其他的服务,例如:

  • 默认直连服务(default) :允许(管理)用户,绕过连接池直接访问数据库的服务
  • 离线从库服务(offline) :不承接线上只读流量的专用从库,用于ETL与分析查询
  • 同步从库服务(standby) :没有复制延迟的只读服务,由 同步备库/主库处理只读查询
  • 延迟从库服务(delayed) :访问同一个集群在一段时间之前的旧数据,由 延迟从库 来处理

默认服务

Pigsty默认为每个 PostgreSQL 数据库集群提供四种不同的服务,以下是默认服务及其定义:

服务端口描述
primary5433生产读写,连接到主库连接池(6432)
replica5434生产只读,连接到备库连接池(6432)
default5436管理,ETL写入,直接访问主库(5432)
offline5438OLAP、ETL、个人用户、交互式查询

以默认的 pg-meta 集群为例,它提供四种默认服务:

psql postgres://dbuser_meta:DBUser.Meta@pg-meta:5433/meta   # pg-meta-primary : 通过主要的 pgbouncer(6432) 进行生产读写
psql postgres://dbuser_meta:DBUser.Meta@pg-meta:5434/meta   # pg-meta-replica : 通过备份的 pgbouncer(6432) 进行生产只读
psql postgres://dbuser_dba:DBUser.DBA@pg-meta:5436/meta     # pg-meta-default : 通过主要的 postgres(5432) 直接连接
psql postgres://dbuser_stats:DBUser.Stats@pg-meta:5438/meta # pg-meta-offline : 通过离线的 postgres(5432) 直接连接

从示例集群 架构图 上可以看出这四种服务的工作方式:

pigsty-ha.png

注意在这里pg-meta 域名指向了集群的 L2 VIP,进而指向集群主库上的 haproxy 负载均衡器,它负责将流量路由到不同的实例上,详见 服务接入


服务实现

在 Pigsty 中,服务使用 节点 上的 haproxy 来实现,通过主机节点上的不同端口进行区分。

Pigsty 所纳管的每个节点上都默认启用了 Haproxy 以对外暴露服务,而数据库节点也不例外。 集群中的节点尽管从数据库的视角来看有主从之分,但从服务的视角来看,每个节点都是相同的: 这意味着即使您访问的是从库节点,只要使用正确的服务端口,就依然可以使用到主库读写的服务。 这样的设计可以屏蔽复杂度:所以您只要可以访问 PostgreSQL 集群上的任意一个实例,就可以完整的访问到所有服务。

这样的设计类似于 Kubernetes 中的 NodePort 服务,同样在 Pigsty 中,每一个服务都包括以下两个核心要素:

  1. 通过 NodePort 暴露的访问端点(端口号,从哪访问?)
  2. 通过 Selectors 选择的目标实例(实例列表,谁来承载?)

Pigsty的服务交付边界止步于集群的HAProxy,用户可以用各种手段访问这些负载均衡器,请参考 接入服务

所有的服务都通过配置文件进行声明,例如,PostgreSQL 默认服务就是由 pg_default_services 参数所定义的:

pg_default_services:
- { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }
- { name: replica ,port: 5434 ,dest: default  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
- { name: default ,port: 5436 ,dest: postgres ,check: /primary   ,selector: "[]" }
- { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]"}

您也可以在 pg_services 中定义额外的服务,参数 pg_default_servicespg_services 都是由 服务定义 对象组成的数组。


定义服务

Pigsty 允许您定义自己的服务:

  • pg_default_services:所有 PostgreSQL 集群统一对外暴露的服务,默认有四个。
  • pg_services:额外的 PostgreSQL 服务,可以视需求在全局或集群级别定义。
  • haproxy_servies:直接定制 HAProxy 服务内容,可以用于其他组件的接入

对于 PostgreSQL 集群来说,通常只需要关注前两者即可。 每一条服务定义都会在所有相关 HAProxy 实例的配置目录下生成一个新的配置文件:/etc/haproxy/<svcname>.cfg 下面是一个自定义的服务样例 standby:当您想要对外提供没有复制延迟的只读服务时,就可以在 pg_services 新增这条记录:

- name: standby                   # 必选,服务名称,最终的 svc 名称会使用 `pg_cluster` 作为前缀,例如:pg-meta-standby
  port: 5435                      # 必选,暴露的服务端口(作为 kubernetes 服务节点端口模式)
  ip: "*"                         # 可选,服务绑定的 IP 地址,默认情况下为所有 IP 地址
  selector: "[]"                  # 必选,服务成员选择器,使用 JMESPath 来筛选配置清单
  backup: "[? pg_role == `primary`]"  # 可选,服务成员选择器(备份),也就是当默认选择器选中的实例都宕机后,服务才会由这里选中的实例成员来承载
  dest: default                   # 可选,目标端口,default|postgres|pgbouncer|<port_number>,默认为 'default',Default的意思就是使用 pg_default_service_dest 的取值来最终决定
  check: /sync                    # 可选,健康检查 URL 路径,默认为 /,这里使用 Patroni API:/sync ,只有同步备库和主库才会返回 200 健康状态码 
  maxconn: 5000                   # 可选,允许的前端连接最大数,默认为5000
  balance: roundrobin             # 可选,haproxy 负载均衡算法(默认为 roundrobin,其他选项:leastconn)
  options: 'inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100'

而上面的服务定义,在样例的三节点 pg-test 上将会被转换为 haproxy 配置文件 /etc/haproxy/pg-test-standby.conf

#---------------------------------------------------------------------
# service: pg-test-standby @ 10.10.10.11:5435
#---------------------------------------------------------------------
# service instances 10.10.10.11, 10.10.10.13, 10.10.10.12
# service backups   10.10.10.11
listen pg-test-standby
    bind *:5435            # <--- 绑定了所有IP地址上的 5435 端口
    mode tcp               # <--- 负载均衡器工作在 TCP 协议上
    maxconn 5000           # <--- 最大连接数为 5000,可按需调大
    balance roundrobin     # <--- 负载均衡算法为 rr 轮询,还可以使用 leastconn 
    option httpchk         # <--- 启用 HTTP 健康检查
    option http-keep-alive # <--- 保持HTTP连接
    http-check send meth OPTIONS uri /sync   # <---- 这里使用 /sync ,Patroni 健康检查 API ,只有同步备库和主库才会返回 200 健康状态码。 
    http-check expect status 200             # <---- 健康检查返回代码 200 代表正常
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers: # pg-test 集群全部三个实例都被 selector: "[]" 给圈中了,因为没有任何的筛选条件,所以都会作为 pg-test-replica 服务的后端服务器。但是因为还有 /sync 健康检查,所以只有主库和同步备库才能真正承载请求。
    server pg-test-1 10.10.10.11:6432 check port 8008 weight 100 backup  # <----- 唯独主库满足条件 pg_role == `primary`, 被 backup selector 选中。
    server pg-test-3 10.10.10.13:6432 check port 8008 weight 100         #        因此作为服务的兜底实例:平时不承载请求,其他从库全部宕机后,才会承载只读请求,从而最大避免了读写服务受到只读服务的影响
    server pg-test-2 10.10.10.12:6432 check port 8008 weight 100         #        

在这里,pg-test 集群全部三个实例都被 selector: "[]" 给圈中了,渲染进入 pg-test-replica 服务的后端服务器列表中。但是因为还有 /sync 健康检查,Patroni Rest API只有在主库和 同步备库 上才会返回代表健康的 HTTP 200 状态码,因此只有主库和同步备库才能真正承载请求。 此外,主库因为满足条件 pg_role == primary, 被 backup selector 选中,被标记为了备份服务器,只有当没有其他实例(也就是同步备库)可以满足需求时,才会顶上。


Primary服务

Primary服务可能是生产环境中最关键的服务,它在 5433 端口提供对数据库集群的读写能力,服务定义如下:

- { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }
  • 选择器参数 selector: "[]" 意味着所有集群成员都将被包括在Primary服务中
  • 但只有主库能够通过健康检查(check: /primary),实际承载Primary服务的流量。
  • 目的地参数 dest: default 意味着Primary服务的目的地受到 pg_default_service_dest 参数的影响
  • dest 默认值 default 会被替换为 pg_default_service_dest 的值,默认为 pgbouncer
  • 默认情况下 Primary 服务的目的地默认是主库上的连接池,也就是由 pgbouncer_port 指定的端口,默认为 6432

如果 pg_default_service_dest 的值为 postgres,那么 primary 服务的目的地就会绕过连接池,直接使用 PostgreSQL 数据库的端口(pg_port,默认值 5432),对于一些不希望使用连接池的场景,这个参数非常实用。

示例:pg-test-primary 的 haproxy 配置
listen pg-test-primary
    bind *:5433         # <--- primary 服务默认使用 5433 端口
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /primary # <--- primary 服务默认使用 Patroni RestAPI /primary 健康检查
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-1 10.10.10.11:6432 check port 8008 weight 100
    server pg-test-3 10.10.10.13:6432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:6432 check port 8008 weight 100

Patroni 的 高可用 机制确保任何时候最多只会有一个实例的 /primary 健康检查为真,因此Primary服务将始终将流量路由到主实例。

使用 Primary 服务而不是直连数据库的一个好处是,如果集群因为某种情况出现了双主(比如在没有watchdog的情况下kill -9杀死主库 Patroni),Haproxy在这种情况下仍然可以避免脑裂,因为它只会在 Patroni 存活且返回主库状态时才会分发流量。


Replica服务

Replica服务在生产环境中的重要性仅次于Primary服务,它在 5434 端口提供对数据库集群的只读能力,服务定义如下:

- { name: replica ,port: 5434 ,dest: default  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
  • 选择器参数 selector: "[]" 意味着所有集群成员都将被包括在Replica服务中
  • 所有实例都能够通过健康检查(check: /read-only),承载Replica服务的流量。
  • 备份选择器:[? pg_role == 'primary' || pg_role == 'offline' ] 将主库和 离线从库 标注为备份服务器。
  • 只有当所有 普通从库 都宕机后,Replica服务才会由主库或离线从库来承载。
  • 目的地参数 dest: default 意味着Replica服务的目的地也受到 pg_default_service_dest 参数的影响
  • dest 默认值 default 会被替换为 pg_default_service_dest 的值,默认为 pgbouncer,这一点和 Primary服务 相同
  • 默认情况下 Replica 服务的目的地默认是从库上的连接池,也就是由 pgbouncer_port 指定的端口,默认为 6432
示例:pg-test-replica 的 haproxy 配置
listen pg-test-replica
    bind *:5434
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /read-only
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-1 10.10.10.11:6432 check port 8008 weight 100 backup
    server pg-test-3 10.10.10.13:6432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:6432 check port 8008 weight 100

Replica服务非常灵活:如果有存活的专用 Replica 实例,那么它会优先使用这些实例来承载只读请求,只有当从库实例全部宕机后,才会由主库来兜底只读请求。对于常见的一主一从双节点集群就是:只要从库活着就用从库,从库挂了再用主库。

此外,除非专用只读实例全部宕机,Replica 服务也不会使用专用 Offline 实例,这样就避免了在线快查询与离线慢查询混在一起,相互影响。


Default服务

Default服务在 5436 端口上提供服务,它是Primary服务的变体。

Default服务总是绕过连接池直接连到主库上的 PostgreSQL,这对于管理连接、ETL写入、CDC数据变更捕获等都很有用。

- { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }

如果 pg_default_service_dest 被修改为 postgres,那么可以说 Default 服务除了端口和名称内容之外,与 Primary 服务是完全等价的。在这种情况下,您可以考虑将 Default 从默认服务中剔除。

示例:pg-test-default 的 haproxy 配置
listen pg-test-default
    bind *:5436         # <--- 除了监听端口/目标端口和服务名,其他配置和 primary 服务一模一样
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /primary
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-1 10.10.10.11:5432 check port 8008 weight 100
    server pg-test-3 10.10.10.13:5432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:5432 check port 8008 weight 100

Offline服务

Default服务在 5438 端口上提供服务,它也绕开连接池直接访问 PostgreSQL 数据库,通常用于慢查询/分析查询/ETL读取/个人用户交互式查询,其服务定义如下:

- { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]"}

Offline服务将流量直接路由到专用的 离线从库 上,或者带有 pg_offline_query 标记的普通 只读实例

  • 选择器参数从集群中筛选出了两种实例:pg_role = offline 的离线从库,或是带有 pg_offline_query = true 标记的普通 只读实例
  • 专用离线从库和打标记的普通从库主要的区别在于:前者默认不承载 Replica服务 的请求,避免快慢请求混在一起,而后者默认会承载。
  • 备份选择器参数从集群中筛选出了一种实例:不带 offline 标记的普通从库,这意味着如果离线实例或者带Offline标记的普通从库挂了之后,其他普通的从库可以用来承载Offline服务。
  • 健康检查 /replica 只会针对从库返回 200, 主库会返回错误,因此 Offline服务 永远不会将流量分发到主库实例上去,哪怕集群中只剩这一台主库。
  • 同时,主库实例既不会被选择器圈中,也不会被备份选择器圈中,因此它永远不会承载Offline服务。因此 Offline 服务总是可以避免用户访问主库,从而避免对主库的影响。
示例:pg-test-offline 的 haproxy 配置
listen pg-test-offline
    bind *:5438
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /replica
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-3 10.10.10.13:5432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:5432 check port 8008 weight 100 backup

Offline服务提供受限的只读服务,通常用于两类查询:交互式查询(个人用户),慢查询长事务(分析/ETL)。

Offline 服务需要额外的维护照顾:当集群发生主从切换或故障自动切换时,集群的实例角色会发生变化,而 Haproxy 的配置却不会自动发生变化。对于有多个从库的集群来说,这通常并不是一个问题。 然而对于一主一从,从库跑Offline查询的精简小集群而言,主从切换意味着从库变成了主库(健康检查失效),原来的主库变成了从库(不在 Offline 后端列表中),于是没有实例可以承载 Offline 服务了,因此需要手动 重载服务 以使变更生效。

如果您的业务模型较为简单,您可以考虑剔除 Default 服务与 Offline 服务,使用 Primary 服务与 Replica 服务直连数据库。


重载服务

当集群成员发生变化,如添加/删除副本、主备切换或调整相对权重时, 你需要 重载服务 以使更改生效。

bin/pgsql-svc <cls> [ip...]         # 为 lb 集群或 lb 实例重载服务
# ./pgsql.yml -t pg_service         # 重载服务的实际 ansible 任务

接入服务

Pigsty的服务交付边界止步于集群的HAProxy,用户可以用各种手段访问这些负载均衡器。

典型的做法是使用 DNS 或 VIP 接入,将其绑定在集群所有或任意数量的负载均衡器上。

pigsty-access.jpg

你可以使用不同的 主机 & 端口 组合,它们以不同的方式提供 PostgreSQL 服务。

主机

类型样例描述
集群域名pg-test通过集群域名访问(由 dnsmasq @ infra 节点解析)
集群 VIP 地址10.10.10.3通过由 vip-manager 管理的 L2 VIP 地址访问,绑定到主节点
实例主机名pg-test-1通过任何实例主机名访问(由 dnsmasq @ infra 节点解析)
实例 IP 地址10.10.10.11访问任何实例的 IP 地址

端口

Pigsty 使用不同的 端口 来区分 pg services

端口服务类型描述
5432postgres数据库直接访问 postgres 服务器
6432pgbouncer中间件访问 postgres 前先通过连接池中间件
5433primary服务访问主 pgbouncer (或 postgres)
5434replica服务访问备份 pgbouncer (或 postgres)
5436default服务访问主 postgres
5438offline服务访问离线 postgres

组合

# 通过集群域名访问
postgres://test@pg-test:5432/test # DNS -> L2 VIP -> 主直接连接
postgres://test@pg-test:6432/test # DNS -> L2 VIP -> 主连接池 -> 主
postgres://test@pg-test:5433/test # DNS -> L2 VIP -> HAProxy -> 主连接池 -> 主
postgres://test@pg-test:5434/test # DNS -> L2 VIP -> HAProxy -> 备份连接池 -> 备份
postgres://dbuser_dba@pg-test:5436/test # DNS -> L2 VIP -> HAProxy -> 主直接连接 (用于管理员)
postgres://dbuser_stats@pg-test:5438/test # DNS -> L2 VIP -> HAProxy -> 离线直接连接 (用于 ETL/个人查询)

# 通过集群 VIP 直接访问
postgres://test@10.10.10.3:5432/test # L2 VIP -> 主直接访问
postgres://test@10.10.10.3:6432/test # L2 VIP -> 主连接池 -> 主
postgres://test@10.10.10.3:5433/test # L2 VIP -> HAProxy -> 主连接池 -> 主
postgres://test@10.10.10.3:5434/test # L2 VIP -> HAProxy -> 备份连接池 -> 备份
postgres://dbuser_dba@10.10.10.3:5436/test # L2 VIP -> HAProxy -> 主直接连接 (用于管理员)
postgres://dbuser_stats@10.10.10.3::5438/test # L2 VIP -> HAProxy -> 离线直接连接 (用于 ETL/个人查询)

# 直接指定任何集群实例名
postgres://test@pg-test-1:5432/test # DNS -> 数据库实例直接连接 (单例访问)
postgres://test@pg-test-1:6432/test # DNS -> 连接池 -> 数据库
postgres://test@pg-test-1:5433/test # DNS -> HAProxy -> 连接池 -> 数据库读/写
postgres://test@pg-test-1:5434/test # DNS -> HAProxy -> 连接池 -> 数据库只读
postgres://dbuser_dba@pg-test-1:5436/test # DNS -> HAProxy -> 数据库直接连接
postgres://dbuser_stats@pg-test-1:5438/test # DNS -> HAProxy -> 数据库离线读/写

# 直接指定任何集群实例 IP 访问
postgres://test@10.10.10.11:5432/test # 数据库实例直接连接 (直接指定实例, 没有自动流量分配)
postgres://test@10.10.10.11:6432/test # 连接池 -> 数据库
postgres://test@10.10.10.11:5433/test # HAProxy -> 连接池 -> 数据库读/写
postgres://test@10.10.10.11:5434/test # HAProxy -> 连接池 -> 数据库只读
postgres://dbuser_dba@10.10.10.11:5436/test # HAProxy -> 数据库直接连接
postgres://dbuser_stats@10.10.10.11:5438/test # HAProxy -> 数据库离线读-写

# 智能客户端:自动进行读写分离
postgres://test@10.10.10.11:6432,10.10.10.12:6432,10.10.10.13:6432/test?target_session_attrs=primary
postgres://test@10.10.10.11:6432,10.10.10.12:6432,10.10.10.13:6432/test?target_session_attrs=prefer-standby

覆盖服务

你可以通过多种方式覆盖默认的服务配置,一种常见的需求是让 Primary服务Replica服务 绕过Pgbouncer连接池,直接访问 PostgreSQL 数据库。

为了实现这一点,你可以将 pg_default_service_dest 更改为 postgres,这样所有服务定义中 svc.dest='default' 的服务都会使用 postgres 而不是默认的 pgbouncer 作为目标。

如果您已经将 Primary服务 指向了 PostgreSQL,那么 default服务 就会比较多余,可以考虑移除。

如果您不需要区分个人交互式查询,分析/ETL慢查询,可以考虑从默认服务列表 pg_default_services 中移除 Offline服务

如果您不需要只读从库来分担在线只读流量,也可以从默认服务列表中移除 Replica服务


委托服务

Pigsty 通过节点上的 haproxy 暴露 PostgreSQL 服务。整个集群中的所有 haproxy 实例都使用相同的 服务定义 进行配置。

但是,你可以将 pg 服务委托给特定的节点分组(例如,专门的 haproxy 负载均衡器集群),而不是 PostgreSQL 集群成员上的 haproxy。

为此,你需要使用 pg_default_services 覆盖默认的服务定义,并将 pg_service_provider 设置为代理组名称。

例如,此配置将在端口 10013 的 proxy haproxy 节点组上公开 pg 集群的主服务。

pg_service_provider: proxy       # 使用端口 10013 上的 `proxy` 组的负载均衡器
pg_default_services:  [{ name: primary ,port: 10013 ,dest: postgres  ,check: /primary   ,selector: "[]" }]

用户需要确保每个委托服务的端口,在代理集群中都是唯一的。

在 43 节点生产环境仿真 沙箱 中提供了一个使用专用负载均衡器集群的例子:prod.yml

4 - 访问控制

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

Pigsty 提供了一套开箱即用的,基于 角色系统权限系统 的访问控制模型。

权限控制很重要,但很多用户做不好。因此 Pigsty 提供了一套开箱即用的精简访问控制模型,为您的集群安全性提供一个兜底。


角色系统

Pigsty 默认的角色系统包含四个 默认角色 和四个 默认用户

角色名称属性所属描述
dbrole_readonlyNOLOGIN角色:全局只读访问
dbrole_readwriteNOLOGINdbrole_readonly角色:全局读写访问
dbrole_adminNOLOGINpg_monitor,dbrole_readwrite角色:管理员/对象创建
dbrole_offlineNOLOGIN角色:受限的只读访问
postgresSUPERUSER系统超级用户
replicatorREPLICATIONpg_monitor,dbrole_readonly系统复制用户
dbuser_dbaSUPERUSERdbrole_adminpgsql 管理用户
dbuser_monitorpg_monitorpgsql 监控用户

这些 角色与用户 的详细定义如下所示:

pg_default_roles:                 # 全局默认的角色与系统用户
  - { name: dbrole_readonly  ,login: false ,comment: role for global read-only access     }
  - { name: dbrole_offline   ,login: false ,comment: role for restricted read-only access }
  - { name: dbrole_readwrite ,login: false ,roles: [dbrole_readonly] ,comment: role for global read-write access }
  - { name: dbrole_admin     ,login: false ,roles: [pg_monitor, dbrole_readwrite] ,comment: role for object creation }
  - { name: postgres     ,superuser: true  ,comment: system superuser }
  - { name: replicator ,replication: true  ,roles: [pg_monitor, dbrole_readonly] ,comment: system replicator }
  - { name: dbuser_dba   ,superuser: true  ,roles: [dbrole_admin]  ,pgbouncer: true ,pool_mode: session, pool_connlimit: 16 ,comment: pgsql admin user }
  - { name: dbuser_monitor ,roles: [pg_monitor] ,pgbouncer: true ,parameters: {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment: pgsql monitor user }

默认角色

Pigsty 中有四个默认角色:

  • 业务只读 (dbrole_readonly): 用于全局只读访问的角色。如果别的业务想要此库只读访问权限,可以使用此角色。
  • 业务读写 (dbrole_readwrite): 用于全局读写访问的角色,主属业务使用的生产账号应当具有数据库读写权限
  • 业务管理员 (dbrole_admin): 拥有DDL权限的角色,通常用于业务管理员,或者需要在应用中建表的场景(比如各种业务软件)
  • 离线只读访问 (dbrole_offline): 受限的只读访问角色(只能访问 offline 实例,通常是个人用户,ETL工具账号)

默认角色在 pg_default_roles 中定义,除非您确实知道自己在干什么,建议不要更改默认角色的名称。

- { name: dbrole_readonly  , login: false , comment: role for global read-only access  }                            # 生产环境的只读角色
- { name: dbrole_offline ,   login: false , comment: role for restricted read-only access (offline instance) }      # 受限的只读角色
- { name: dbrole_readwrite , login: false , roles: [dbrole_readonly], comment: role for global read-write access }  # 生产环境的读写角色
- { name: dbrole_admin , login: false , roles: [pg_monitor, dbrole_readwrite] , comment: role for object creation } # 生产环境的 DDL 更改角色

默认用户

Pigsty 也有四个默认用户(系统用户):

  • 超级用户 (postgres),集群的所有者和创建者,与操作系统 dbsu 名称相同。
  • 复制用户 (replicator),用于主-从复制的系统用户。
  • 监控用户 (dbuser_monitor),用于监控数据库和连接池指标的用户。
  • 管理用户 (dbuser_dba),执行日常操作和数据库更改的管理员用户。

这4个默认用户的用户名/密码通过4对专用参数进行定义,并在很多地方引用:

在生产部署中记得更改这些密码,不要使用默认值!

pg_dbsu: postgres                             # 数据库超级用户名,这个用户名建议不要修改。
pg_dbsu_password: ''                          # 数据库超级用户密码,这个密码建议留空!禁止dbsu密码登陆。
pg_replication_username: replicator           # 系统复制用户名
pg_replication_password: DBUser.Replicator    # 系统复制密码,请务必修改此密码!
pg_monitor_username: dbuser_monitor           # 系统监控用户名
pg_monitor_password: DBUser.Monitor           # 系统监控密码,请务必修改此密码!
pg_admin_username: dbuser_dba                 # 系统管理用户名
pg_admin_password: DBUser.DBA                 # 系统管理密码,请务必修改此密码!

如果您修改默认用户的参数,在 pg_default_roles 中修改相应的角色 定义 即可:

- { name: postgres     ,superuser: true                                          ,comment: system superuser }
- { name: replicator ,replication: true  ,roles: [pg_monitor, dbrole_readonly]   ,comment: system replicator }
- { name: dbuser_dba   ,superuser: true  ,roles: [dbrole_admin]  ,pgbouncer: true ,pool_mode: session, pool_connlimit: 16 , comment: pgsql admin user }
- { name: dbuser_monitor   ,roles: [pg_monitor, dbrole_readonly] ,pgbouncer: true ,parameters: {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment: pgsql monitor user }

权限系统

Pigsty 拥有一套开箱即用的权限模型,该模型与 默认角色 一起配合工作。

  • 所有用户都可以访问所有模式。
  • 只读用户(dbrole_readonly)可以从所有表中读取数据。(SELECT,EXECUTE)
  • 读写用户(dbrole_readwrite)可以向所有表中写入数据并运行 DML。(INSERT,UPDATE,DELETE)。
  • 管理员用户(dbrole_admin)可以创建对象并运行 DDL(CREATE,USAGE,TRUNCATE,REFERENCES,TRIGGER)。
  • 离线用户(dbrole_offline)类似只读用户,但访问受到限制,只允许访问 离线实例pg_role = 'offline'pg_offline_query = true
  • 由管理员用户创建的对象将具有正确的权限。
  • 所有数据库上都配置了默认权限,包括模板数据库。
  • 数据库连接权限由数据库 定义 管理。
  • 默认撤销PUBLIC在数据库和public模式下的CREATE权限。

对象权限

数据库中新建对象的默认权限由参数 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

由管理员新创建的对象,默认将会上述权限。使用 \ddp+ 可以查看这些默认权限:

类型访问权限
函数=X
dbrole_readonly=X
dbrole_offline=X
dbrole_admin=X
模式dbrole_readonly=U
dbrole_offline=U
dbrole_admin=UC
序列号dbrole_readonly=r
dbrole_offline=r
dbrole_readwrite=wU
dbrole_admin=rwU
dbrole_readonly=r
dbrole_offline=r
dbrole_readwrite=awd
dbrole_admin=arwdDxt

默认权限

ALTER DEFAULT PRIVILEGES 允许您设置将来创建的对象的权限。 它不会影响已经存在对象的权限,也不会影响非管理员用户创建的对象。

在 Pigsty 中,默认权限针对三个角色进行定义:

{% for priv in pg_default_privileges %}
ALTER DEFAULT PRIVILEGES FOR ROLE {{ pg_dbsu }} {{ priv }};
{% endfor %}

{% for priv in pg_default_privileges %}
ALTER DEFAULT PRIVILEGES FOR ROLE {{ pg_admin_username }} {{ priv }};
{% endfor %}

-- 对于其他业务管理员而言,它们应当在执行 DDL 前执行 SET ROLE dbrole_admin,从而使用对应的默认权限配置。
{% for priv in pg_default_privileges %}
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" {{ priv }};
{% endfor %}

这些内容将会被 PG集群初始化模板 pg-init-template.sql 所使用,在集群初始化的过程中渲染并输出至 /pg/tmp/pg-init-template.sql。 该命令会在 template1postgres 数据库中执行,新创建的数据库会通过模板 template1 继承这些默认权限配置。

也就是说,为了维持正确的对象权限,您必须用管理员用户来执行 DDL,它们可以是:

  1. {{ pg_dbsu }},默认为 postgres
  2. {{ pg_admin_username }},默认为 dbuser_dba
  3. 授予了 dbrole_admin 角色的业务管理员用户(通过 SET ROLE 切换为 dbrole_admin 身份)。

使用 postgres 作为全局对象所有者是明智的。如果您希望以业务管理员用户身份创建对象,创建之前必须使用 SET ROLE dbrole_admin 来维护正确的权限。

当然,您也可以在数据库中通过 ALTER DEFAULT PRIVILEGE FOR ROLE <some_biz_admin> XXX 来显式对业务管理员授予默认权限。


数据库权限

在 Pigsty 中,数据库(Database)层面的权限在 数据库定义 中被涵盖。

数据库有三个级别的权限:CONNECTCREATETEMP,以及一个特殊的’权限’:OWNERSHIP

- name: meta         # 必选,`name` 是数据库定义中唯一的必选字段
  owner: postgres    # 可选,数据库所有者,默认为 postgres
  allowconn: true    # 可选,是否允许连接,默认为 true。显式设置 false 将完全禁止连接到此数据库
  revokeconn: false  # 可选,撤销公共连接权限。默认为 false,设置为 true 时,属主和管理员之外用户的 CONNECT 权限会被回收
  • 如果 owner 参数存在,它作为数据库属主,替代默认的 {{ pg_dbsu }}(通常也就是postgres
  • 如果 revokeconnfalse,所有用户都有数据库的 CONNECT 权限,这是默认的行为。
  • 如果显式设置了 revokeconntrue
    • 数据库的 CONNECT 权限将从 PUBLIC 中撤销:普通用户无法连接上此数据库
    • CONNECT 权限将被显式授予 {{ pg_replication_username }}{{ pg_monitor_username }}{{ pg_admin_username }}
    • CONNECT 权限将 GRANT OPTION 被授予数据库属主,数据库属主用户可以自行授权其他用户连接权限。
  • revokeconn 选项可用于在同一个集群间隔离跨数据库访问,您可以为每个数据库创建不同的业务用户作为属主,并为它们设置 revokeconn 选项。
示例:数据库隔离
pg-infra:
  hosts:
    10.10.10.40: { pg_seq: 1, pg_role: primary }
    10.10.10.41: { pg_seq: 2, pg_role: replica , pg_offline_query: true }
  vars:
    pg_cluster: pg-infra
    pg_users:
      - { name: dbuser_confluence, password: mc2iohos , pgbouncer: true, roles: [ dbrole_admin ] }
      - { name: dbuser_gitlab, password: sdf23g22sfdd , pgbouncer: true, roles: [ dbrole_readwrite ] }
      - { name: dbuser_jira, password: sdpijfsfdsfdfs , pgbouncer: true, roles: [ dbrole_admin ] }
    pg_databases:
      - { name: confluence , revokeconn: true, owner: dbuser_confluence , connlimit: 100 }
      - { name: gitlab , revokeconn: true, owner: dbuser_gitlab, connlimit: 100 }
      - { name: jira , revokeconn: true, owner: dbuser_jira , connlimit: 100 }

CREATE权限

出于安全考虑,Pigsty 默认从 PUBLIC 撤销数据库上的 CREATE 权限,从 PostgreSQL 15 开始这也是默认行为。

数据库属主总是可以根据实际需要,来自行调整 CREATE 权限。

5 - 管理任务

数据库管理与运维任务

6 - 日常管理

数据库日常管理任务标准操作指南(SOP)

6.1 - 管理 PostgreSQL 数据库集群

创建/销毁 PostgreSQL 集群,以及对现有集群进行扩容,缩容,克隆集群。

速查手册

操作快捷命令说明
创建集群bin/pgsql-add <cls>创建新的 PostgreSQL 集群
扩容集群bin/pgsql-add <cls> <ip...>为现有集群添加从库副本
缩容集群bin/pgsql-rm <cls> <ip...>从集群中移除指定实例
销毁集群bin/pgsql-rm <cls>销毁整个 PostgreSQL 集群
刷新服务bin/pgsql-svc <cls> [ip...]重载集群的负载均衡配置
刷新HBAbin/pgsql-hba <cls> [ip...]重载集群的 HBA 访问规则
克隆集群-通过备份集群或 PITR 克隆

其他管理任务,请参考:高可用管理管理用户管理数据库


创建集群

要创建一个新的 PostgreSQL 集群,请首先在 配置清单定义集群,然后 纳管节点并进行初始化:

bin/node-add  <cls>     # 添加分组 <cls> 下的节点
./node.yml  -l <cls>    # 直接使用 Ansible 剧本添加分组 <cls> 下的节点
bin/pgsql-add pg-test   # 例子,添加 pg-test 分组下的节点,实际执行 ./node.yml -l pg-test

在被纳管的节点上,可以使用以下命令创建集群:(针对 <cls> 分组执行 pgsql.yml 剧本)

bin/pgsql-add <cls>     # 创建 PostgreSQL 集群 <cls>
./pgsql.yml -l <cls>    # 直接使用 Ansible 剧本创建 PostgreSQL 集群 <cls>
bin/pgsql-add pg-test   # 例子,创建 pg-test 集群

示例:创建三节点 PG 集群 pg-test


扩容集群

若要将新从库添加到 现有的 PostgreSQL 集群 中,您需要将 实例定义 添加到 配置清单all.children.<cls>.hosts 中。

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 }

扩容集群的操作与 创建集群 非常类似,首先需要将扩容的节点纳入 Pigsty 管理:添加节点

bin/node-add <ip>       # 添加 IP 地址为 <ip> 的节点
./node.yml -l <ip>      # 直接使用 Ansible 剧本添加 <ip> 对应的节点
bin/node-add 10.10.10.13    # 例子,添加 IP 为 10.10.10.13 的节点,实际执行 ./node.yml -l 10.10.10.13

然后在新节点上运行以下命令以扩容集群(针对新节点安装 PGSQL 模块,使用与现有集群相同的 pg_cluster

bin/pgsql-add <cls> <ip>  # 添加 IP 地址为 <ip> 的节点
./pgsql.yml -l <ip>       # 核心逻辑:使用 Ansible 剧本在 <ip> 节点上安装 PGSQL 模块
bin/pgsql-add pg-test 10.10.10.13   # 示例,为 pg-test 集群扩容 IP 为 10.10.10.13 的节点

扩容完成后,您应当 刷新服务 以将新成员添加至负载均衡器中以实际承载流量。

示例:为两节点集群 pg-test 扩容一个新从库 10.10.10.13


缩容集群

若要从 现有的 PostgreSQL 集群 中移除副本,您需要从 配置清单all.children.<cls>.hosts 中移除对应的 实例定义

缩容集群首先需要卸载目标节点上的 PGSQL 模块(针对 <ip> 执行 pgsql-rm.yml 剧本):

bin/pgsql-rm <cls> <ip>   # 从集群 <cls> 中移除 <ip> 节点上的 PostgreSQL 实例
./pgsql-rm.yml -l <ip>    # 直接使用 Ansible 剧本移除 <ip> 节点上的 PostgreSQL 实例
bin/pgsql-rm pg-test 10.10.10.13  # 例子,从 pg-test 集群移除 10.10.10.13 节点

移除 PGSQL 模块后,您可以选择将节点从 Pigsty 管理中移除:移除节点(可选):

bin/node-rm <ip>          # 从 Pigsty 管理中移除 <ip> 节点
./node-rm.yml -l <ip>     # 直接使用 Ansible 剧本从 Pigsty 管理中移除 <ip> 节点
bin/node-rm 10.10.10.13   # 例子,从 Pigsty 管理中移除 10.10.10.13 节点

缩容完成后,您应当从 配置清单 中移除该实例的定义,然后 刷新服务 以将已它从负载均衡器中踢除。

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-test 中缩容一个从库 10.10.10.13


销毁集群

销毁集群需要在集群的所有节点上卸载 PGSQL 模块(针对 <cls> 执行 pgsql-rm.yml 剧本):

bin/pgsql-rm <cls>        # 销毁整个 PostgreSQL 集群 <cls>
./pgsql-rm.yml -l <cls>   # 直接使用 Ansible 剧本销毁整个 PostgreSQL 集群 <cls>
bin/pgsql-rm pg-test      # 例子,销毁 pg-test 集群

销毁 PGSQL 模块后,您可以选择将节点一并从 Pigsty 管理中移除:移除节点(可选,如果还有其他服务可以保留):

bin/node-rm <cls>         # 从 Pigsty 管理中移除 <cls> 分组下的所有节点
./node-rm.yml -l <cls>    # 直接使用 Ansible 剧本从 Pigsty 管理中移除 <cls> 分组下的所有节点
bin/node-rm pg-test       # 例子,从 Pigsty 管理中移除 pg-test 分组下的所有节点

销毁结束后,建议及时从 配置清单 中移除整个 集群定义

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 集群 pg-test

注意:如果为这个集群配置了 pg_safeguard(或全局设置为 true),pgsql-rm.yml 将中止执行,以避免意外销毁集群。 您可以使用剧本命令行参数明确地覆盖它,以强制执行销毁。 此外默认情况下,集群的备份仓库将同集群一并删除。如果你希望保留备份(例如在使用集中式备份仓库时),可以设置 pg_rm_backup=false 参数:

./pgsql-rm.yml -l pg-meta -e pg_safeguard=false    # 强制销毁受保护的 pg 集群 pg-meta
./pgsql-rm.yml -l pg-meta -e pg_rm_backup=false    # 在销毁集群过程中保留其备份仓库

刷新服务

PostgreSQL 集群通过主机节点上的 HAProxy 对外提供 服务。 当服务定义变化,实例权重变化,或者集群成员发生变化时(例如,集群 扩容 / 缩容,主从切换/故障转移),您需要择机刷新服务以更新负载均衡器的配置。

要在整个集群或特定实例上刷新服务配置(针对 <cls><ip> 执行 pgsql.ymlpg_service 子任务):

bin/pgsql-svc <cls>           # 刷新整个集群 <cls> 的服务配置
bin/pgsql-svc <cls> <ip...>   # 刷新集群 <cls> 中指定实例的服务配置
./pgsql.yml -l <cls> -t pg_service -e pg_reload=true        # 刷新整个集群的服务配置
./pgsql.yml -l <ip>  -t pg_service -e pg_reload=true        # 刷新指定实例的服务配置
bin/pgsql-svc pg-test                 # 例子,刷新 pg-test 集群的服务配置
bin/pgsql-svc pg-test 10.10.10.13     # 例子,刷新 pg-test 集群中 10.10.10.13 实例的服务配置

备注:如果您使用集中式的专用负载均衡集群(pg_service_provider),那么只有刷新集群主库时才会更新负载均衡配置。

示例:刷新集群 pg-test 的服务配置

示例:重载PG服务以踢除一个实例

asciicast


刷新HBA

当您修改了 HBA 相关配置后,需要刷新 HBA 规则以应用更改。(pg_hba_rules / pgb_hba_rules) 如果您有任何特定于角色的 HBA 规则,或者在 IP 地址段中引用了集群成员的别名,那么当主从切换/集群扩缩容后也可能需要刷新 HBA。

要在整个集群或特定实例上刷新 PG 和 Pgbouncer 的 HBA 规则(针对 <cls><ip> 执行 pgsql.yml 的 HBA 相关子任务):

bin/pgsql-hba <cls>           # 刷新整个集群 <cls> 的 HBA 规则
bin/pgsql-hba <cls> <ip...>   # 刷新集群 <cls> 中指定实例的 HBA 规则
./pgsql.yml -l <cls> -t pg_hba,pg_reload,pgbouncer_hba,pgbouncer_reload -e pg_reload=true   # 刷新整个集群
./pgsql.yml -l <ip>  -t pg_hba,pg_reload,pgbouncer_hba,pgbouncer_reload -e pg_reload=true   # 刷新指定实例
bin/pgsql-hba pg-test                 # 例子,刷新 pg-test 集群的 HBA 规则
bin/pgsql-hba pg-test 10.10.10.13     # 例子,刷新 pg-test 集群中 10.10.10.13 实例的 HBA 规则

示例:刷新集群 pg-test 的 HBA 规则


配置集群

PostgreSQL 的配置参数由 Patroni 管理,初始参数由 Patroni 配置模板 指定。 集群初始化之后,配置存储在 Etcd 中,并由 Patroni 进行动态管理,并在集群中同步与共享。 Patroni 本身的 配置参数 大部分可以通过 patronictl命令行工具修改。 其余参数(例如,etcd DCS 配置,日志/RestAPI 等配置)则可以通过下面的子任务进行更新。例如,当 etcd 集群成员发生变动时,你可以刷新 Patroni 配置:

./pgsql.yml -l pg-test -t pg_conf                   # 更新 Patroni 配置文件
ansible pg-test -b -a 'systemctl reload patroni'    # 重载 Patroni 服务

您可以在不同层次上覆盖 Patroni 集中管理的默认,例如单独 为实例指定配置参数; 单独为 为用户指定配置参数,或者 为数据库指定配置参数


克隆集群

有两种克隆集群的方式:使用 备份集群 功能,或者使用 时间点恢复 功能。 前者配置简单,无需依赖,但只能克隆指定集群的最新状态;后者依赖集中式的 备份仓库(例如 MinIO),但可以克隆到备份保留期内的任意时间点。

方式优点缺点适用场景
备份集群配置简单,无需依赖只能克隆最新状态灾备,读写分离,迁移
PITR可恢复到任意时间点依赖集中式备份仓库误操作恢复,数据审计

使用备份集群克隆

备份集群(Standby Cluster)通过流复制从上游集群持续同步数据,是克隆集群最简单的方式。 只需在新集群主库上指定 pg_upstream 参数,即可自动从上游集群拉取数据。

# 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 }  # 指定上游
    10.10.10.13: { pg_seq: 2, pg_role: replica }
  vars: { pg_cluster: pg-test2 }

使用以下命令创建备份集群:

bin/pgsql-add pg-test2    # 创建备份集群,自动从上游 pg-test 克隆数据
./pgsql.yml -l pg-test2   # 直接使用 Ansible 剧本创建备份集群

备份集群会持续追随上游集群,保持数据同步。您可以随时将其 提升 为独立集群:

示例:提升备份集群为独立集群

通过 配置集群 擦除 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-test2 将成为可以独立承载写入请求的独立集群,与原集群 pg-test 分叉。

示例:更改复制上游

如果上游集群发生主从切换,您可以通过 配置集群 更改备份集群的复制上游:

$ pg edit-config pg-test2

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

Apply these changes? [y/N]: y

使用 PITR 克隆

时间点恢复(PITR)允许您将集群恢复到备份保留期内的任意时间点。 此方式依赖集中式的 备份仓库(如 MinIO/S3),但功能更加强大。

要使用 PITR 克隆集群,在配置中添加 pg_pitr 参数指定恢复目标:

# 从 pg-meta 集群的备份克隆一个新集群 pg-meta2
pg-meta2:
  hosts: { 10.10.10.12: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta2
    pg_pitr:
      cluster: pg-meta                    # 从 pg-meta 的备份恢复
      time: '2025-01-10 10:00:00+00'      # 恢复到指定时间点

使用 pgsql-pitr.yml 剧本执行克隆:

./pgsql-pitr.yml -l pg-meta2    # 从 pg-meta 备份克隆 pg-meta2
# 也可以通过命令行参数指定 PITR 选项
./pgsql-pitr.yml -l pg-meta2 -e '{"pg_pitr": {"cluster": "pg-meta", "time": "2025-01-10 10:00:00+00"}}'

PITR 支持多种恢复目标类型:

目标类型参数示例说明
时间点time: "2025-01-10 10:00:00+00"恢复到指定时间戳
事务IDxid: "250000"恢复到指定事务之前/之后
恢复点name: "before_migration"恢复到命名恢复点
LSNlsn: "0/4001C80"恢复到指定 WAL 位置
最新type: "latest"恢复到 WAL 归档末尾

更多 PITR 的详细用法,请参考 恢复操作 文档。

6.2 - 管理 PostgreSQL 业务用户

用户管理:创建、修改、删除用户,管理角色成员关系,连接池用户配置

快速上手

Pigsty 使用声明式管理方式,首先在 配置清单定义用户,然后使用 bin/pgsql-user <cls> <username> 创建或修改用户。

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_users: [{ name: dbuser_app, password: 'DBUser.App', pgbouncer: true }]  # <--- 在这里定义用户列表!
bin/pgsql-user <cls> <username>    # 在 <cls> 集群上创建/修改 <username> 用户
./pgsql-user.yml -l pg-meta -e username=dbuser_app    # 直接使用剧本在 <cls> 集群上创建/修改 <username> 用户
bin/pgsql-user pg-meta dbuser_app    # 在 pg-meta 集群上创建/修改 dbuser_app 用户

关于用户定义参数的完整参考,请查阅 用户配置。关于用户的访问权限,请参考 ACL:角色权限

请注意,用户的 name 字段在创建后无法修改。如需更改用户名,请先删除原用户,再创建新用户。

操作快捷命令说明
创建用户bin/pgsql-user <cls> <user>创建新的业务用户或角色
修改用户bin/pgsql-user <cls> <user>修改已存在用户的属性
删除用户bin/pgsql-user <cls> <user>安全删除用户(需设置 state: absent

创建用户

定义在 pg_users 里面的用户会在 PostgreSQL 集群创建 的时候在 pg_user 任务中自动创建。

要在现有的 PostgreSQL 集群上创建新的业务用户,请将 用户定义 添加到 all.children.<cls>.pg_users,然后执行:

bin/pgsql-user <cls> <username>   # 创建用户 <username>
./pgsql-user.yml -l <cls> -e username=<username>   # 直接使用 Ansible 剧本创建用户
bin/pgsql-user pg-meta dbuser_app    # 例子,在 pg-meta 集群中创建 dbuser_app 用户

示例配置:创建名为 dbuser_app 的业务用户

#all.children.pg-meta.vars.pg_users: # 省略上级缩进
  - name: dbuser_app
    password: DBUser.App
    pgbouncer: true
    roles: [dbrole_readwrite]
    comment: application user for myapp

执行效果:在主库上创建用户 dbuser_app,设置密码,授予 dbrole_readwrite 角色权限, 将用户添加到 Pgbouncer 连接池,在每个实例上重载 Pgbouncer 配置使其立即生效。


修改用户

修改用户与创建用户使用相同的命令,剧本是幂等的。当目标用户已存在时,Pigsty 会修改目标用户的属性使其符合配置。

bin/pgsql-user <cls> <user>   # 修改用户 <user> 的属性
./pgsql-user.yml -l <cls> -e username=<user>   # 幂等操作,可重复执行
bin/pgsql-user pg-meta dbuser_app    # 修改 dbuser_app 用户的属性使其符合配置

不可修改的属性:用户的 name(名称)在创建后无法修改,需要先删除再创建。

其他属性均可修改,以下是一些常见的修改示例:

修改密码:更新配置中的 password 字段后执行剧本。密码修改时会临时禁用日志记录,避免密码泄露到日志中。

- name: dbuser_app
  password: NewSecretPassword     # 修改密码

修改权限属性:通过配置相应的布尔标志来修改用户权限。

- name: dbuser_app
  superuser: false           # 超级用户(谨慎使用!)
  createdb: true             # 允许创建数据库
  createrole: false          # 允许创建角色
  inherit: true              # 自动继承角色权限
  replication: false         # 允许流复制连接
  bypassrls: false           # 绕过行级安全策略
  connlimit: 50              # 限制连接数,-1 不限制

修改用户有效期:使用 expire_in 设置相对过期时间(N 天后过期),或 expire_at 设置绝对过期日期。expire_in 优先级更高,每次执行剧本时会重新计算,适合需要定期续期的临时用户。

- name: temp_user
  expire_in: 30                   # 30 天后过期(相对时间)

- name: contractor_user
  expire_at: '2024-12-31'         # 指定日期过期(绝对时间)

- name: permanent_user
  expire_at: 'infinity'           # 永不过期

修改角色成员关系:通过 roles 数组配置角色成员关系,支持简单格式和扩展格式。角色成员关系是增量操作,不会移除未声明的现有角色。使用 state: absent 可以显式撤销角色。

- name: dbuser_app
  roles:
    - dbrole_readwrite                      # 简单形式:授予角色
    - { name: dbrole_admin, admin: true }   # 带 ADMIN OPTION(可以将此角色授予其他用户)
    - { name: pg_monitor, set: false }      # PG16+: 不允许 SET ROLE
    - { name: old_role, state: absent }     # 撤销角色成员关系

管理用户参数:通过 parameters 字典配置用户级参数,会生成 ALTER USER ... SET 语句。使用特殊值 DEFAULT 可将参数重置为 PostgreSQL 默认值。

- name: dbuser_analyst
  parameters:
    work_mem: '256MB'
    statement_timeout: '5min'
    search_path: 'analytics,public'
    log_statement: DEFAULT        # 重置为默认值

连接池配置:设置 pgbouncer: true 将用户添加到连接池,可选配置 pool_mode(池化模式:transaction/session/statement)和 pool_connlimit(用户最大连接数)。

- name: dbuser_app
  pgbouncer: true                 # 添加到连接池
  pool_mode: transaction          # 池化模式
  pool_connlimit: 50              # 用户最大连接数

删除用户

要删除用户,将其 state 设置为 absent 并执行剧本:

bin/pgsql-user <cls> <user>   # 删除用户 <user>(需在配置中设置 state: absent)
./pgsql-user.yml -l <cls> -e username=<user>   # 直接使用 Ansible 剧本删除用户
bin/pgsql-user pg-meta dbuser_old    # 删除 dbuser_old 用户(配置中已设置 state: absent)

配置示例

pg_users:
  - name: dbuser_old
    state: absent

删除操作会:使用 pg-drop-role 脚本安全删除用户,自动禁用用户登录并终止活跃连接,自动转移数据库/表空间所有权到 postgres,自动处理所有数据库中的对象所有权和权限,撤销所有角色成员关系,创建审计日志,从 Pgbouncer 用户列表中移除并重载配置。

保护机制:以下系统用户无法删除,会被自动跳过:postgres(超级用户)、replicator(或 pg_replication_username 配置的用户)、dbuser_dba(或 pg_admin_username 配置的用户)、dbuser_monitor(或 pg_monitor_username 配置的用户)。


手工删除用户

如果需要手动删除用户,可以直接使用 pg-drop-role 脚本:

# 检查依赖关系(只读操作)
pg-drop-role dbuser_old --check

# 预览删除操作(不实际执行)
pg-drop-role dbuser_old --dry-run -v

# 删除用户,转移对象给 postgres
pg-drop-role dbuser_old

# 强制删除(终止活跃连接)
pg-drop-role dbuser_old --force

# 删除用户,转移对象给指定用户
pg-drop-role dbuser_old dbuser_new

常见用例

下面是一些常见的用户配置示例:

创建基本业务用户

- name: dbuser_app
  password: DBUser.App
  pgbouncer: true
  roles: [dbrole_readwrite]
  comment: application user

创建只读用户

- name: dbuser_readonly
  password: DBUser.Readonly
  pgbouncer: true
  roles: [dbrole_readonly]

创建管理员用户(可执行 DDL)

- name: dbuser_admin
  password: DBUser.Admin
  pgbouncer: true
  pool_mode: session
  roles: [dbrole_admin]
  parameters:
    log_statement: 'all'

创建临时用户(30天后过期)

- name: temp_contractor
  password: TempPassword
  expire_in: 30
  roles: [dbrole_readonly]

创建角色(不可登录,用于权限分组)

- name: custom_role
  login: false
  comment: custom role for special permissions

创建带高级角色选项的用户(PG16+)

- name: dbuser_special
  password: DBUser.Special
  pgbouncer: true
  roles:
    - dbrole_readwrite
    - { name: dbrole_admin, admin: true }
    - { name: pg_monitor, set: false }
    - { name: pg_execute_server_program, inherit: false }

查询用户

以下是一些常用的 SQL 查询,用于查看用户信息:

查看所有用户

SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb,
       rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolvaliduntil
FROM pg_roles WHERE rolname NOT LIKE 'pg_%' ORDER BY rolname;

查看用户的角色成员关系

SELECT r.rolname AS member, g.rolname AS role, m.admin_option, m.set_option, m.inherit_option
FROM pg_auth_members m
JOIN pg_roles r ON r.oid = m.member
JOIN pg_roles g ON g.oid = m.roleid
WHERE r.rolname = 'dbuser_app';

查看用户级参数设置

SELECT rolname, setconfig FROM pg_db_role_setting s
JOIN pg_roles r ON r.oid = s.setrole WHERE s.setdatabase = 0;

查看即将过期的用户

SELECT rolname, rolvaliduntil, rolvaliduntil - CURRENT_TIMESTAMP AS time_remaining
FROM pg_roles WHERE rolvaliduntil IS NOT NULL
  AND rolvaliduntil < CURRENT_TIMESTAMP + INTERVAL '30 days'
ORDER BY rolvaliduntil;

连接池管理

在用户定义中配置的 连接池参数 会在创建/修改用户时应用到 Pgbouncer 连接池中。

设置 pgbouncer: true 的用户会被添加到 /etc/pgbouncer/userlist.txt 文件中。用户级别的连接池参数(pool_modepool_connlimit)通过 /etc/pgbouncer/useropts.txt 文件配置。

您可以使用 postgres 操作系统用户,使用 pgb 别名访问 Pgbouncer 管理数据库。更多连接池管理操作,请参考 Pgbouncer 管理


管理默认用户密码

要修改普通用户的密码, 按照上面 修改用户 的说明,更新配置中的 password 字段并执行剧本即可。 不过修改 默认用户 的密码会稍微复杂一些,因为它们的密码还在多个地方被其他服务引用。

参数默认值对应用户用途
pg_admin_passwordDBUser.DBAdbuser_dba管理员用户密码
pg_monitor_passwordDBUser.Monitordbuser_monitor监控用户密码
pg_replication_passwordDBUser.Replicatorreplicator复制用户密码

要修改 pg_admin_password,请执行以下命令:

# Step 1: 修改配置文件中的密码 pg_admin_password 后(重要!),通过剧本批量修改密码
./pgsql-user.yml -e username=dbuser_dba -e '{"pg_users":[{"name":"dbuser_dba","password":"NewPass123"}]}'

# Step 2: 更新所有 PG 节点的 patroni 配置文件与 .pgpass,然后重载 patroni 配置
./pgsql.yml -t pg_conf,pg_pass,patroni_reload -e pg_reload=true

# Step 3: 刷新 /infra/env/.pgpass 以及 /infra/conf/pg_service.conf 对管理员密码的引用
./infra.yml -t env_pgpass,env_pg_service

要修改 pg_monitor_password,请执行以下命令:

# Step 1: 修改配置文件中的密码 pg_monitor_password 后(重要!),通过剧本批量修改密码
./pgsql-user.yml -e username=dbuser_monitor -e '{"pg_users":[{"name":"dbuser_monitor","password":"NewPass123"}]}'

# Step 2: 更新所有 PG 节点的 patroni 配置文件与 .pgpass,然后重载 patroni 配置
./pgsql.yml -t pg_conf,pg_pass,patroni_reload -e pg_reload=true

# Step 3: 刷新 pg_exporter 与 pgbouncer_exporter 配置里面使用的密码,更新 Grafana 监控面板中数据源使用的密码
./pgsql.yml -t pg_exporter,pgbouncer_exporter,add_ds

要修改 pg_replication_password,请执行以下命令:

# Step 1: 修改配置文件中的密码 pg_replication_password 后(重要!),通过剧本批量修改密码
./pgsql-user.yml -e username=replicator -e '{"pg_users":[{"name":"replicator","password":"NewPass123"}]}'

# Step 2: 更新所有 PG 节点的 patorni 配置文件与 .pgpass,然后重载 patroni 配置
./pgsql.yml -t pg_conf,pg_pass,patroni_reload -e pg_reload=true

# Step 3: 更新 Infra 节点的 .pgpass
./infra.yml -t env_pgpass

此外,Patroni 本身 RestAPI 的密码 patroni_password 可以通过以下命令进行修改:

# Step 1: 刷新 patroni 配置文件里面配置的密码,并重载 patroni 配置应用生效
./pgsql.yml -t pg_conf,patroni_reload -e pg_reload=true

# Step 2: 刷新 /infra/conf/patronictl.yml 对 patroni 密码的引用
./infra.yml -t env_patroni

修改前三个密码前,需先用 SQL 修改对应 PostgreSQL 用户的密码:ALTER USER <username> PASSWORD '<new_password>';

6.3 - 管理 PostgreSQL 业务数据库

数据库管理:创建、修改、删除、重建数据库,使用模板克隆数据库

快速上手

Pigsty 使用声明式管理方式,首先在 配置清单定义数据库,然后使用 bin/pgsql-db <cls> <dbname> 创建或修改数据库。

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_databases: [{ name: some_db }]  # <--- 在这里定义数据库列表!
bin/pgsql-db <cls> <dbname>    # 在 <cls> 集群上创建/修改 <dbname> 数据库
./pgsql-db.yml -l pg-meta -e dbname=some_db    # 直接使用剧本在 <cls> 集群上创建/修改 <dbname> 数据库
bin/pgsql-db pg-meta some_db    # 在 pg-meta 集群上创建/修改 some_db 数据库

关于数据库定义参数的完整参考,请查阅 数据库配置。关于数据库的访问权限,请参考 ACL:数据库权限

请注意,部分数据库参数仅能在 创建时 指定。修改这些参数需要先删除再创建数据库(使用 state: recreate 重建数据库)。

操作快捷命令说明
创建数据库bin/pgsql-db <cls> <db>创建新的业务数据库
修改数据库bin/pgsql-db <cls> <db>修改已存在数据库的属性
删除数据库bin/pgsql-db <cls> <db>删除数据库(需设置 state: absent
重建数据库bin/pgsql-db <cls> <db>先删再建(需设置 state: recreate
克隆数据库bin/pgsql-db <cls> <db>使用模板克隆数据库

创建数据库

定义在 pg_databases 里面的数据库会在 PostgreSQL 集群创建 的时候在 pg_db 任务中自动创建。

要在现有的 PostgreSQL 集群上创建新的业务数据库,请将 数据库定义 添加到 all.children.<cls>.pg_databases,然后执行:

bin/pgsql-db <cls> <dbname>   # 创建数据库 <dbname>
./pgsql-db.yml -l <cls> -e dbname=<dbname>   # 直接使用 Ansible 剧本创建数据库
bin/pgsql-db pg-meta myapp    # 例子,在 pg-meta 集群中创建 myapp 数据库

示例配置:创建名为 myapp 的业务数据库

#all.children.pg-meta.vars.pg_databases: # 省略上级缩进
  - name: myapp
    owner: dbuser_myapp
    schemas: [app]
    extensions:
      - { name: pg_trgm }
      - { name: btree_gin }
    comment: my application database

执行效果:在主库上创建数据库 myapp,设置数据库所有者为 dbuser_myapp,创建 schema app, 启用扩展 pg_trgmbtree_gin,数据库将默认添加到 Pgbouncer 连接池,并注册为 Grafana PG 数据源。


修改数据库

修改数据库与创建数据库使用相同的命令,在没有定义 baseline SQL 的情况下剧本是幂等的。

当目标数据库已存在时,Pigsty 会修改目标数据库的属性使其符合配置。然而,一些属性只能在数据库创建时设置。

bin/pgsql-db <cls> <db>   # 修改数据库 <db> 的属性
./pgsql-db.yml -l <cls> -e dbname=<db>   # 幂等操作,可重复执行
bin/pgsql-db pg-meta myapp    # 修改 myapp 数据库的属性使其符合配置

不可修改的属性:以下属性在数据库创建后无法修改,需要使用 state: recreate 重建数据库:

  • name(数据库名称)、template(模板数据库)、strategy(克隆策略)。
  • encoding(字符编码)、locale/lc_collate/lc_ctype(本地化设置)、locale_provider/icu_locale/icu_rules/builtin_locale(本地化提供者设置)

其他属性均可修改,以下是一些常见的修改示例:

修改属主:更新配置中的 owner 字段后执行剧本,会执行 ALTER DATABASE ... OWNER TO 并授予相应权限。

- name: myapp
  owner: dbuser_new_owner     # 修改为新属主

修改连接限制:通过 connlimit 限制数据库的最大连接数。

- name: myapp
  connlimit: 100              # 限制最大 100 个连接

回收公共连接权限:设置 revokeconn: true 会回收 PUBLIC 的 CONNECT 权限,仅允许属主、DBA、监控用户和复制用户连接。

- name: myapp
  owner: dbuser_myapp
  revokeconn: true            # 回收 PUBLIC 的 CONNECT 权限

管理数据库参数:通过 parameters 字典配置数据库级参数,会生成 ALTER DATABASE ... SET 语句。使用特殊值 DEFAULT 可将参数重置为默认值。

- name: myapp
  parameters:
    work_mem: '256MB'
    maintenance_work_mem: '512MB'
    statement_timeout: '30s'
    search_path: DEFAULT      # 重置为默认值

管理模式(Schema):通过 schemas 数组配置模式,支持简单格式和指定属主的完整格式。使用 state: absent 删除模式(CASCADE)。

- name: myapp
  schemas:
    - app                                   # 简单形式
    - { name: core, owner: dbuser_myapp }   # 指定属主
    - { name: deprecated, state: absent }   # 删除模式

管理扩展(Extension):通过 extensions 数组配置扩展,支持简单格式和指定 schema/版本的完整格式。使用 state: absent 卸载扩展(CASCADE)。

- name: myapp
  extensions:
    - postgis                                 # 简单形式
    - { name: vector, schema: public }        # 指定 schema
    - { name: pg_trgm, state: absent }        # 卸载扩展

连接池配置:默认情况下所有业务数据库都会添加到 Pgbouncer 连接池。可配置 pgbouncer(是否加入连接池)、pool_mode(池化模式)、pool_size(默认池大小)、pool_reserve(保留连接数)、pool_connlimit(最大数据库连接)等参数。

- name: myapp
  pgbouncer: true              # 是否加入连接池(默认 true)
  pool_mode: transaction       # 池化模式:transaction/session/statement
  pool_size: 64                # 默认池大小
  pool_connlimit: 100          # 最大数据库连接

删除数据库

要删除数据库,将其 state 设置为 absent 并执行剧本:

bin/pgsql-db <cls> <db>   # 删除数据库 <db>(需在配置中设置 state: absent)
./pgsql-db.yml -l <cls> -e dbname=<db>   # 直接使用 Ansible 剧本删除数据库
bin/pgsql-db pg-meta olddb    # 删除 olddb 数据库(配置中已设置 state: absent)

配置示例

pg_databases:
  - name: olddb
    state: absent

删除操作会:如果数据库标记为 is_template: true,先执行 ALTER DATABASE ... IS_TEMPLATE false;使用 DROP DATABASE ... WITH (FORCE) 强制删除数据库(PG13+)并终止所有活动连接;从 Pgbouncer 连接池中移除该数据库;从 Grafana 数据源中取消注册。

保护机制:系统数据库 postgrestemplate0template1 无法删除。删除操作仅在主库上执行,流复制会自动同步到从库。


重建数据库

recreate 状态用于重建数据库,等效于先删除再创建:

bin/pgsql-db <cls> <db>   # 重建数据库 <db>(需在配置中设置 state: recreate)
./pgsql-db.yml -l <cls> -e dbname=<db>   # 直接使用 Ansible 剧本重建数据库
bin/pgsql-db pg-meta testdb    # 重建 testdb 数据库(配置中已设置 state: recreate)

配置示例

pg_databases:
  - name: testdb
    state: recreate
    owner: dbuser_test
    baseline: test_init.sql    # 重建后执行初始化

适用场景:测试环境重置、清空开发数据库、修改不可变属性(编码、本地化等)、恢复数据库到初始状态。

与手动 DROP + CREATE 的区别:单条命令完成,无需两次操作;自动保留 Pgbouncer 和 Grafana 配置;执行后自动加载 baseline 初始化脚本。


克隆数据库

你可以通过 PG 的 template 机制复制一个 PostgreSQL 数据库,在克隆期间,不允许有任何连接到模版数据库的活动连接。

bin/pgsql-db <cls> <db>   # 克隆数据库 <db>(需在配置中指定 template)
./pgsql-db.yml -l <cls> -e dbname=<db>   # 直接使用 Ansible 剧本克隆数据库
bin/pgsql-db pg-meta meta_dev    # 克隆创建 meta_dev 数据库(配置中已指定 template: meta)

配置示例

pg_databases:
  - name: meta                   # 源数据库

  - name: meta_dev
    template: meta               # 以 meta 作为模板
    strategy: FILE_COPY          # PG15+ 克隆策略,PG18 瞬间生效

瞬间克隆(PG18+):如果使用 PostgreSQL 18 以上版本,Pigsty 默认设置了 file_copy_method,配合 strategy: FILE_COPY 可以在约 200ms 内完成数据库克隆,而不需要复制数据文件。例如克隆一个 30 GB 的数据库,普通克隆用时 18 秒,瞬间克隆仅需 200 毫秒。

手动克隆:确保清理掉所有连接到模版数据库的连接后执行:

SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'meta';
CREATE DATABASE meta_dev TEMPLATE meta STRATEGY FILE_COPY;

局限性与注意事项:瞬间克隆仅在支持的文件系统上可用(xfs,brtfs,zfs,apfs);不要使用 postgres 数据库作为模版数据库进行克隆;在高并发环境中使用瞬间克隆需要谨慎,需在克隆窗口(200ms)内清理掉所有连接到模版数据库的连接。


连接池管理

在数据库定义中配置的 连接池参数 会在创建/修改数据库时应用到 Pgbouncer 连接池中。

默认情况下所有业务数据库都会添加到 Pgbouncer 连接池(pgbouncer: true)。数据库会被添加到 /etc/pgbouncer/database.txt 文件中,数据库级别的连接池参数(pool_modepool_size 等)通过此文件配置。

您可以使用 postgres 操作系统用户,使用 pgb 别名访问 Pgbouncer 管理数据库。更多连接池管理操作,请参考 Pgbouncer 管理

6.4 - 管理 Patroni 高可用

使用 Patroni 管理 PG 集群高可用,包括,修改参数,查看状态,主从切换,重启,重做从库等操作。

概览

Pigsty 使用 Patroni 管理 PostgreSQL 集群,它可以用来修改集群配置,查看集群状态,执行主从切换,重启集群,重做从库等操作。

要使用 Patroni 进行管理,您需要有以下两种身份之一:

Patroni 提供了 patronictl 命令行工具用于管理,Pigsty 提供了封装的快捷命令 pg 来简化其操作。

通过 pg 别名使用 patronictl
pg ()
{
    local patroni_conf="/infra/conf/patronictl.yml";
    if [ ! -r ${patroni_conf} ]; then
        patroni_conf="/etc/patroni/patroni.yml";
        if [ ! -r ${patroni_conf} ]; then
            echo "error: patronictl config not found";
            return 1;
        fi;
    fi;
    patronictl -c ${patroni_conf} "$@"
}

可用命令

命令功能说明
edit-config修改配置交互式修改集群的 Patroni/PostgreSQL 配置
list查看状态列出集群成员及其状态
switchover主动切换将主库角色切换到指定从库(计划内维护)
failover故障切换强制故障转移到指定从库(紧急情况)
restart重启实例重启 PostgreSQL 实例以应用需要重启的参数
reload重载配置重载 Patroni 配置(无需重启)
reinit重做从库重新初始化从库(擦除数据并重新复制)
pause暂停自动切换暂停 Patroni 的自动故障转移功能
resume恢复自动切换恢复 Patroni 的自动故障转移功能
history查看历史显示集群的故障转移历史记录
show-config显示配置显示集群当前的配置(只读)
query执行查询在集群成员上执行 SQL 查询
topology查看拓扑显示集群的复制拓扑结构
version查看版本显示 Patroni 版本信息
remove移除成员从 DCS 中移除集群成员(危险操作)

修改配置

使用 edit-config 子命令可以交互式修改集群的 Patroni 与 PostgreSQL 配置。该命令会打开一个编辑器,让您修改存储在 DCS(分布式配置存储)中的集群配置,修改后会自动应用到所有集群成员。您可以更改 Patroni 本身的参数(如 ttlloop_waitsynchronous_mode 等),以及 postgresql.parameters 中的 PostgreSQL 参数。

pg edit-config <cls>                  # 交互式编辑集群配置
pg edit-config <cls> --force          # 跳过确认提示直接应用
pg edit-config <cls> -p <k>=<v>       # 修改 PostgreSQL 参数(--pg 简写)
pg edit-config <cls> -s <k>=<v>       # 修改 Patroni 参数(--set 简写)

以下是一些常见的配置修改示例:

# 修改 PostgreSQL 参数:慢查询阈值(会询问是否应用)
pg edit-config pg-test -p log_min_duration_statement=1000

# 修改 PostgreSQL 参数并跳过确认
pg edit-config pg-test -p log_min_duration_statement=1000 --force

# 修改多个 PostgreSQL 参数
pg edit-config pg-test -p work_mem=256MB -p maintenance_work_mem=1GB --force

# 修改 Patroni 参数:增大故障检测时间窗口(增大 RTO)
pg edit-config pg-test -s loop_wait=15 -s ttl=60 --force

# 修改 Patroni 参数:启用同步复制模式
pg edit-config pg-test -s synchronous_mode=true --force

# 修改 Patroni 参数:启用严格同步模式(至少一个同步从库才允许写入)
pg edit-config pg-test -s synchronous_mode_strict=true --force

# 修改需要重启的参数(修改后需执行 pg restart)
pg edit-config pg-test -p shared_buffers=4GB --force
pg edit-config pg-test -p shared_preload_libraries='timescaledb, pg_stat_statements' --force
pg edit-config pg-test -p max_connections=200 --force

部分参数修改后需要重启 PostgreSQL 才能生效,您可以使用 pg list 检查集群状态,带 * 标记的实例表示需要重启。然后使用 pg restart 命令重启集群使配置生效。 您也可以使用 curl 或编写程序直接调用 Patroni 提供的 REST API 来修改配置:

# 查看当前配置
curl -s 10.10.10.11:8008/config | jq .

# 通过 API 修改参数(需要认证)
curl -u 'postgres:Patroni.API' \
     -d '{"postgresql":{"parameters": {"log_min_duration_statement":200}}}' \
     -s -X PATCH http://10.10.10.11:8008/config | jq .

查看状态

使用 list 子命令可以查看集群成员及其状态。输出结果会显示每个实例的名称、主机地址、角色、运行状态、时间线和复制延迟等信息。这是日常运维中最常用的命令之一,用于快速了解集群的健康状况。

pg list <cls>                         # 查看指定集群的状态
pg list                               # 列出所有集群(需要在管理节点上执行)
pg list <cls> -e                      # 显示扩展信息(--extended)
pg list <cls> -t                      # 显示时间戳(--timestamp)
pg list <cls> -f json                 # 以 JSON 格式输出(--format)
pg list <cls> -W 5                    # 每 5 秒刷新一次(--watch)

输出示例:

+ Cluster: pg-test (7322261897169354773) -----+----+--------------+
| Member    | Host        | Role    | State   | TL | Lag in MB    |
+-----------+-------------+---------+---------+----+--------------+
| pg-test-1 | 10.10.10.11 | Leader  | running |  1 |              |
| pg-test-2 | 10.10.10.12 | Replica | running |  1 |            0 |
| pg-test-3 | 10.10.10.13 | Replica | running |  1 |            0 |
+-----------+-------------+---------+---------+----+--------------+

输出列说明:Member 是实例名称,由 pg_cluster-pg_seq 组成;Host 是实例所在主机的 IP 地址;Role 表示角色,包括 Leader(主库)、Replica(从库)、Sync Standby(同步从库)、Standby Leader(级联复制的级联主库)等;State 表示运行状态,常见值包括 running(正常运行)、streaming(流复制中)、in archive recovery(归档恢复中)、starting(启动中)、stopped(已停止)等;TL 是时间线编号(Timeline),每次主从切换后会递增;Lag in MB 是复制延迟,以 MB 为单位,主库不显示此值。

如果某个实例需要重启才能应用配置更改,实例名称后会显示 * 标记:

+ Cluster: pg-test (7322261897169354773) -------+----+--------------+
| Member      | Host        | Role    | State   | TL | Lag in MB    |
+-------------+-------------+---------+---------+----+--------------+
| pg-test-1 * | 10.10.10.11 | Leader  | running |  1 |              |
| pg-test-2 * | 10.10.10.12 | Replica | running |  1 |            0 |
+-------------+-------------+---------+---------+----+--------------+

主动切换

使用 switchover 子命令可以执行计划内的主从切换。Switchover 是一种优雅的切换方式:Patroni 会先确保从库完全同步,然后让主库降级为从库,最后提升目标从库为新主库。这个过程通常只需要几秒钟,期间会有短暂的写入不可用。适用于主库所在主机需要维护、升级、或者需要将主库迁移到性能更好的节点等场景。

pg switchover <cls>                   # 交互式切换,会提示选择目标从库
pg switchover <cls> --leader <old>    # 指定当前主库名称
pg switchover <cls> --candidate <new> # 指定目标从库名称
pg switchover <cls> --scheduled <time> # 定时切换,格式如 2024-12-01T03:00
pg switchover <cls> --force           # 跳过确认提示

执行切换前请确保所有从库复制状态正常(状态为 runningstreaming),复制延迟在可接受范围内,并已通知相关业务方。

# 交互式切换(推荐,会显示当前拓扑并提示选择)
$ pg switchover pg-test
Current cluster topology
+ Cluster: pg-test (7322261897169354773) -----+----+--------------+
| Member    | Host        | Role    | State   | TL | Lag in MB    |
+-----------+-------------+---------+---------+----+--------------+
| pg-test-1 | 10.10.10.11 | Leader  | running |  1 |              |
| pg-test-2 | 10.10.10.12 | Replica | running |  1 |            0 |
| pg-test-3 | 10.10.10.13 | Replica | running |  1 |            0 |
+-----------+-------------+---------+---------+----+--------------+
Primary [pg-test-1]:
Candidate ['pg-test-2', 'pg-test-3'] []: pg-test-2
When should the switchover take place (e.g. 2024-01-01T12:00) [now]:
Are you sure you want to switchover cluster pg-test, demoting current leader pg-test-1? [y/N]: y

# 非交互式切换(指定主库和候选从库)
pg switchover pg-test --leader pg-test-1 --candidate pg-test-2 --force

# 定时切换(在凌晨 3 点执行,适合维护窗口)
pg switchover pg-test --leader pg-test-1 --candidate pg-test-2 --scheduled "2024-12-01T03:00"

切换完成后,请使用 pg list 确认新的集群拓扑。


故障切换

使用 failover 子命令可以执行紧急故障切换。与 switchover 不同,failover 用于主库已经不可用的紧急情况。它会直接提升一个从库为新主库,而不等待原主库的确认。由于从库可能尚未完全同步所有数据,使用 failover 可能会导致少量数据丢失。因此,在非紧急情况下请优先使用 switchover

pg failover <cls>                     # 交互式故障切换
pg failover <cls> --leader <old>      # 指定原主库(用于验证,可选)
pg failover <cls> --candidate <new>   # 指定要提升的从库
pg failover <cls> --force             # 跳过确认提示

故障切换示例:

# 交互式故障切换
$ pg failover pg-test
Candidate ['pg-test-2', 'pg-test-3'] []: pg-test-2
Are you sure you want to failover cluster pg-test? [y/N]: y
Successfully failed over to "pg-test-2"

# 非交互式故障切换(紧急情况快速执行)
pg failover pg-test --candidate pg-test-2 --force

# 指定原主库进行验证(如果原主库名称不匹配会报错)
pg failover pg-test --leader pg-test-1 --candidate pg-test-2 --force

Switchover 与 Failover 的区别:Switchover 用于计划内维护,要求原主库在线,执行前会确保数据完全同步,不会丢失数据;Failover 用于紧急故障恢复,原主库可以离线,会直接提升从库,可能丢失未同步的数据。日常维护、升级请使用 Switchover;只有在主库彻底故障无法恢复时才使用 Failover。


重启实例

使用 restart 子命令可以重启 PostgreSQL 实例,通常用于应用需要重启才能生效的参数更改。Patroni 会协调重启过程,对于整个集群的重启会采用滚动方式:先重启从库,最后重启主库,以最小化服务中断。

pg restart <cls>                      # 重启整个集群的所有实例
pg restart <cls> <member>             # 重启指定实例
pg restart <cls> --role leader        # 仅重启主库
pg restart <cls> --role replica       # 仅重启所有从库
pg restart <cls> --pending            # 仅重启标记为需要重启的实例
pg restart <cls> --scheduled <time>   # 定时重启
pg restart <cls> --timeout <sec>      # 设置重启超时时间(秒)
pg restart <cls> --force              # 跳过确认提示

当您修改了需要重启才能生效的参数(如 shared_buffersshared_preload_librariesmax_connectionsmax_worker_processes 等)后,需要使用此命令重启实例。

# 查看哪些实例需要重启(名称后带 * 标记)
$ pg list pg-test
+ Cluster: pg-test (7322261897169354773) -------+----+--------------+
| Member      | Host        | Role    | State   | TL | Lag in MB    |
+-------------+-------------+---------+---------+----+--------------+
| pg-test-1 * | 10.10.10.11 | Leader  | running |  1 |              |
| pg-test-2 * | 10.10.10.12 | Replica | running |  1 |            0 |
+-------------+-------------+---------+---------+----+--------------+

# 重启单个从库实例
pg restart pg-test pg-test-2

# 重启整个集群(滚动重启,先从库后主库)
pg restart pg-test --force

# 仅重启需要重启的实例
pg restart pg-test --pending --force

# 仅重启所有从库
pg restart pg-test --role replica --force

# 定时重启(在维护窗口执行)
pg restart pg-test --scheduled "2024-12-01T03:00"

# 设置重启超时时间为 300 秒
pg restart pg-test --timeout 300 --force

重载配置

使用 reload 子命令可以重载 Patroni 配置,无需重启 PostgreSQL。该命令会让 Patroni 重新读取配置文件,并将不需要重启的参数变更应用到 PostgreSQL(通过 pg_reload_conf())。相比 restartreload 更加轻量,不会中断数据库连接和正在执行的查询。

pg reload <cls>                       # 重载整个集群的配置
pg reload <cls> <member>              # 重载指定实例的配置
pg reload <cls> --role leader         # 仅重载主库
pg reload <cls> --role replica        # 仅重载所有从库
pg reload <cls> --force               # 跳过确认提示

大多数 PostgreSQL 参数可以通过 reload 生效,只有少数参数(位于 postmaster 上下文的参数,例如 shared_buffersmax_connectionsshared_preload_librariesarchive_mode 等)需要重启 PostgreSQL 才能生效。

# 重载整个集群
pg reload pg-test

# 重载单个实例
pg reload pg-test pg-test-1

# 强制重载,跳过确认
pg reload pg-test --force

重做从库

使用 reinit 子命令可以重新初始化从库。该操作会删除从库上的所有数据,然后从主库重新执行 pg_basebackup 进行完整的数据复制。适用于从库数据损坏无法修复、从库落后太多导致 WAL 已被清理无法追赶、或从库配置错误需要重置等场景。

pg reinit <cls> <member>              # 重新初始化指定从库
pg reinit <cls> <member> --force      # 跳过确认提示
pg reinit <cls> <member> --wait       # 等待重建完成后再返回

⚠️ 警告:此操作会删除目标实例的所有数据!只能对从库执行,不能对主库执行。

# 重新初始化从库(会提示确认)
$ pg reinit pg-test pg-test-2
Are you sure you want to reinitialize members pg-test-2? [y/N]: y
Success: reinitialize for member pg-test-2

# 强制重新初始化,跳过确认
pg reinit pg-test pg-test-2 --force

# 重新初始化并等待完成
pg reinit pg-test pg-test-2 --force --wait

重建过程中,可以使用 pg list 查看进度。从库状态会显示为 creating replica

+ Cluster: pg-test (7322261897169354773) --------------+----+------+
| Member    | Host        | Role    | State            | TL | Lag  |
+-----------+-------------+---------+------------------+----+------+
| pg-test-1 | 10.10.10.11 | Leader  | running          |  2 |      |
| pg-test-2 | 10.10.10.12 | Replica | creating replica |    |    ? |
+-----------+-------------+---------+------------------+----+------+

暂停自动切换

使用 pause 子命令可以暂停 Patroni 的自动故障转移功能。暂停后,即使主库故障,Patroni 也不会自动提升从库为新主库。适用于计划内维护窗口(避免维护操作误触发切换)、调试问题时防止集群状态变化、或需要手动控制切换时机等场景。

pg pause <cls>                        # 暂停自动故障转移
pg pause <cls> --wait                 # 暂停并等待所有成员确认

⚠️ 警告:暂停期间如果主库故障,集群将不会自动恢复!请确保在维护完成后及时使用 resume 恢复。

# 暂停自动切换
$ pg pause pg-test
Success: cluster management is paused

# 查看集群状态(底部会显示 Maintenance mode: on)
$ pg list pg-test
+ Cluster: pg-test (7322261897169354773) -----+----+--------------+
| Member    | Host        | Role    | State   | TL | Lag in MB    |
+-----------+-------------+---------+---------+----+--------------+
| pg-test-1 | 10.10.10.11 | Leader  | running |  1 |              |
| pg-test-2 | 10.10.10.12 | Replica | running |  1 |            0 |
+-----------+-------------+---------+---------+----+--------------+
 Maintenance mode: on

恢复自动切换

使用 resume 子命令可以恢复 Patroni 的自动故障转移功能。维护完成后应立即执行此命令,以确保集群在主库故障时能够自动恢复。

pg resume <cls>                       # 恢复自动故障转移
pg resume <cls> --wait                # 恢复并等待所有成员确认
# 恢复自动切换
$ pg resume pg-test
Success: cluster management is resumed

# 确认已恢复(Maintenance mode 提示消失)
$ pg list pg-test

查看历史

使用 history 子命令可以查看集群的故障转移历史记录。每次主从切换(无论是自动故障转移还是手动切换)都会生成一条新的时间线记录。

pg history <cls>                      # 显示故障转移历史
pg history <cls> -f json              # 以 JSON 格式输出
pg history <cls> -f yaml              # 以 YAML 格式输出
$ pg history pg-test
+----+-----------+------------------------------+---------------------------+
| TL |       LSN | Reason                       | Timestamp                 |
+----+-----------+------------------------------+---------------------------+
|  1 | 0/5000060 | no recovery target specified | 2024-01-15T10:30:00+08:00 |
|  2 | 0/6000000 | switchover to pg-test-2      | 2024-01-20T14:00:00+08:00 |
|  3 | 0/7000028 | failover to pg-test-1        | 2024-01-25T09:15:00+08:00 |
+----+-----------+------------------------------+---------------------------+

输出列说明:TL 是时间线编号(Timeline),每次切换后递增,用于区分不同的主库历史;LSN 是切换时的日志序列号(Log Sequence Number),标识切换发生时的 WAL 位置;Reason 是切换原因,可能是 switchover to xxx(手动切换)、failover to xxx(故障转移)或 no recovery target specified(初始化);Timestamp 是切换发生的时间戳。


显示配置

使用 show-config 子命令可以查看集群当前存储在 DCS 中的配置。这是一个只读操作,如需修改配置请使用 edit-config 命令。

pg show-config <cls>                  # 显示集群配置
$ pg show-config pg-test
loop_wait: 10
maximum_lag_on_failover: 1048576
postgresql:
  parameters:
    archive_command: pgbackrest --stanza=pg-test archive-push %p
    max_connections: 100
    shared_buffers: 256MB
    log_min_duration_statement: 1000
  use_pg_rewind: true
  use_slots: true
retry_timeout: 10
ttl: 30
synchronous_mode: false

执行查询

使用 query 子命令可以在集群成员上快速执行 SQL 查询。这是一个方便的调试工具,适合快速检查集群状态或执行简单查询。生产环境中的复杂查询建议使用 psql 或应用程序连接。

pg query <cls> -c "<sql>"             # 在主库上执行查询
pg query <cls> -c "<sql>" -m <member> # 在指定实例上执行(--member)
pg query <cls> -c "<sql>" -r leader   # 在主库上执行(--role)
pg query <cls> -c "<sql>" -r replica  # 在所有从库上执行
pg query <cls> -f <file>              # 从文件读取 SQL 执行
pg query <cls> -c "<sql>" -U <user>   # 指定用户名(--username)
pg query <cls> -c "<sql>" -d <db>     # 指定数据库(--dbname)
pg query <cls> -c "<sql>" --format json  # 以 JSON 格式输出
# 查看主库当前连接数
pg query pg-test -c "SELECT count(*) FROM pg_stat_activity"

# 查看 PostgreSQL 版本
pg query pg-test -c "SELECT version()"

# 在所有从库上查看复制状态
pg query pg-test -c "SELECT pg_is_in_recovery(), pg_last_wal_replay_lsn()" -r replica

# 在指定实例上执行
pg query pg-test -c "SELECT pg_is_in_recovery()" -m pg-test-2

# 使用指定用户和数据库
pg query pg-test -c "SELECT current_user, current_database()" -U postgres -d postgres

# 以 JSON 格式输出结果
pg query pg-test -c "SELECT * FROM pg_stat_replication" --format json

查看拓扑

使用 topology 子命令可以以树形结构查看集群的复制拓扑。与 list 相比,topology 更直观地展示了主从复制关系,特别适合级联复制(Cascading Replication)场景。

pg topology <cls>                     # 显示复制拓扑
$ pg topology pg-test
+ Cluster: pg-test (7322261897169354773) -------+----+--------------+
| Member      | Host        | Role    | State   | TL | Lag in MB    |
+-------------+-------------+---------+---------+----+--------------+
| pg-test-1   | 10.10.10.11 | Leader  | running |  1 |              |
| + pg-test-2 | 10.10.10.12 | Replica | running |  1 |            0 |
| + pg-test-3 | 10.10.10.13 | Replica | running |  1 |            0 |
+-------------+-------------+---------+---------+----+--------------+

在级联复制场景中,拓扑图会清晰展示复制链路层级,例如 pg-test-3pg-test-2 复制,而 pg-test-2 从主库 pg-test-1 复制。


查看版本

使用 version 子命令可以查看 patronictl 的版本信息。

pg version                            # 显示 patronictl 版本
$ pg version
patronictl version 4.1.0

移除成员

使用 remove 子命令可以从 DCS(分布式配置存储)中移除集群或成员的元数据。这是一个危险操作,仅移除 DCS 中的元数据,不会停止 PostgreSQL 服务或删除数据文件。错误使用可能导致集群状态不一致。

pg remove <cls>                       # 从 DCS 中移除整个集群的元数据

通常情况下您不需要使用此命令。如需正确移除集群或实例,请使用 Pigsty 提供的 bin/pgsql-rm 脚本或 pgsql-rm.yml 剧本。 只有在以下特殊情况下才考虑使用 remove:DCS 中存在孤立的元数据需要清理(例如节点已物理移除但元数据残留),或集群已通过其他方式销毁需要清理残留信息。

# 移除整个集群的元数据(需要多次确认)
$ pg remove pg-test
Please confirm the cluster name to remove: pg-test
You are about to remove all information in DCS for pg-test, please type: "Yes I am aware": Yes I am aware

6.5 - Pgbouncer 连接池管理

使用 Pgbouncer 管理连接池,包括暂停、恢复、禁用、启用、重连、终止、重载等操作。

概览

Pigsty 使用 Pgbouncer 作为 PostgreSQL 的连接池中间件,默认监听 6432 端口,代理访问本机 5432 端口上的 PostgreSQL 实例。

这是一个 可选组件,如果您并没有海量链接,也不需要事务池化与查询监控指标,可以关闭连接池,直连数据库,或者保留但不使用。


用户与数据库管理

Pgbouncer 的中用户和数据库由 Pigsty 自动管理,并在 创建数据库创建用户 时自动应用 数据库配置用户配置

数据库管理:在 pg_databases 中定义的数据库,默认会自动添加到 Pgbouncer。设置 pgbouncer: false 可以排除特定数据库。

pg_databases:
  - name: mydb                # 默认加入连接池
    pool_mode: transaction    # 数据库级池化模式
    pool_size: 64             # 默认池大小
  - name: internal
    pgbouncer: false          # 不加入连接池

用户管理:在 pg_users 中定义的用户,需要显式设置 pgbouncer: true 才会加入连接池用户列表。

pg_users:
  - name: dbuser_app
    password: DBUser.App
    pgbouncer: true           # 加入连接池用户列表
    pool_mode: transaction    # 用户级池化模式

服务管理

在 Pigsty 中,PostgreSQL 集群的 Primary 服务 与 Replica 服务默认指向 Pgbouncer 6432 端口, 如果您想要让这两个服务绕过连接池直接访问 PostgreSQL 实例,可以定制 pg_services,或将将 pg_default_service_dest 设置为 postgres


配置管理

Pgbouncer 的配置文件位于 /etc/pgbouncer/ 目录,由 Pigsty 统一生成与管理:

文件说明
pgbouncer.ini主配置文件,连接池级别参数
database.txt数据库列表,数据库级别参数
userlist.txt用户密码列表
useropts.txt用户级别的连接池参数
pgb_hba.confHBA 访问控制规则

Pigsty 会自动管理 database.txtuserlist.txt,在 创建数据库创建用户 时自动更新这些文件。

您也可以手动编辑配置文件后执行 RELOAD 使其生效:

# 编辑配置
$ vim /etc/pgbouncer/pgbouncer.ini

# 重载生效:通过 systemctl
$ sudo systemctl reload pgbouncer

# 重载生效,本身是 pg_dbsu / postgres 用户
$ pgb -c "RELOAD;"

连接池管理

Pgbouncer 使用和 PostgreSQL 相同的 dbsu 运行,默认为 postgres 操作系统用户。Pigsty 提供了快捷命令 pgb 来简化管理操作:

alias pgb="psql -p 6432 -d pgbouncer -U postgres"

您可以在数据库节点上使用 pgb 命令连接到 Pgbouncer 管理控制台,执行管理命令和监控查询。

$ pgb
pgbouncer=# SHOW POOLS;
pgbouncer=# SHOW CLIENTS;
pgbouncer=# SHOW SERVERS;
命令功能说明
PAUSE暂停暂停数据库连接,等待事务完成后断开服务端连接
RESUME恢复恢复被 PAUSE/KILL/SUSPEND 暂停的数据库
DISABLE禁用拒绝指定数据库的新客户端连接
ENABLE启用允许指定数据库的新客户端连接
RECONNECT重连优雅地关闭并重建服务端连接
KILL终止立即断开指定数据库的所有客户端和服务端连接
KILL_CLIENT杀客户端终止指定的客户端连接
SUSPEND挂起刷新缓冲区并停止监听,用于在线重启
SHUTDOWN关闭关闭 Pgbouncer 进程
RELOAD重载重新加载配置文件
WAIT_CLOSE等待关闭等待 RECONNECT/RELOAD 后的服务端连接释放
监控命令监控查看连接池状态、客户端、服务端等信息

PAUSE

使用 PAUSE 命令暂停数据库连接。Pgbouncer 会根据池化模式等待活动事务/会话完成后断开服务端连接。新的客户端请求会被阻塞直到执行 RESUME

PAUSE [db];           -- 暂停指定数据库,不指定则暂停所有数据库

典型使用场景:

  • 在线切换后端数据库(如主从切换后更新连接目标)
  • 执行需要断开所有连接的维护操作
  • 配合 SUSPEND 实现 Pgbouncer 在线重启
$ pgb -c "PAUSE mydb;"        # 暂停 mydb 数据库
$ pgb -c "PAUSE;"             # 暂停所有数据库

暂停后,SHOW DATABASES 会显示 paused 状态:

pgbouncer=# SHOW DATABASES;
   name   |   host    | port | database | ... | paused | disabled
----------+-----------+------+----------+-----+--------+----------
 mydb     | /var/run  | 5432 | mydb     | ... |      1 |        0

RESUME

使用 RESUME 命令恢复被 PAUSEKILLSUSPEND 暂停的数据库,允许新的连接请求并恢复正常服务。

RESUME [db];          -- 恢复指定数据库,不指定则恢复所有数据库
$ pgb -c "RESUME mydb;"       # 恢复 mydb 数据库
$ pgb -c "RESUME;"            # 恢复所有数据库

DISABLE

使用 DISABLE 命令禁用指定数据库,拒绝所有新的客户端连接请求。已存在的连接不受影响。

DISABLE db;           -- 禁用指定数据库(必须指定数据库名)

典型使用场景:

  • 临时下线某个数据库进行维护
  • 阻止新连接以便安全地进行数据库迁移
  • 逐步下线即将删除的数据库
$ pgb -c "DISABLE mydb;"      # 禁用 mydb,新连接被拒绝

ENABLE

使用 ENABLE 命令启用之前被 DISABLE 禁用的数据库,重新接受新的客户端连接。

ENABLE db;            -- 启用指定数据库(必须指定数据库名)
$ pgb -c "ENABLE mydb;"       # 启用 mydb,允许新连接

RECONNECT

使用 RECONNECT 命令优雅地重建服务端连接。Pgbouncer 会在连接释放回池后关闭它们,并在需要时建立新连接。

RECONNECT [db];       -- 重建指定数据库的服务端连接,不指定则重建所有

典型使用场景:

  • 后端数据库 IP 地址变更后刷新连接
  • 主从切换后重新路由流量
  • DNS 更新后重建连接
$ pgb -c "RECONNECT mydb;"    # 重建 mydb 的服务端连接
$ pgb -c "RECONNECT;"         # 重建所有服务端连接

执行 RECONNECT 后,可以使用 WAIT_CLOSE 等待旧连接完全释放。


KILL

使用 KILL 命令立即断开指定数据库的所有客户端和服务端连接。与 PAUSE 不同,KILL 不等待事务完成,直接强制断开。

KILL [db];            -- 终止指定数据库的所有连接,不指定则终止所有(admin 除外)
$ pgb -c "KILL mydb;"         # 强制断开 mydb 的所有连接
$ pgb -c "KILL;"              # 强制断开所有数据库的连接(admin 除外)

执行 KILL 后,新连接会被阻塞直到执行 RESUME


KILL_CLIENT

使用 KILL_CLIENT 命令终止指定的客户端连接。客户端 ID 可以从 SHOW CLIENTS 输出中获取。

KILL_CLIENT id;       -- 终止指定 ID 的客户端连接
# 查看客户端连接
$ pgb -c "SHOW CLIENTS;"

# 终止特定客户端(假设 ptr 列显示的 ID 为 0x1234567890)
$ pgb -c "KILL_CLIENT 0x1234567890;"

SUSPEND

使用 SUSPEND 命令挂起 Pgbouncer。Pgbouncer 会刷新所有 socket 缓冲区并停止监听数据,直到执行 RESUME

SUSPEND;              -- 挂起 Pgbouncer

SUSPEND 主要用于实现 Pgbouncer 的在线重启(零停机升级):

# 1. 挂起当前 Pgbouncer
$ pgb -c "SUSPEND;"

# 2. 启动新的 Pgbouncer 进程(使用 -R 选项接管 socket)
$ pgbouncer -R /etc/pgbouncer/pgbouncer.ini

# 3. 新进程接管后,旧进程自动退出

SHUTDOWN

使用 SHUTDOWN 命令关闭 Pgbouncer 进程。支持多种关闭模式:

SHUTDOWN;                      -- 立即关闭
SHUTDOWN WAIT_FOR_SERVERS;     -- 等待服务端连接释放后关闭
SHUTDOWN WAIT_FOR_CLIENTS;     -- 等待客户端断开后关闭(零停机滚动重启)
模式说明
SHUTDOWN立即关闭 Pgbouncer 进程
WAIT_FOR_SERVERS停止接受新连接,等待服务端连接释放后退出
WAIT_FOR_CLIENTS停止接受新连接,等待所有客户端断开后退出,适用于滚动重启
$ pgb -c "SHUTDOWN WAIT_FOR_CLIENTS;"   # 优雅关闭,等待客户端断开

RELOAD

使用 RELOAD 命令重新加载 Pgbouncer 配置文件。可以动态更新大部分配置参数,无需重启进程。

RELOAD;               -- 重载配置文件
$ pgb -c "RELOAD;"              # 通过管理控制台重载
$ systemctl reload pgbouncer    # 通过 systemd 重载
$ kill -SIGHUP $(cat /var/run/pgbouncer/pgbouncer.pid)  # 通过信号重载

Pigsty 提供了重载 Pgbouncer 配置的剧本任务:

./pgsql.yml -l <cls> -t pgbouncer_reload    # 重载集群的 Pgbouncer 配置

WAIT_CLOSE

使用 WAIT_CLOSE 命令等待服务端连接完成关闭。通常在 RECONNECTRELOAD 后使用,确保旧连接已全部释放。

WAIT_CLOSE [db];      -- 等待指定数据库的服务端连接关闭,不指定则等待所有
# 完整的连接重建流程
$ pgb -c "RECONNECT mydb;"
$ pgb -c "WAIT_CLOSE mydb;"    # 等待旧连接释放

监控命令

Pgbouncer 提供了丰富的 SHOW 命令用于监控连接池状态:

命令说明
SHOW HELP显示可用命令帮助
SHOW DATABASES显示数据库配置和状态
SHOW POOLS显示连接池统计信息
SHOW CLIENTS显示客户端连接列表
SHOW SERVERS显示服务端连接列表
SHOW USERS显示用户配置
SHOW STATS显示统计信息(请求数、字节数等)
SHOW STATS_TOTALS显示累计统计信息
SHOW STATS_AVERAGES显示平均统计信息
SHOW CONFIG显示当前配置参数
SHOW MEM显示内存使用情况
SHOW DNS_HOSTS显示 DNS 缓存的主机名
SHOW DNS_ZONES显示 DNS 缓存的区域
SHOW SOCKETS显示打开的 socket 信息
SHOW ACTIVE_SOCKETS显示活动的 socket
SHOW LISTS显示内部列表计数
SHOW FDS显示文件描述符使用情况
SHOW STATE显示 Pgbouncer 运行状态
SHOW VERSION显示 Pgbouncer 版本

常用监控示例:

# 查看连接池状态
$ pgb -c "SHOW POOLS;"

# 查看客户端连接
$ pgb -c "SHOW CLIENTS;"

# 查看服务端连接
$ pgb -c "SHOW SERVERS;"

# 查看统计信息
$ pgb -c "SHOW STATS;"

# 查看数据库状态
$ pgb -c "SHOW DATABASES;"

更多监控命令的详细说明,请参考 Pgbouncer 官方文档


Unix 信号

Pgbouncer 支持通过 Unix 信号进行控制,这在无法连接管理控制台时非常有用:

信号等效命令说明
SIGHUPRELOAD重载配置文件
SIGTERMSHUTDOWN WAIT_FOR_CLIENTS优雅关闭,等待客户端断开
SIGINTSHUTDOWN WAIT_FOR_SERVERS优雅关闭,等待服务端释放
SIGQUITSHUTDOWN立即关闭
SIGUSR1PAUSE暂停所有数据库
SIGUSR2RESUME恢复所有数据库
# 通过信号重载配置
$ kill -SIGHUP $(cat /var/run/pgbouncer/pgbouncer.pid)

# 通过信号优雅关闭
$ kill -SIGTERM $(cat /var/run/pgbouncer/pgbouncer.pid)

# 通过信号暂停
$ kill -SIGUSR1 $(cat /var/run/pgbouncer/pgbouncer.pid)

# 通过信号恢复
$ kill -SIGUSR2 $(cat /var/run/pgbouncer/pgbouncer.pid)

流量切换

Pigsty 提供了 pgb-route 实用函数,可以将 Pgbouncer 流量快速切换至其他节点,用于零停机迁移:

# 定义(已在 /etc/profile.d/pg-alias.sh 中)
function pgb-route(){
  local ip=${1-'\/var\/run\/postgresql'}
  sed -ie "s/host=[^[:space:]]\+/host=${ip}/g" /etc/pgbouncer/pgbouncer.ini
  cat /etc/pgbouncer/pgbouncer.ini
}

# 使用:将流量路由到 10.10.10.12
$ pgb-route 10.10.10.12
$ pgb -c "RECONNECT; WAIT_CLOSE;"

完整的零停机切换流程:

# 1. 修改路由目标
$ pgb-route 10.10.10.12

# 2. 重载配置
$ pgb -c "RELOAD;"

# 3. 重建连接并等待旧连接释放
$ pgb -c "RECONNECT;"
$ pgb -c "WAIT_CLOSE;"

6.6 - 管理 PostgreSQL 组件服务

使用 systemctl 管理 PostgreSQL 集群中的各个组件服务:启动、停止、重启、重载与状态检查。

概述

Pigsty 的 PGSQL 模块由多个组件构成,每个组件都以 systemd 服务的形式运行在节点上。( pgbackrest 除外)

了解这些组件及其管理方式,对于维护生产环境中的 PostgreSQL 集群非常重要。

组件端口服务名说明
Patroni8008patroni高可用管理器,负责 PostgreSQL 的生命周期管理
PostgreSQL5432postgres占位服务,默认不使用,应急使用
Pgbouncer6432pgbouncer连接池中间件,业务流量入口
PgBackRest--pgBackRest 没有守护服务
HAProxy543xhaproxy负载均衡器,暴露数据库服务
pg_exporter9630pg_exporterPostgreSQL 监控指标导出器
pgbouncer_exporter9631pgbouncer_exporterPgbouncer 监控指标导出器
vip-manager-vip-manager可选,管理 L2 VIP 地址漂移

命令速查

操作命令
启动服务systemctl start <service>
停止服务systemctl stop <service>
重启服务systemctl restart <service>
重载配置systemctl reload <service>
查看状态systemctl status <service>
查看日志journalctl -u <service> -f
开机启动systemctl enable <service>
禁用启动systemctl disable <service>

常用组件服务名:patronipgbouncerhaproxypg_exporterpgbouncer_exportervip-manager


Patroni

Patroni 是 PostgreSQL 的高可用管理器,负责 PostgreSQL 的启动、停止、故障检测与自动故障转移。 它是 PGSQL 模块的核心组件,PostgreSQL 进程由 Patroni 托管,不应直接通过 systemctl 管理 postgres 服务。

启动 Patroni

systemctl start patroni     # 启动 Patroni(同时启动 PostgreSQL)

启动 Patroni 后,它会自动拉起 PostgreSQL 进程。首次启动时,Patroni 会根据角色决定行为:

  • 主库:初始化或恢复数据目录
  • 从库:从主库克隆数据并建立复制

停止 Patroni

systemctl stop patroni      # 停止 Patroni(同时停止 PostgreSQL)

停止 Patroni 时,它会优雅地关闭 PostgreSQL 进程。注意:如果这是主库,且未暂停自动切换,可能触发故障转移。

重启 Patroni

systemctl restart patroni   # 重启 Patroni(同时重启 PostgreSQL)

重启会导致短暂的服务中断。对于生产环境,建议使用 pg restart 命令进行滚动重启。

重载 Patroni

systemctl reload patroni    # 重载 Patroni 配置

重载会让 Patroni 重新读取配置文件,并将可热加载的参数应用到 PostgreSQL。

查看状态与日志

systemctl status patroni    # 查看 Patroni 服务状态
journalctl -u patroni -f    # 实时查看 Patroni 日志
journalctl -u patroni -n 100 --no-pager  # 查看最近 100 行日志

配置文件位置/etc/patroni/patroni.yml

最佳实践:使用 patronictl 而非 systemctl 管理 PostgreSQL 集群。


Pgbouncer

Pgbouncer 是轻量级的 PostgreSQL 连接池中间件。 业务流量通常通过 Pgbouncer(6432 端口)而非直接连接 PostgreSQL(5432 端口),以实现连接复用和保护数据库。

启动 Pgbouncer

systemctl start pgbouncer

停止 Pgbouncer

systemctl stop pgbouncer

注意:停止 Pgbouncer 会中断所有通过连接池的业务连接。

重启 Pgbouncer

systemctl restart pgbouncer

重启会断开所有现有连接。如果只是配置变更,建议使用 reload

重载 Pgbouncer

systemctl reload pgbouncer

重载会重新读取配置文件(用户列表、连接池参数等),不会断开现有连接。

查看状态与日志

systemctl status pgbouncer
journalctl -u pgbouncer -f

配置文件位置

  • 主配置:/etc/pgbouncer/pgbouncer.ini
  • HBA 规则:/etc/pgbouncer/pgb_hba.conf
  • 用户列表:/etc/pgbouncer/userlist.txt
  • 数据库列表:/etc/pgbouncer/database.txt

管理控制台

psql -p 6432 -U postgres -d pgbouncer  # 连接到 Pgbouncer 管理控制台

常用管理命令:

SHOW POOLS;      -- 查看连接池状态
SHOW CLIENTS;    -- 查看客户端连接
SHOW SERVERS;    -- 查看后端服务器连接
SHOW STATS;      -- 查看统计信息
RELOAD;          -- 重载配置
PAUSE;           -- 暂停所有连接池
RESUME;          -- 恢复所有连接池

HAProxy

HAProxy 是高性能的负载均衡器,负责将流量分发到正确的 PostgreSQL 实例。 Pigsty 使用 HAProxy 暴露 服务,根据角色(主库/从库)和健康状态进行流量调度。

启动 HAProxy

systemctl start haproxy

停止 HAProxy

systemctl stop haproxy

注意:停止 HAProxy 会中断所有通过负载均衡器的连接。

重启 HAProxy

systemctl restart haproxy

重载 HAProxy

systemctl reload haproxy

HAProxy 支持优雅重载,不会断开现有连接。配置变更后推荐使用 reload

查看状态与日志

systemctl status haproxy
journalctl -u haproxy -f

配置文件位置/etc/haproxy/haproxy.cfg

管理界面

HAProxy 提供 Web 管理界面,默认监听在 9101 端口:

http://<node_ip>:9101/haproxy

默认认证:用户名 admin,密码由 haproxy_admin_password 配置。


pg_exporter

pg_exporter 是 PostgreSQL 的 Prometheus 监控指标导出器,负责采集数据库性能指标。

启动 pg_exporter

systemctl start pg_exporter

停止 pg_exporter

systemctl stop pg_exporter

停止后,Prometheus 将无法采集该实例的 PostgreSQL 监控指标。

重启 pg_exporter

systemctl restart pg_exporter

查看状态与日志

systemctl status pg_exporter
journalctl -u pg_exporter -f

配置文件位置/etc/pg_exporter.yml

验证指标采集

curl -s localhost:9630/metrics | head -20

pgbouncer_exporter

pgbouncer_exporter 是 Pgbouncer 的 Prometheus 监控指标导出器。

启动/停止/重启

systemctl start pgbouncer_exporter
systemctl stop pgbouncer_exporter
systemctl restart pgbouncer_exporter

查看状态与日志

systemctl status pgbouncer_exporter
journalctl -u pgbouncer_exporter -f

验证指标采集

curl -s localhost:9631/metrics | head -20

vip-manager

vip-manager 是可选组件,用于管理 L2 VIP 地址漂移。 当启用 pg_vip_enabled 时,vip-manager 会将 VIP 绑定到当前主库节点。

启动 vip-manager

systemctl start vip-manager

停止 vip-manager

systemctl stop vip-manager

停止后,VIP 地址会从当前节点释放。

重启 vip-manager

systemctl restart vip-manager

查看状态与日志

systemctl status vip-manager
journalctl -u vip-manager -f

配置文件位置/etc/default/vip-manager

验证 VIP 绑定

ip addr show           # 查看网络接口,检查 VIP 是否绑定
pg list <cls>          # 确认主库位置

启动顺序与依赖

PGSQL 模块组件的推荐启动顺序:

1. patroni          # 首先启动 Patroni(会自动启动 PostgreSQL)
2. pgbouncer        # 然后启动连接池
3. haproxy          # 启动负载均衡器
4. pg_exporter      # 启动监控导出器
5. pgbouncer_exporter
6. vip-manager      # 最后启动 VIP 管理器(如果启用)

停止顺序应相反。Pigsty 剧本会自动处理这些依赖关系。

批量启动所有服务

systemctl start patroni pgbouncer haproxy pg_exporter pgbouncer_exporter

批量停止所有服务

systemctl stop pgbouncer_exporter pg_exporter haproxy pgbouncer patroni

常见故障排查

服务启动失败

systemctl status <service>        # 查看服务状态
journalctl -u <service> -n 50     # 查看最近日志
journalctl -u <service> --since "5 min ago"  # 查看最近 5 分钟日志

Patroni 无法启动

现象可能原因解决方案
无法连接 etcdetcd 集群不可用检查 etcd 服务状态
数据目录权限错误文件所有权不是 postgreschown -R postgres:postgres /pg/data
端口被占用PostgreSQL 残留进程pg_ctl stop -D /pg/datakill

Pgbouncer 无法启动

现象可能原因解决方案
配置文件语法错误INI 格式错误检查 /etc/pgbouncer/pgbouncer.ini
端口被占用6432 端口已被使用lsof -i :6432
userlist.txt 权限文件权限不正确chmod 600 /etc/pgbouncer/userlist.txt

HAProxy 无法启动

现象可能原因解决方案
配置文件语法错误haproxy.cfg 格式错误haproxy -c -f /etc/haproxy/haproxy.cfg
端口被占用服务端口冲突lsof -i :5433

相关文档

6.7 - 管理 PostgreSQL 定时任务

配置 Crontab 定期调度 PostgreSQL 备份任务,执行备份 / Vacuum Freeze / Analyze 任务,以及处理表膨胀

Pigsty 使用 crontab 来管理定时任务,用于执行例行备份,冻结老化事务,重整膨胀表索引等维护工作。

速查手册

操作快捷命令说明
配置定时任务./pgsql.yml -t pg_crontab -l <cls>应用 pg_crontab 配置
查看定时任务crontab -l以 postgres 用户查看
物理备份pg-backup [full|diff|incr]使用 pgBackRest 执行备份
事务冻结pg-vacuum [database...]冻结老化事务,预防 XID 回卷
膨胀治理pg-repack [database...]在线重整膨胀的表与索引

其他管理任务,请参考:备份管理监控系统高可用管理


配置定时任务

使用 pg_crontab 参数配置 PostgreSQL 数据库超级用户(pg_dbsu,默认 postgres)的定时任务。

下面 pg-meta 集群配置了每天凌晨1点进行全量备份的定时任务,pg-test 配置了每周一全量备份,其余日期增量备份的定时任务。

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_crontab:
      - '00 01 * * * /pg/bin/pg-backup'
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
    pg_crontab:
      - '00 01 * * 1            /pg/bin/pg-backup full'
      - '00 01 * * 2,3,4,5,6,7  /pg/bin/pg-backup'

推荐的维护计划

pg_crontab:
  - '00 01 * * * /pg/bin/pg-backup full'    # 每天凌晨1点全量备份
  - '00 03 * * 0 /pg/bin/pg-vacuum'         # 每周日凌晨3点执行 vacuum freeze
  - '00 04 * * 1 /pg/bin/pg-repack'         # 每周一凌晨4点执行 repack
任务频率时机说明
pg-backup每天凌晨全量或增量备份,视业务需求而定
pg-vacuum每周一次周日凌晨冻结老化事务,预防 XID 回卷
pg-repack每周/每月业务低峰期重整膨胀表索引,回收空间

应用定时任务

定时任务会在 pgsql.yml 剧本执行时(pg_crontab 任务)自动写入对应操作系统发行版的默认位置:

  • EL(RHEL/Rocky/Alma):/var/spool/cron/postgres
  • Debian/Ubuntu:/var/spool/cron/crontabs/postgres
./pgsql.yml -l pg-meta -t pg_crontab     # 应用 pg_crontab 配置到指定集群
./pgsql.yml -l 10.10.10.10 -t pg_crontab # 仅针对特定主机
# 以 postgres 用户编辑定时任务
sudo -u postgres crontab -e

# 或直接编辑 crontab 文件
sudo vi /var/spool/cron/postgres           # EL 系列
sudo vi /var/spool/cron/crontabs/postgres  # Debian/Ubuntu

每次执行剧本都会 全量覆盖刷新 定时任务配置。


查看定时任务

使用 pg_dbsu 操作系统用户执行以下命令查看定时任务:

crontab -l

# Pigsty Managed Crontab for postgres
SHELL=/bin/bash
PATH=/usr/pgsql/bin:/pg/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin
MAILTO=""
00 01 * * * /pg/bin/pg-backup

如果您不熟悉 Crontab 的语法,可以参考 Crontab Guru 的解释。


pg-backup

pg-backup 是 Pigsty 提供的物理备份脚本,基于 pgBackRest 实现,支持全量、差异、增量三种备份模式。

基本用法

pg-backup                # 执行增量备份(默认),如果没有全量备份则自动执行全量备份
pg-backup full           # 执行全量备份
pg-backup diff           # 执行差异备份(基于最近的全量备份)
pg-backup incr           # 执行增量备份(基于最近的任意备份)

备份类型说明

类型参数说明
全量备份full完整备份所有数据,恢复时只需要该备份
差异备份diff备份自上次全量备份以来的变更,恢复时需要全量+差异
增量备份incr备份自上次任意备份以来的变更,恢复时需要完整链路

执行条件

  • 脚本必须在 主库 上以 postgres 用户身份运行
  • 脚本会自动检测当前节点角色,从库执行时会直接退出(exit 1)
  • /etc/pgbackrest/pgbackrest.conf 中自动获取 stanza 名称

常用定时任务配置

pg_crontab:
  - '00 01 * * * /pg/bin/pg-backup full'    # 每天凌晨1点全量备份
pg_crontab:
  - '00 01 * * 1            /pg/bin/pg-backup full'  # 周一全量备份
  - '00 01 * * 2,3,4,5,6,7  /pg/bin/pg-backup'       # 其他日期增量备份
pg_crontab:
  - '00 01 * * 1            /pg/bin/pg-backup full'  # 周一全量备份
  - '00 01 * * 2,3,4,5,6,7  /pg/bin/pg-backup diff'  # 其他日期差异备份

更多备份恢复操作,请参考 备份管理 章节。


pg-vacuum

pg-vacuum 是 Pigsty 提供的事务冻结脚本,用于执行 VACUUM FREEZE 操作,防止事务ID(XID)回卷导致数据库停机。

基本用法

pg-vacuum                    # 冻结所有数据库中的老化表
pg-vacuum mydb               # 仅处理指定数据库
pg-vacuum -n mydb            # 空跑模式,只显示不执行
pg-vacuum -a 80000000 mydb   # 使用自定义年龄阈值(默认1亿)
pg-vacuum -r 50 mydb         # 使用自定义老化比例阈值(默认40%)
-- 对整个数据库执行 VACUUM FREEZE
VACUUM FREEZE;

-- 对特定表执行 VACUUM FREEZE
VACUUM FREEZE schema.table_name;

命令选项

选项说明默认值
-h, --help显示帮助信息-
-n, --dry-run空跑模式,只显示不执行false
-a, --age年龄阈值,超过此值的表需要冻结100000000
-r, --ratio老化比例阈值,超过则全库冻结(%)40

工作逻辑

  1. 检查数据库的 datfrozenxid 年龄,如果低于阈值则跳过该库
  2. 计算老化页面比例(超过年龄阈值的表页面占总页面的百分比)
  3. 如果老化比例 > 40%,执行全库 VACUUM FREEZE ANALYZE
  4. 否则,仅对超过年龄阈值的表执行 VACUUM FREEZE ANALYZE

脚本会设置 vacuum_cost_limit = 10000vacuum_cost_delay = 1ms 以控制 I/O 影响。

执行条件

  • 脚本必须在 主库 上以 pg_dbsu postgres 用户身份运行
  • 使用文件锁 /tmp/pg-vacuum.lock 防止并发执行
  • 自动跳过 template0template1postgres 系统数据库

常用定时任务配置

建议将 vacuum 任务与备份/Repack 任务分开执行,避免冲突。

pg_crontab:
  - '00 03 * * 0 /pg/bin/pg-vacuum'     # 每周日凌晨3点执行

pg-repack

pg-repack 是 Pigsty 提供的膨胀治理脚本,基于 pg_repack 扩展实现,用于在线重整膨胀的表与索引。

基本用法

pg-repack                    # 重整所有数据库中的膨胀表与索引
pg-repack mydb               # 仅重整指定数据库
pg-repack mydb1 mydb2        # 重整多个数据库
pg-repack -n mydb            # 空跑模式,只显示不执行
pg-repack -t mydb            # 仅重整表
pg-repack -i mydb            # 仅重整索引
pg-repack -T 30 -j 4 mydb    # 自定义锁超时(秒)和并行度
# 直接使用 pg_repack 命令重整特定表
pg_repack dbname -t schema.table

# 直接使用 pg_repack 命令重整特定索引
pg_repack dbname -i schema.index

命令选项

选项说明默认值
-h, --help显示帮助信息-
-n, --dry-run空跑模式,只显示不执行false
-t, --table仅重整表false
-i, --index仅重整索引false
-T, --timeout锁等待超时时间(秒)10
-j, --jobs并行作业数2

自动选择阈值

脚本会根据表和索引的大小与膨胀率,自动选择需要重整的对象:

表膨胀阈值

大小范围膨胀率阈值最大数量
< 256MB> 40%64
256MB - 2GB> 30%16
2GB - 8GB> 20%4
8GB - 64GB> 15%1

索引膨胀阈值

大小范围膨胀率阈值最大数量
< 128MB> 40%64
128MB - 1GB> 35%16
1GB - 8GB> 30%4
8GB - 64GB> 20%1

超过 64GB 的巨型表/索引会被跳过并给出提示,需要手动处理。

执行条件

  • 脚本必须在 主库 上以 postgres 用户身份运行
  • 需要安装 pg_repack 扩展(Pigsty 默认安装)
  • 需要 monitor schema 中的 pg_table_bloatpg_index_bloat 视图
  • 使用文件锁 /tmp/pg-repack.lock 防止并发执行
  • 自动跳过 template0template1postgres 系统数据库

常用定时任务配置

pg_crontab:
  - '00 04 * * 1 /pg/bin/pg-repack'     # 每周一凌晨4点执行

您可以通过 Pigsty 的 PGCAT Database - Table Bloat 面板确认数据库中的膨胀情况,并选择膨胀率较高的表与索引进行重整。

更多细节请参考:关系膨胀的治理


移除定时任务

当使用 pgsql-rm.yml 剧本移除 PostgreSQL 集群时,会自动删除 postgres 用户的 crontab 文件。

./pgsql-rm.yml -l <cls> -t pg_crontab    # 仅移除定时任务
./pgsql-rm.yml -l <cls>                  # 移除整个集群(包含定时任务)

相关文档

6.8 - 升级 PostgreSQL 大小版本

版本升级:小版本滚动升级、大版本迁移、扩展升级

快速上手

PostgreSQL 版本升级分为两种类型:小版本升级大版本升级,两者的风险和复杂度差异很大。

类型示例停机时间数据兼容性风险等级
小版本升级17.2 → 17.3秒级(滚动重启)完全兼容
大版本升级17 → 18分钟级需要升级数据目录
# 滚动升级:先从库后主库
ansible <cls> -b -a 'yum upgrade -y postgresql17*'
pg restart --role replica --force <cls>
pg switchover <cls>
pg restart <cls> <old-primary> --force
# 推荐:逻辑复制迁移
bin/pgsql-add pg-new              # 创建新版本集群
# 配置逻辑复制同步数据...
# 切换流量到新集群
ansible <cls> -b -a 'yum upgrade -y postgis36_17*'
psql -c 'ALTER EXTENSION postgis UPDATE;'

关于在线迁移的详细流程,请参考 在线迁移 文档。

操作说明风险
小版本升级更新软件包,滚动重启
小版本降级回退到之前的小版本
大版本升级逻辑复制或 pg_upgrade
扩展升级升级扩展软件包和扩展对象

小版本升级

小版本升级(如 17.2 → 17.3)是最常见的升级场景,通常用于应用安全补丁和 Bug 修复。数据目录完全兼容,通过滚动重启即可完成。

升级策略:推荐采用 滚动升级 方式:先升级从库,再通过主从切换升级原主库,最小化服务中断。

1. 更新软件仓库 → 2. 升级从库软件包 → 3. 重启从库
4. 主从切换 → 5. 升级原主库软件包 → 6. 重启原主库

步骤一:准备软件包

确保本地软件仓库中有最新版本的 PostgreSQL 包,并刷新节点缓存:

cd ~/pigsty
./infra.yml -t repo_upstream      # 添加上游仓库(需要互联网)
./infra.yml -t repo_build         # 重建本地仓库
ansible <cls> -b -a 'yum clean all'
ansible <cls> -b -a 'yum makecache'
ansible <cls> -b -a 'apt clean'
ansible <cls> -b -a 'apt update'

步骤二:升级从库

在所有从库上升级软件包并验证版本:

ansible <cls> -b -a 'yum upgrade -y postgresql17*'
ansible <cls> -b -a '/usr/pgsql/bin/pg_ctl --version'
ansible <cls> -b -a 'apt install -y postgresql-17'
ansible <cls> -b -a '/usr/lib/postgresql/17/bin/pg_ctl --version'

重启所有从库以应用新版本:

pg restart --role replica --force <cls>

步骤三:切换主库

执行主从切换,将主库角色转移到已升级的从库:

pg switchover <cls>
# 或非交互式:
pg switchover --leader <old-primary> --candidate <new-primary> --scheduled=now --force <cls>

步骤四:升级原主库

原主库现在已降级为从库,升级软件包并重启:

ansible <old-primary-ip> -b -a 'yum upgrade -y postgresql17*'
ansible <old-primary-ip> -b -a 'apt install -y postgresql-17'
pg restart <cls> <old-primary-name> --force

步骤五:验证

确认所有实例版本一致:

pg list <cls>
pg query <cls> -c "SELECT version()"

小版本降级

在极少数情况下(如新版本引入 Bug),可能需要将 PostgreSQL 降级到之前的版本。

步骤一:获取旧版本包

cd ~/pigsty; ./infra.yml -t repo_upstream     # 添加上游仓库
cd /www/pigsty; repotrack postgresql17-*-17.1 # 下载指定版本的包
cd ~/pigsty; ./infra.yml -t repo_create       # 重建仓库元数据
ansible <cls> -b -a 'yum clean all'
ansible <cls> -b -a 'yum makecache'

步骤二:执行降级

ansible <cls> -b -a 'yum downgrade -y postgresql17*'
ansible <cls> -b -a 'apt install -y postgresql-17=17.1*'

步骤三:重启集群

pg restart --force <cls>

大版本升级

大版本升级(如 17 → 18)涉及数据格式变更,需要使用专用工具进行数据迁移。

方式停机时间复杂度适用场景
逻辑复制迁移秒级切换生产环境,要求最小停机
pg_upgrade 原地升级分钟~小时测试环境,数据量较小

逻辑复制迁移

逻辑复制迁移是生产环境大版本升级的推荐方式,核心步骤:

1. 创建新版本目标集群 → 2. 配置逻辑复制同步数据 → 3. 验证数据一致性
4. 切换应用流量到新集群 → 5. 下线旧集群

步骤一:创建新版本集群

pg-meta-new:
  hosts:
    10.10.10.12: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-meta-new
    pg_version: 18                    # 新版本
bin/pgsql-add pg-meta-new

步骤二:配置逻辑复制

-- 源集群(旧版本)主库:创建发布
CREATE PUBLICATION upgrade_pub FOR ALL TABLES;

-- 目标集群(新版本)主库:创建订阅
CREATE SUBSCRIPTION upgrade_sub
  CONNECTION 'host=10.10.10.11 port=5432 dbname=mydb user=replicator password=xxx'
  PUBLICATION upgrade_pub;

步骤三:等待同步完成

-- 目标集群:检查订阅状态
SELECT * FROM pg_stat_subscription;

-- 源集群:检查复制槽 LSN
SELECT slot_name, confirmed_flush_lsn FROM pg_replication_slots;

步骤四:切换流量

确认数据同步完成后:停止应用写入源集群 → 等待最后的数据同步 → 切换应用连接到新集群 → 删除订阅,下线源集群。

-- 目标集群:删除订阅
DROP SUBSCRIPTION upgrade_sub;

详细的迁移流程请参考 在线迁移 文档。

pg_upgrade 原地升级

pg_upgrade 是 PostgreSQL 官方提供的大版本升级工具,适用于测试环境或可接受较长停机时间的场景。

步骤一:安装新版本软件包

./pgsql.yml -l <cls> -t pg_pkg -e pg_version=18

步骤二:停止 Patroni

pg pause <cls>                        # 暂停自动故障转移
systemctl stop patroni                # 停止 Patroni(会停止 PostgreSQL)

步骤三:运行 pg_upgrade

sudo su - postgres
mkdir -p /data/postgres/pg-meta-18/data

# 预检(-c 参数只检查不执行)
/usr/pgsql-18/bin/pg_upgrade \
  -b /usr/pgsql-17/bin -B /usr/pgsql-18/bin \
  -d /data/postgres/pg-meta-17/data \
  -D /data/postgres/pg-meta-18/data \
  -v -c

# 执行升级
/usr/pgsql-18/bin/pg_upgrade \
  -b /usr/pgsql-17/bin -B /usr/pgsql-18/bin \
  -d /data/postgres/pg-meta-17/data \
  -D /data/postgres/pg-meta-18/data \
  --link -j 8 -v

步骤四:更新链接并启动

rm -rf /usr/pgsql && ln -s /usr/pgsql-18 /usr/pgsql
rm -rf /pg && ln -s /data/postgres/pg-meta-18 /pg
# 编辑 /etc/patroni/patroni.yml 更新路径
systemctl start patroni
pg resume <cls>

步骤五:后处理

/usr/pgsql-18/bin/vacuumdb --all --analyze-in-stages
./delete_old_cluster.sh   # pg_upgrade 生成的清理脚本

扩展升级

升级 PostgreSQL 版本时,通常也需要升级相关扩展插件。

升级扩展软件包

ansible <cls> -b -a 'yum upgrade -y postgis36_17 timescaledb-2-postgresql-17* pgvector_17*'
ansible <cls> -b -a 'apt install -y postgresql-17-postgis-3 postgresql-17-pgvector'

升级扩展版本

软件包升级后,在数据库中执行扩展升级:

-- 查看可升级的扩展
SELECT name, installed_version, default_version FROM pg_available_extensions
WHERE installed_version IS NOT NULL AND installed_version <> default_version;

-- 升级扩展
ALTER EXTENSION postgis UPDATE;
ALTER EXTENSION timescaledb UPDATE;
ALTER EXTENSION vector UPDATE;

-- 检查扩展版本
SELECT extname, extversion FROM pg_extension;

注意事项

  1. 备份优先:任何升级操作前都应进行完整备份
  2. 测试验证:先在测试环境验证升级流程
  3. 扩展兼容:确认所有扩展支持目标版本
  4. 回滚预案:准备好回滚方案,特别是大版本升级
  5. 监控观察:升级后密切监控数据库性能和错误日志
  6. 文档记录:记录升级过程中的所有操作和问题

相关文档

6.9 - 管理 PostgreSQL 扩展插件

扩展管理:下载、安装、配置、启用、更新、卸载扩展

快速上手

Pigsty 提供 444 扩展,使用扩展涉及四个步骤:下载安装配置启用

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_extensions: [ postgis, timescaledb, pgvector ]           # <--- 安装扩展软件包
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain'    # <--- 配置预加载扩展
    pg_databases:
      - name: meta
        extensions: [ postgis, timescaledb, vector ]            # <--- 在数据库中启用
bin/pgsql-ext <cls>           # 在 <cls> 集群上安装配置中定义的扩展
bin/pgsql-ext <cls> [ext...]  # 在 <cls> 集群上安装命令行参数给出的扩展
./pgsql.yml -l pg-meta -t pg_ext    # 使用剧本安装扩展
bin/pgsql-ext pg-meta                         # 在 pg-meta 集群上安装定义的扩展
bin/pgsql-ext pg-meta pg_duckdb pg_mooncake   # 安装指定扩展

关于扩展的完整参考,请查阅 扩展插件 章节。关于可用扩展列表,请参考 扩展目录

操作快捷命令说明
下载扩展./infra.yml -t repo_build将扩展下载到本地仓库
安装扩展bin/pgsql-ext <cls>在集群节点上安装扩展软件包
配置扩展pg edit-config <cls> -p将扩展添加到预加载库(需重启)
启用扩展psql -c 'CREATE EXT ...'在数据库中创建扩展对象
更新扩展ALTER EXTENSION UPDATE更新扩展软件包与扩展对象
移除扩展DROP EXTENSION删除扩展对象,卸载软件包

安装扩展

定义在 pg_extensions 里面的扩展会在 PostgreSQL 集群创建 的时候在 pg_extension 任务中自动安装。

要在现有的 PostgreSQL 集群上安装扩展,请将扩展添加到 all.children.<cls>.pg_extensions,然后执行:

bin/pgsql-ext <cls>   # 在 <cls> 集群上安装扩展
./pgsql.yml -l <cls> -t pg_extension   # 直接使用 Ansible 剧本安装扩展
bin/pgsql-ext pg-meta    # 在 pg-meta 集群上安装配置中定义的扩展

示例配置:在集群上安装 PostGIS、TimescaleDB 和 PGVector

#all.children.pg-meta.vars: # 省略上级缩进
pg_extensions: [ postgis, timescaledb, pgvector ]

执行效果:在集群所有节点上安装扩展软件包。Pigsty 会自动将 包别名 翻译为对应操作系统和 PostgreSQL 版本的实际包名。


手工安装

如果您不想使用 Pigsty 配置来管理 PostgreSQL 扩展,可以在命令行中直接传递要安装的扩展列表:

bin/pgsql-ext pg-meta pg_duckdb pg_mooncake   # 在 pg-meta 集群上安装指定扩展
./pgsql.yml -l pg-meta -t pg_ext -e '{"pg_extensions": ["pg_duckdb", "pg_mooncake"]}'

您也可以使用 pig 包管理器命令行工具在单个节点上安装扩展,同样会自动进行 包别名 解析。

pig install postgis timescaledb       # 安装多个扩展
pig install pgvector -v 17            # 针对特定 PG 大版本安装

ansible pg-test -b -a 'pig install pg_duckdb'   # 使用 Ansible 在集群上批量安装

您也可以 直接使用操作系统包管理器 (apt/dnf) 进行安装,但您必须知道具体操作系统/PG下的 RPM/DEB 包名:

# EL 系统(RHEL、Rocky、Alma、Oracle Linux)
sudo yum install -y pgvector_17*

# Debian / Ubuntu 系统
sudo apt install -y postgresql-17-pgvector

下载扩展

要想安装扩展,您需要确保节点上配置的 扩展仓库 包含待安装的扩展:

  • 单机安装 时无需操心,上游仓库已经直接添加到节点上。
  • 离线安装 时无需操心,绝大部分扩展都已经包含在离线安装包里,个别扩展需要在线安装。
  • 使用本地仓库的 生产多节点部署,要看情况,如果在本地仓库创建的时候 repo_packages / repo_extra_packages 中包含了扩展包, 则意味着已经下载到了本地,可以直接安装,否则需要先下载扩展包到本地仓库。或者直接为节点 配置上游仓库 在线安装。

Pigsty 的默认配置在安装过程中会自动下载主流扩展到本地仓库。如需额外扩展,添加到 repo_extra_packages 后重建仓库:

repo_extra_packages: [ pgvector, postgis, timescaledb ]
make repo         # 快捷方式 = repo-build + node-repo
make repo-build   # 快捷方式,重建 Infra 上的软件仓库(下载软件包与依赖)
make node-repo    # 快捷方式,刷新节点上的软件源缓存,更新对 Infra 软件仓库的引用
./deploy.yml -t repo_build,node_repo  # 一次性执行两个任务
./infra.yml -t repo_build     # 重新下载软件包到本地仓库
./node.yml  -t node_repo      # 刷新节点软件源缓存

配置仓库

您也可以选择直接让所有节点都使用上游仓库(生产环境不推荐),跳过下载步骤,直接从互联网 上游扩展仓库 安装

./node.yml -t node_repo -e node_repo_modules=node,pgsql   # 添加 PGDG 与 Pigsty 上游仓库

配置扩展

部分扩展需要预加载到 shared_preload_libraries 才能使用,修改后需要 重启数据库 生效。

您可以用 pg_libs 参数作为它的默认值,在配置预加载的扩展,但是这个参数只在集群初始化时生效,后面修改就无效了。

pg-meta:
  vars:
    pg_cluster: pg-meta
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain'   # 预加载扩展
    pg_extensions: [ timescaledb, postgis, pgvector ]          # 安装扩展包

对于已有集群,您可以参考 修改配置 的介绍,修改 shared_preload_libraries参数:

pg edit-config pg-meta --force -p shared_preload_libraries='timescaledb, pg_stat_statements, auto_explain'
pg restart pg-meta   # 修改 pg-meta 集群的参数,并重启集群使配置生效

请确保扩展软件包已正确安装后再添加预加载配置,如果 shared_preload_libraries 中的扩展不存在或加载失败,PostgreSQL 将 无法启动。 此外,请通过 Patroni 管理集群的配置变更,避免使用 ALTER SYSTEM 或者 pg_parameters 单独修改实例配置。 如果主库和从库配置不一致,可能导致启动失败或复制中断。


启用扩展

安装扩展软件包后,需要在数据库中执行 CREATE EXTENSION 才能使用扩展提供的功能。

集群初始化时启用

数据库定义 中通过 extensions 数组声明要启用的扩展:

pg_databases:
  - name: meta
    extensions:
      - vector                             # 简单形式
      - { name: postgis, schema: public }  # 指定 Schema

手动启用

CREATE EXTENSION vector;                      -- 创建扩展
CREATE EXTENSION postgis SCHEMA public;       -- 指定 Schema
CREATE EXTENSION IF NOT EXISTS vector;        -- 幂等创建
CREATE EXTENSION postgis_topology CASCADE;    -- 自动安装依赖
psql -d meta -c 'CREATE EXTENSION vector;'                  # 在 meta 数据库创建扩展
psql -d meta -c 'CREATE EXTENSION postgis SCHEMA public;'   # 指定 Schema
# 修改数据库定义后使用剧本启用扩展
bin/pgsql-db pg-meta meta    # 创建/修改数据库会自动启用定义的扩展

执行效果:在数据库中创建扩展对象(函数、类型、操作符、索引方法等),之后即可使用扩展提供的功能。


更新扩展

扩展更新涉及两个层面:软件包更新扩展对象更新

更新软件包

pig update pgvector                           # 使用 pig 更新扩展
sudo yum update pgvector_18 # EL
sudo apt upgrade postgresql-18-pgvector  # Debian/Ubuntu

更新扩展对象

-- 查看可升级的扩展
SELECT name, installed_version, default_version FROM pg_available_extensions
WHERE installed_version IS NOT NULL AND installed_version <> default_version;

-- 更新扩展到最新版本
ALTER EXTENSION vector UPDATE;

-- 更新到指定版本
ALTER EXTENSION vector UPDATE TO '0.8.1';

移除扩展

移除扩展涉及两个层面:删除扩展对象卸载软件包

删除扩展对象

DROP EXTENSION vector;              -- 删除扩展
DROP EXTENSION vector CASCADE;      -- 级联删除(删除依赖对象)

移除预加载

如果是预加载扩展,需从 shared_preload_libraries 中移除并重启:

pg edit-config pg-meta --force -p shared_preload_libraries='pg_stat_statements, auto_explain'
pg restart pg-meta   # 重启使配置生效

卸载软件包(可选)

pig remove pgvector                           # 使用 pig 卸载
sudo yum remove pgvector_17*                  # EL 系统
sudo apt remove postgresql-17-pgvector        # Debian/Ubuntu

查询扩展

以下是一些常用的 SQL 查询,用于查看扩展信息:

查看已启用的扩展

SELECT extname, extversion, nspname AS schema
FROM pg_extension e JOIN pg_namespace n ON e.extnamespace = n.oid
ORDER BY extname;

查看可用扩展

SELECT name, default_version, installed_version, comment
FROM pg_available_extensions
WHERE installed_version IS NOT NULL   -- 仅显示已安装的
ORDER BY name;

检查扩展是否可用

SELECT * FROM pg_available_extensions WHERE name = 'vector';

查看扩展依赖关系

SELECT e.extname, d.refobjid::regclass AS depends_on
FROM pg_extension e
JOIN pg_depend d ON d.objid = e.oid
WHERE d.deptype = 'e' AND e.extname = 'postgis_topology';

查看扩展对象

SELECT classid::regclass, objid, deptype
FROM pg_depend
WHERE refobjid = (SELECT oid FROM pg_extension WHERE extname = 'vector');

psql 快捷命令

\dx                    # 列出已启用的扩展
\dx+ vector            # 显示扩展详情

添加仓库

如需直接从上游安装扩展,可手动添加软件仓库。

使用 Pigsty 剧本添加

./node.yml -t node_repo -e node_repo_modules=node,pgsql        # 添加 PGDG 与 Pigsty 仓库
./node.yml -t node_repo -e node_repo_modules=node,pgsql,local  # 包括本地仓库

YUM 仓库(EL 系统)

# Pigsty 仓库
curl -fsSL https://repo.pigsty.io/key | sudo tee /etc/pki/rpm-gpg/RPM-GPG-KEY-pigsty >/dev/null
curl -fsSL https://repo.pigsty.io/yum/repo | sudo tee /etc/yum.repos.d/pigsty.repo >/dev/null

# 中国大陆镜像
curl -fsSL https://repo.pigsty.cc/key | sudo tee /etc/pki/rpm-gpg/RPM-GPG-KEY-pigsty >/dev/null
curl -fsSL https://repo.pigsty.cc/yum/repo | sudo tee /etc/yum.repos.d/pigsty.repo >/dev/null

APT 仓库(Debian/Ubuntu)

curl -fsSL https://repo.pigsty.io/key | sudo gpg --dearmor -o /etc/apt/keyrings/pigsty.gpg
sudo tee /etc/apt/sources.list.d/pigsty.list > /dev/null <<EOF
deb [signed-by=/etc/apt/keyrings/pigsty.gpg] https://repo.pigsty.io/apt/infra generic main
deb [signed-by=/etc/apt/keyrings/pigsty.gpg] https://repo.pigsty.io/apt/pgsql $(lsb_release -cs) main
EOF
sudo apt update

# 中国大陆镜像:将 repo.pigsty.io 替换为 repo.pigsty.cc

常见问题

扩展名与包名的区别

名称说明示例
扩展名CREATE EXTENSION 使用的名称vector
包别名Pigsty 配置中使用的标准化名称pgvector
包名操作系统实际的包名pgvector_17*postgresql-17-pgvector

预加载扩展无法启动

如果 shared_preload_libraries 中的扩展不存在或加载失败,PostgreSQL 将无法启动。解决方法:

  1. 确保扩展软件包已正确安装
  2. 或从 shared_preload_libraries 中移除该扩展(编辑 /pg/data/postgresql.conf

扩展依赖问题

某些扩展依赖于其他扩展,需按顺序创建或使用 CASCADE

CREATE EXTENSION postgis;                    -- 先创建基础扩展
CREATE EXTENSION postgis_topology;           -- 再创建依赖扩展
-- 或
CREATE EXTENSION postgis_topology CASCADE;   -- 自动创建依赖

扩展版本不兼容

查看当前 PostgreSQL 版本支持的扩展版本:

SELECT * FROM pg_available_extension_versions WHERE name = 'vector';

相关资源

7 - 备份恢复

时间点恢复(PITR)备份与恢复

Pigsty 使用 pgBackRest 管理 PostgreSQL 备份,这可能是生态系统中最强大的开源备份工具。 它支持增量/并行备份与恢复、加密、MinIO/S3 等众多特性。Pigsty 默认为每个 PGSQL 集群预配置了备份功能。

章节内容
机制备份脚本、定时任务、pgbackrest、仓库与管理
策略备份策略、磁盘规划、恢复窗口权衡
仓库配置备份仓库:本地、MinIO、S3
管理常用备份管理命令
恢复使用剧本恢复到特定时间点
示例沙箱示例:手工执行恢复操作

快速上手

  1. 备份策略:使用 Crontab 调度基础备份
  2. WAL 归档:持续记录写入活动
  3. 恢复与还原:从备份和 WAL 归档中恢复
node_crontab: [ '00 01 * * * postgres /pg/bin/pg-backup full' ]
./pgsql-pitr.yml -e '{"pg_pitr": { "time": "2025-07-13 10:00:00+00" }}'

7.1 - 备份策略

根据您的需求设计备份策略
  • 何时:备份策略
  • 何处:备份仓库
  • 如何:备份方法

何时备份

第一个问题是何时备份您的数据库——这是备份频率和恢复时间之间的权衡。 由于您需要从上一次备份开始重放 WAL 日志到恢复目标点,备份越频繁,需要重放的 WAL 日志就越少,恢复速度就越快。

每日全量备份

对于生产数据库,建议从最简单的每日全量备份策略开始。 这也是 Pigsty 的默认备份策略,通过 crontab 实现。

node_crontab: [ '00 01 * * * postgres /pg/bin/pg-backup full' ]
pgbackrest_method: local          # 选择备份仓库方法:`local`、`minio` 或其他自定义仓库
pgbackrest_repo:                  # pgbackrest 仓库配置: https://pgbackrest.org/configuration.html#section-repository
  local:                          # 使用本地 POSIX 文件系统的默认 pgbackrest 仓库
    path: /pg/backup              # 本地备份目录,默认为 `/pg/backup`
    retention_full_type: count    # 按数量保留全量备份
    retention_full: 2             # 使用本地文件系统仓库时,保留2个,最多3个全量备份

配合默认的 local 本地文件系统备份仓库使用时,可提供 24~48 小时的恢复窗口。

pitr-scope

假设您的数据库大小为 100GB,每天写入 10GB 数据,则备份大小如下:

pitr-space

这将消耗数据库大小的 2~3 倍空间,再加上 2 天的 WAL 日志。 因此在实践中,您可能需要准备至少 3~5 倍数据库大小的备份磁盘才能使用默认备份策略。

全量 + 增量备份

您可以通过调整这些参数来优化备份空间使用。

如果使用 MinIO / S3 作为集中式备份仓库,您可以使用超出本地磁盘限制的存储空间。 此时可以考虑使用全量 + 增量备份配合 2 周保留策略:

node_crontab:  # 周一凌晨1点全量备份,工作日增量备份
  - '00 01 * * 1 postgres /pg/bin/pg-backup full'
  - '00 01 * * 2,3,4,5,6,7 postgres /pg/bin/pg-backup'
pgbackrest_method: minio
pgbackrest_repo:                  # pgbackrest 仓库配置: https://pgbackrest.org/configuration.html#section-repository
  minio:                          # 可选的 minio 仓库
    type: s3                      # minio 兼容 S3 协议
    s3_endpoint: sss.pigsty       # minio 端点域名,默认为 `sss.pigsty`
    s3_region: us-east-1          # minio 区域,默认 us-east-1,对 minio 无实际意义
    s3_bucket: pgsql              # minio 桶名,默认为 `pgsql`
    s3_key: pgbackrest            # pgbackrest 的 minio 用户访问密钥
    s3_key_secret: S3User.Backup  # pgbackrest 的 minio 用户密钥
    s3_uri_style: path            # minio 使用路径风格 URI 而非主机风格
    path: /pgbackrest             # minio 备份路径,默认为 `/pgbackrest`
    storage_port: 9000            # minio 端口,默认 9000
    storage_ca_file: /etc/pki/ca.crt  # minio CA 证书路径,默认 `/etc/pki/ca.crt`
    block: y                      # 启用块级增量备份
    bundle: y                     # 将小文件打包成单个文件
    bundle_limit: 20MiB           # 文件包大小限制,对象存储建议 20MiB
    bundle_size: 128MiB           # 文件包目标大小,对象存储建议 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码,默认为 'pgBackRest'
    retention_full_type: time     # 按时间保留全量备份
    retention_full: 14            # 保留最近 14 天的全量备份

配合内置的 minio 备份仓库使用时,可提供保证 1 周的 PITR 恢复窗口。

pitr-scope2

假设您的数据库大小为 100GB,每天写入 10GB 数据,则备份大小如下:

pitr-space2


备份位置

默认情况下,Pigsty 提供两个默认备份仓库定义:localminio 备份仓库。

  • local默认选项,使用本地 /pg/backup 目录(软链接指向 pg_fs_backup/data/backups
  • minio:使用 SNSD 单节点 MinIO 集群(Pigsty 支持,但默认不启用)
pgbackrest_method: local          # 选择备份仓库方法:`local`、`minio` 或其他自定义仓库
pgbackrest_repo:                  # pgbackrest 仓库配置: https://pgbackrest.org/configuration.html#section-repository
  local:                          # 使用本地 POSIX 文件系统的默认 pgbackrest 仓库
    path: /pg/backup              # 本地备份目录,默认为 `/pg/backup`
    retention_full_type: count    # 按数量保留全量备份
    retention_full: 2             # 使用本地文件系统仓库时,保留2个,最多3个全量备份
  minio:                          # 可选的 minio 仓库
    type: s3                      # minio 兼容 S3 协议
    s3_endpoint: sss.pigsty       # minio 端点域名,默认为 `sss.pigsty`
    s3_region: us-east-1          # minio 区域,默认 us-east-1,对 minio 无实际意义
    s3_bucket: pgsql              # minio 桶名,默认为 `pgsql`
    s3_key: pgbackrest            # pgbackrest 的 minio 用户访问密钥
    s3_key_secret: S3User.Backup  # pgbackrest 的 minio 用户密钥
    s3_uri_style: path            # minio 使用路径风格 URI 而非主机风格
    path: /pgbackrest             # minio 备份路径,默认为 `/pgbackrest`
    storage_port: 9000            # minio 端口,默认 9000
    storage_ca_file: /etc/pki/ca.crt  # minio CA 证书路径,默认 `/etc/pki/ca.crt`
    block: y                      # 启用块级增量备份
    bundle: y                     # 将小文件打包成单个文件
    bundle_limit: 20MiB           # 文件包大小限制,对象存储建议 20MiB
    bundle_size: 128MiB           # 文件包目标大小,对象存储建议 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码,默认为 'pgBackRest'
    retention_full_type: time     # 按时间保留全量备份
    retention_full: 14            # 保留最近 14 天的全量备份

7.2 - 备份机制

备份脚本、定时任务、备份仓库与基础设施

备份可以通过内置 脚本 调用,使用节点 crontab 定时执行, 由 pgbackrest 管理,存储在备份仓库中, 仓库可以是本地磁盘文件系统或 MinIO / S3,并支持不同的 保留 策略。


脚本

您可以使用 pg_dbsu 用户(默认为 postgres)执行 pgbackrest 命令创建备份:

pgbackrest --stanza=pg-meta --type=full backup   # 为集群 pg-meta 创建全量备份
$ pgbackrest --stanza=pg-meta --type=full backup
2025-07-15 01:36:57.007 P00   INFO: backup command begin 2.54.2: --annotation=pg_cluster=pg-meta ...
2025-07-15 01:36:57.030 P00   INFO: execute non-exclusive backup start: backup begins after the requested immediate checkpoint completes
2025-07-15 01:36:57.105 P00   INFO: backup start archive = 000000010000000000000006, lsn = 0/6000028
2025-07-15 01:36:58.540 P00   INFO: new backup label = 20250715-013657F
2025-07-15 01:36:58.588 P00   INFO: full backup size = 44.5MB, file total = 1437
2025-07-15 01:36:58.589 P00   INFO: backup command end: completed successfully (1584ms)
$ pgbackrest --stanza=pg-meta --type=diff backup
2025-07-15 01:37:24.952 P00   INFO: backup command begin 2.54.2: ...
2025-07-15 01:37:24.985 P00   INFO: last backup label = 20250715-013657F, version = 2.54.2
2025-07-15 01:37:26.337 P00   INFO: new backup label = 20250715-013657F_20250715-013724D
2025-07-15 01:37:26.381 P00   INFO: diff backup size = 424.3KB, file total = 1437
2025-07-15 01:37:26.381 P00   INFO: backup command end: completed successfully (1431ms)
$ pgbackrest --stanza=pg-meta --type=incr backup
2025-07-15 01:37:30.305 P00   INFO: backup command begin 2.54.2: ...
2025-07-15 01:37:30.337 P00   INFO: last backup label = 20250715-013657F_20250715-013724D, version = 2.54.2
2025-07-15 01:37:31.356 P00   INFO: new backup label = 20250715-013657F_20250715-013730I
2025-07-15 01:37:31.403 P00   INFO: incr backup size = 8.3KB, file total = 1437
2025-07-15 01:37:31.403 P00   INFO: backup command end: completed successfully (1099ms)
$ pgbackrest --stanza=pg-meta info
stanza: pg-meta
    status: ok
    cipher: aes-256-cbc

    db (current)
        wal archive min/max (17): 000000010000000000000001/00000001000000000000000A

        full backup: 20250715-013657F
            timestamp start/stop: 2025-07-15 01:36:57+00 / 2025-07-15 01:36:58+00
            wal start/stop: 000000010000000000000006 / 000000010000000000000006
            database size: 44.5MB, database backup size: 44.5MB
            repo1: backup size: 8.7MB

        diff backup: 20250715-013657F_20250715-013724D
            timestamp start/stop: 2025-07-15 01:37:24+00 / 2025-07-15 01:37:26+00
            database size: 44.5MB, database backup size: 424.3KB
            repo1: backup size: 94KB
            backup reference total: 1 full

        incr backup: 20250715-013657F_20250715-013730I
            timestamp start/stop: 2025-07-15 01:37:30+00 / 2025-07-15 01:37:31+00
            database size: 44.5MB, database backup size: 8.3KB
            repo1: backup size: 504B
            backup reference total: 1 full, 1 diff

这里的 stanza 是数据库集群名称:pg_cluster,在默认配置中为 pg-meta

Pigsty 提供了 pb 别名和 pg-backup 包装脚本,会自动填充当前集群名称作为 stanza:

function pb() {
    local stanza=$(grep -o '\[[^][]*]' /etc/pgbackrest/pgbackrest.conf | head -n1 | sed 's/.*\[\([^]]*\)].*/\1/')
    pgbackrest --stanza=$stanza $@
}
pb ...    # pgbackrest --stanza=pg-meta ...
pb info   # pgbackrest --stanza=pg-meta info
pb backup # pgbackrest --stanza=pg-meta backup
pg-backup full   # 执行全量备份         = pgbackrest --stanza=pg-meta --type=full backup
pg-backup incr   # 执行增量备份         = pgbackrest --stanza=pg-meta --type=incr backup
pg-backup diff   # 执行差异备份         = pgbackrest --stanza=pg-meta --type=diff backup

定时备份

Pigsty 利用 Linux crontab 来调度备份任务。您可以用它定义备份策略。

例如,大多数单节点配置模板都有以下用于备份的 node_crontab

node_crontab: [ '00 01 * * * postgres /pg/bin/pg-backup full' ]

您可以使用 crontab 和 pg-backup 脚本设计更复杂的备份策略,例如:

node_crontab:  # 周一凌晨1点全量备份,工作日增量备份
  - '00 01 * * 1 postgres /pg/bin/pg-backup full'
  - '00 01 * * 2,3,4,5,6,7 postgres /pg/bin/pg-backup'

要应用 crontab 变更,使用 node.yml 更新所有节点的 crontab:

./node.yml -t node_crontab -l pg-meta    # 将 crontab 变更应用到 pg-meta 组

pgbackrest

以下是 Pigsty 对 pgbackrest 的配置细节:

文件层次结构

  • bin:/usr/bin/pgbackrest,来自 PGDG 的 pgbackrest 包,在组别名 pgsql-common 中。
  • conf:/etc/pgbackrest,主配置文件是 /etc/pgbackrest/pgbackrest.conf
  • logs:/pg/log/pgbackrest/*,由 pgbackrest_log_dir 控制
  • tmp:/pg/spool 用作 pgbackrest 的临时 spool 目录
  • data:/pg/backup 用于存储数据(当选择默认的 local 文件系统备份仓库时)

此外,在 PITR 恢复 过程中,Pigsty 会创建临时的 /pg/conf/pitr.conf pgbackrest 配置文件, 并将 postgres 恢复日志写入 /pg/tmp/recovery.log 文件。

监控

有一个 pgbackrest_exporter 服务运行在 pgbackrest_exporter_port9854)端口上,用于导出 pgbackrest 指标。 您可以通过 pgbackrest_exporter_options 自定义它, 或将 pgbackrest_exporter_enabled 设置为 false 来禁用它。

初始备份

当创建 postgres 集群时,Pigsty 会自动创建初始备份。 由于新集群几乎为空,这是一个很小的备份。 它会留下一个 /etc/pgbackrest/initial.done 标记文件,以避免重复创建初始备份。 如果不需要初始备份,请将 pgbackrest_init_backup 设置为 false


管理

启用备份

如果数据库集群创建时 pgbackrest_enabled 设置为 true,备份将自动启用。

如果创建时该值为 false,您可以使用以下命令启用 pgbackrest 组件:

./pgsql.yml -t pg_backup    # 运行 pgbackrest 子任务

删除备份

当移除主实例(pg_role = primary)时,Pigsty 会删除 pgbackrest 备份 stanza。

./pgsql-rm.yml
./pgsql-rm.yml -e pg_rm_backup=false   # 保留备份
./pgsql-rm.yml -t pg_backup            # 仅删除备份

使用 pg_backup 子任务仅删除备份,使用 pg_rm_backup 参数(设为 false)保留备份。

如果您的备份仓库被锁定(例如 S3 / MinIO 有锁定选项),此操作将失败。

列出备份

此命令将列出 pgbackrest 仓库中的所有备份(所有集群共享)

pgbackrest info

手动备份

Pigsty 提供了内置脚本 /pg/bin/pg-backup,封装了 pgbackrest 备份命令。

pg-backup        # 执行增量备份
pg-backup full   # 执行全量备份
pg-backup incr   # 执行增量备份
pg-backup diff   # 执行差异备份

基础备份

Pigsty 提供了一个替代备份脚本 /pg/bin/pg-basebackup,它不依赖 pgbackrest,直接提供数据库集群的物理副本。 默认备份目录为 /pg/backup

NAME
  pg-basebackup  -- make base backup from PostgreSQL instance

SYNOPSIS
  pg-basebackup -sdfeukr
  pg-basebackup --src postgres:/// --dst . --file backup.tar.lz4

DESCRIPTION
-s, --src, --url     备份源 URL,可选,默认为 "postgres:///",如需密码应在 url、ENV 或 .pgpass 中提供
-d, --dst, --dir     备份文件存放位置,默认为 "/pg/backup"
-f, --file           覆盖默认备份文件名,"backup_${tag}_${date}.tar.lz4"
-r, --remove         删除 n 分钟前的 .lz4 文件,默认 1200(20小时)
-t, --tag            备份文件标签,未设置时使用目标集群名或本地 IP 地址,也用于默认文件名
-k, --key            指定 --encrypt 时的加密密钥,默认密钥为 ${tag}
-u, --upload         上传备份文件到云存储(需自行实现)
-e, --encryption     使用 OpenSSL RC4 加密,未指定密钥时使用 tag 作为密钥
-h, --help           打印此帮助信息
postgres@pg-meta-1:~$ pg-basebackup
[2025-07-13 06:16:05][INFO] ================================================================
[2025-07-13 06:16:05][INFO] [INIT] pg-basebackup begin, checking parameters
[2025-07-13 06:16:05][DEBUG] [INIT] filename  (-f)    :   backup_pg-meta_20250713.tar.lz4
[2025-07-13 06:16:05][DEBUG] [INIT] src       (-s)    :   postgres:///
[2025-07-13 06:16:05][DEBUG] [INIT] dst       (-d)    :   /pg/backup
[2025-07-13 06:16:05][INFO] [LOCK] lock acquired success on /tmp/backup.lock, pid=107417
[2025-07-13 06:16:05][INFO] [BKUP] backup begin, from postgres:/// to /pg/backup/backup_pg-meta_20250713.tar.lz4
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/7000028 on timeline 1
pg_basebackup: write-ahead log end point: 0/7000FD8
pg_basebackup: syncing data to disk ...
pg_basebackup: base backup completed
[2025-07-13 06:16:06][INFO] [BKUP] backup complete!
[2025-07-13 06:16:06][INFO] [DONE] backup procedure complete!
[2025-07-13 06:16:06][INFO] ================================================================

备份使用 lz4 压缩。您可以使用以下命令解压并提取 tarball:

mkdir -p /tmp/data   # 将备份提取到此目录
cat /pg/backup/backup_pg-meta_20250713.tar.lz4 | unlz4 -d -c | tar -xC /tmp/data

逻辑备份

您也可以使用 pg_dump 命令执行逻辑备份。

逻辑备份不能用于 PITR(时间点恢复),但对于在不同主版本之间迁移数据或实现灵活的数据导出逻辑非常有用。

从仓库引导

假设您有一个现有集群 pg-meta,想要将其克隆pg-meta2

您需要创建新的 pg-meta2 集群分支,然后在其上运行 pitr

7.3 - 备份仓库

PostgreSQL 备份存储仓库配置

您可以通过指定 pgbackrest_repo 参数来配置备份存储位置。 您可以在此定义多个仓库,Pigsty 会根据 pgbackrest_method 的值选择使用哪个。

默认仓库

默认情况下,Pigsty 提供两个默认备份仓库定义:localminio 备份仓库。

  • local默认选项,使用本地 /pg/backup 目录(软链接指向 pg_fs_backup/data/backups
  • minio:使用 SNSD 单节点 MinIO 集群(Pigsty 支持,但默认不启用)
pgbackrest_method: local          # 选择备份仓库方法:`local`、`minio` 或其他自定义仓库
pgbackrest_repo:                  # pgbackrest 仓库配置: https://pgbackrest.org/configuration.html#section-repository
  local:                          # 使用本地 POSIX 文件系统的默认 pgbackrest 仓库
    path: /pg/backup              # 本地备份目录,默认为 `/pg/backup`
    retention_full_type: count    # 按数量保留全量备份
    retention_full: 2             # 使用本地文件系统仓库时,保留2个,最多3个全量备份
  minio:                          # 可选的 minio 仓库
    type: s3                      # minio 兼容 S3 协议
    s3_endpoint: sss.pigsty       # minio 端点域名,默认为 `sss.pigsty`
    s3_region: us-east-1          # minio 区域,默认 us-east-1,对 minio 无实际意义
    s3_bucket: pgsql              # minio 桶名,默认为 `pgsql`
    s3_key: pgbackrest            # pgbackrest 的 minio 用户访问密钥
    s3_key_secret: S3User.Backup  # pgbackrest 的 minio 用户密钥
    s3_uri_style: path            # minio 使用路径风格 URI 而非主机风格
    path: /pgbackrest             # minio 备份路径,默认为 `/pgbackrest`
    storage_port: 9000            # minio 端口,默认 9000
    storage_ca_file: /etc/pki/ca.crt  # minio CA 证书路径,默认 `/etc/pki/ca.crt`
    block: y                      # 启用块级增量备份
    bundle: y                     # 将小文件打包成单个文件
    bundle_limit: 20MiB           # 文件包大小限制,对象存储建议 20MiB
    bundle_size: 128MiB           # 文件包目标大小,对象存储建议 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码,默认为 'pgBackRest'
    retention_full_type: time     # 按时间保留全量备份
    retention_full: 14            # 保留最近 14 天的全量备份

仓库保留策略

如果每天备份但不删除旧备份,备份仓库会不断增长并耗尽磁盘空间。 您需要定义保留策略,只保留有限数量的备份。

默认备份策略定义在 pgbackrest_repo 参数中,可按需调整。

  • local:保留最近 2 个全量备份,备份期间最多允许 3 个
  • minio:保留最近 14 天的所有全量备份

空间规划

对象存储提供几乎无限的存储容量,因此无需担心磁盘空间。 您可以使用混合的全量 + 差异备份策略来优化空间使用。

对于本地磁盘备份仓库,Pigsty 建议使用保留最近 2 个全量备份的策略, 这意味着磁盘上保留两个最新的全量备份(运行新备份时可能存在第三个副本)。

这可保证至少 24 小时的恢复窗口。详情请参阅 备份策略


其他仓库选项

您也可以使用其他服务作为备份仓库,详情请参阅 pgbackrest 文档


仓库版本控制

您甚至可以指定 repo target time 来获取对象存储的快照。

您可以通过在 minio_buckets 中添加 versioning 标志来启用 MinIO 版本控制:

minio_buckets:
  - { name: pgsql ,versioning: true }
  - { name: meta  ,versioning: true }
  - { name: data }

仓库锁定

某些对象存储服务(S3、MinIO 等)支持锁定功能,可以防止备份被删除,即使是 DBA 本人也无法删除。

您可以通过在 minio_buckets 中添加 lock 标志来启用 MinIO 锁定功能:

minio_buckets:
  - { name: pgsql , lock: true }
  - { name: meta ,versioning: true  }
  - { name: data }

使用对象存储

对象存储服务提供几乎无限的存储容量,并为您的系统提供远程容灾能力。 如果您没有对象存储服务,Pigsty 内置了 MinIO 支持。

MinIO

您可以通过取消注释以下设置来启用 MinIO 备份仓库。 请注意 pgbackrest 只支持 HTTPS / 域名,因此您必须使用域名和 HTTPS 端点运行 MinIO。

all:
  vars:
    pgbackrest_method: minio      # 使用 minio 作为默认备份仓库
  children:                       # 定义一个单节点 minio SNSD 集群
    minio: { hosts: { 10.10.10.10: { minio_seq: 1 }} ,vars: { minio_cluster: minio }}

S3

如果您只有一个节点,有意义的备份策略可以是使用云厂商的对象存储服务,如 AWS S3、阿里云 OSS 或 Google Cloud 等。 为此,您可以定义一个新仓库:

pgbackrest_method: s3             # 使用 'pgbackrest_repo.s3' 作为备份仓库
pgbackrest_repo:                  # pgbackrest 仓库配置: https://pgbackrest.org/configuration.html#section-repository

  s3:                             # 阿里云 OSS(S3 兼容)对象存储服务
    type: s3                      # oss 兼容 S3 协议
    s3_endpoint: oss-cn-beijing-internal.aliyuncs.com
    s3_region: oss-cn-beijing
    s3_bucket: <your_bucket_name>
    s3_key: <your_access_key>
    s3_key_secret: <your_secret_key>
    s3_uri_style: host
    path: /pgbackrest
    bundle: y                     # 将小文件打包成单个文件
    bundle_limit: 20MiB           # 文件包大小限制,对象存储建议 20MiB
    bundle_size: 128MiB           # 文件包目标大小,对象存储建议 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码,默认为 'pgBackRest'
    retention_full_type: time     # 按时间保留全量备份
    retention_full: 14            # 保留最近 14 天的全量备份

  local:                          # 使用本地 POSIX 文件系统的默认 pgbackrest 仓库
    path: /pg/backup              # 本地备份目录,默认为 `/pg/backup`
    retention_full_type: count    # 按数量保留全量备份
    retention_full: 2             # 使用本地文件系统仓库时,保留2个,最多3个全量备份

管理备份

启用备份

如果数据库集群创建时 pgbackrest_enabled 设置为 true,备份将自动启用。

如果创建时该值为 false,您可以使用以下命令启用 pgbackrest 组件:

./pgsql.yml -t pg_backup    # 运行 pgbackrest 子任务

删除备份

当移除主实例(pg_role = primary)时,Pigsty 会删除 pgbackrest 备份 stanza。

./pgsql-rm.yml
./pgsql-rm.yml -e pg_rm_backup=false   # 保留备份
./pgsql-rm.yml -t pg_backup            # 仅删除备份

使用 pg_backup 子任务仅删除备份,使用 pg_rm_backup 参数(设为 false)保留备份。

如果您的备份仓库被锁定(例如 S3 / MinIO 有锁定选项),此操作将失败。

列出备份

此命令将列出 pgbackrest 仓库中的所有备份(所有集群共享)

pgbackrest info

手动备份

Pigsty 提供了内置脚本 /pg/bin/pg-backup,封装了 pgbackrest 备份命令。

pg-backup        # 执行增量备份
pg-backup full   # 执行全量备份
pg-backup incr   # 执行增量备份
pg-backup diff   # 执行差异备份

基础备份

Pigsty 提供了一个替代备份脚本 /pg/bin/pg-basebackup,它不依赖 pgbackrest,直接提供数据库集群的物理副本。 默认备份目录为 /pg/backup

NAME
  pg-basebackup  -- make base backup from PostgreSQL instance

SYNOPSIS
  pg-basebackup -sdfeukr
  pg-basebackup --src postgres:/// --dst . --file backup.tar.lz4

DESCRIPTION
-s, --src, --url     备份源 URL,可选,默认为 "postgres:///",如需密码应在 url、ENV 或 .pgpass 中提供
-d, --dst, --dir     备份文件存放位置,默认为 "/pg/backup"
-f, --file           覆盖默认备份文件名,"backup_${tag}_${date}.tar.lz4"
-r, --remove         删除 n 分钟前的 .lz4 文件,默认 1200(20小时)
-t, --tag            备份文件标签,未设置时使用目标集群名或本地 IP 地址,也用于默认文件名
-k, --key            指定 --encrypt 时的加密密钥,默认密钥为 ${tag}
-u, --upload         上传备份文件到云存储(需自行实现)
-e, --encryption     使用 OpenSSL RC4 加密,未指定密钥时使用 tag 作为密钥
-h, --help           打印此帮助信息
postgres@pg-meta-1:~$ pg-basebackup
[2025-07-13 06:16:05][INFO] ================================================================
[2025-07-13 06:16:05][INFO] [INIT] pg-basebackup begin, checking parameters
[2025-07-13 06:16:05][DEBUG] [INIT] filename  (-f)    :   backup_pg-meta_20250713.tar.lz4
[2025-07-13 06:16:05][DEBUG] [INIT] src       (-s)    :   postgres:///
[2025-07-13 06:16:05][DEBUG] [INIT] dst       (-d)    :   /pg/backup
[2025-07-13 06:16:05][INFO] [LOCK] lock acquired success on /tmp/backup.lock, pid=107417
[2025-07-13 06:16:05][INFO] [BKUP] backup begin, from postgres:/// to /pg/backup/backup_pg-meta_20250713.tar.lz4
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/7000028 on timeline 1
pg_basebackup: write-ahead log end point: 0/7000FD8
pg_basebackup: syncing data to disk ...
pg_basebackup: base backup completed
[2025-07-13 06:16:06][INFO] [BKUP] backup complete!
[2025-07-13 06:16:06][INFO] [DONE] backup procedure complete!
[2025-07-13 06:16:06][INFO] ================================================================

备份使用 lz4 压缩。您可以使用以下命令解压并提取 tarball:

mkdir -p /tmp/data   # 将备份提取到此目录
cat /pg/backup/backup_pg-meta_20250713.tar.lz4 | unlz4 -d -c | tar -xC /tmp/data

逻辑备份

您也可以使用 pg_dump 命令执行逻辑备份。

逻辑备份不能用于 PITR(时间点恢复),但对于在不同主版本之间迁移数据或实现灵活的数据导出逻辑非常有用。

从仓库引导

假设您有一个现有集群 pg-meta,想要将其克隆pg-meta2

您需要创建新的 pg-meta2 集群分支,然后在其上运行 pitr

7.4 - 管理命令

管理备份仓库和备份

启用备份

如果数据库集群创建时 pgbackrest_enabled 设置为 true,备份将自动启用。

如果创建时该值为 false,您可以使用以下命令启用 pgbackrest 组件:

./pgsql.yml -t pg_backup    # 运行 pgbackrest 子任务

删除备份

当移除主实例(pg_role = primary)时,Pigsty 会删除 pgbackrest 备份 stanza。

./pgsql-rm.yml
./pgsql-rm.yml -e pg_rm_backup=false   # 保留备份
./pgsql-rm.yml -t pg_backup            # 仅删除备份

使用 pg_backup 子任务仅删除备份,使用 pg_rm_backup 参数(设为 false)保留备份。

如果您的备份仓库被锁定(例如 S3 / MinIO 有锁定选项),此操作将失败。


列出备份

此命令将列出 pgbackrest 仓库中的所有备份(所有集群共享)

pgbackrest info

手动备份

Pigsty 提供了内置脚本 /pg/bin/pg-backup,封装了 pgbackrest 备份命令。

pg-backup        # 执行增量备份
pg-backup full   # 执行全量备份
pg-backup incr   # 执行增量备份
pg-backup diff   # 执行差异备份

基础备份

Pigsty 提供了一个替代备份脚本 /pg/bin/pg-basebackup,它不依赖 pgbackrest,直接提供数据库集群的物理副本。 默认备份目录为 /pg/backup

NAME
  pg-basebackup  -- make base backup from PostgreSQL instance

SYNOPSIS
  pg-basebackup -sdfeukr
  pg-basebackup --src postgres:/// --dst . --file backup.tar.lz4

DESCRIPTION
-s, --src, --url     备份源 URL,可选,默认为 "postgres:///",如需密码应在 url、ENV 或 .pgpass 中提供
-d, --dst, --dir     备份文件存放位置,默认为 "/pg/backup"
-f, --file           覆盖默认备份文件名,"backup_${tag}_${date}.tar.lz4"
-r, --remove         删除 n 分钟前的 .lz4 文件,默认 1200(20小时)
-t, --tag            备份文件标签,未设置时使用目标集群名或本地 IP 地址,也用于默认文件名
-k, --key            指定 --encrypt 时的加密密钥,默认密钥为 ${tag}
-u, --upload         上传备份文件到云存储(需自行实现)
-e, --encryption     使用 OpenSSL RC4 加密,未指定密钥时使用 tag 作为密钥
-h, --help           打印此帮助信息
postgres@pg-meta-1:~$ pg-basebackup
[2025-07-13 06:16:05][INFO] ================================================================
[2025-07-13 06:16:05][INFO] [INIT] pg-basebackup begin, checking parameters
[2025-07-13 06:16:05][DEBUG] [INIT] filename  (-f)    :   backup_pg-meta_20250713.tar.lz4
[2025-07-13 06:16:05][DEBUG] [INIT] src       (-s)    :   postgres:///
[2025-07-13 06:16:05][DEBUG] [INIT] dst       (-d)    :   /pg/backup
[2025-07-13 06:16:05][INFO] [LOCK] lock acquired success on /tmp/backup.lock, pid=107417
[2025-07-13 06:16:05][INFO] [BKUP] backup begin, from postgres:/// to /pg/backup/backup_pg-meta_20250713.tar.lz4
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/7000028 on timeline 1
pg_basebackup: write-ahead log end point: 0/7000FD8
pg_basebackup: syncing data to disk ...
pg_basebackup: base backup completed
[2025-07-13 06:16:06][INFO] [BKUP] backup complete!
[2025-07-13 06:16:06][INFO] [DONE] backup procedure complete!
[2025-07-13 06:16:06][INFO] ================================================================

备份使用 lz4 压缩。您可以使用以下命令解压并提取 tarball:

mkdir -p /tmp/data   # 将备份提取到此目录
cat /pg/backup/backup_pg-meta_20250713.tar.lz4 | unlz4 -d -c | tar -xC /tmp/data

逻辑备份

您也可以使用 pg_dump 命令执行逻辑备份。

逻辑备份不能用于 PITR(时间点恢复),但对于在不同主版本之间迁移数据或实现灵活的数据导出逻辑非常有用。


从仓库引导

假设您有一个现有集群 pg-meta,想要将其克隆pg-meta2

您需要创建新的 pg-meta2 集群分支,然后在其上运行 pitr

7.5 - 恢复操作

从备份恢复 PostgreSQL

您可以使用预配置的 pgbackrest 在 Pigsty 中执行时间点恢复(PITR)。


快速上手

如果您想将 pg-meta 集群回滚到之前的时间点,添加 pg_pitr 参数:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta2
    pg_pitr: { time: '2025-07-13 10:00:00+00' }  # 从最新备份恢复

然后运行 pgsql-pitr.yml 剧本,它将把 pg-meta 集群回滚到指定时间点。

./pgsql-pitr.yml -l pg-meta

恢复后处理

恢复后的集群会禁用 archive_mode,以防止意外的 WAL 写入。 如果恢复后的数据库状态正常,您可以启用 archive_mode 并执行全量备份。

psql -c 'ALTER SYSTEM RESET archive_mode; SELECT pg_reload_conf();'
pg-backup full    # 执行新的全量备份

恢复目标

您可以在 pg_pitr 中指定不同类型的恢复目标,但它们是互斥的:

  • time:恢复到哪个时间点?
  • name:恢复到命名的恢复点(由 pg_create_restore_point 创建)
  • xid:恢复到特定的事务 ID(TXID/XID)
  • lsn:恢复到特定的 LSN(日志序列号)点

如果指定了上述任何参数,恢复 类型 会相应设置, 否则将设置为 latest(WAL 归档流的末尾)。 特殊的 immediate 类型可用于指示 pgbackrest 通过在第一个一致点停止来最小化恢复时间。

目标类型

pg_pitr: { }  # 恢复到最新状态(WAL 归档流末尾)
pg_pitr: { time: "2025-07-13 10:00:00+00" }
pg_pitr: { lsn: "0/4001C80" }
pg_pitr: { xid: "250000" }
pg_pitr: { name: "some_restore_point" }
pg_pitr: { type: "immediate" }

按时间恢复

最常用的目标是时间点;您可以指定要恢复到的时间点:

./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": { "time": "2025-12-27 15:50:00+00" }}'

时间应该是有效的 PostgreSQL TIMESTAMP 格式,建议使用 YYYY-MM-DD HH:MM:SS+TZ

按名称恢复

您可以使用 pg_create_restore_point 创建命名恢复点:

SELECT pg_create_restore_point('shit_incoming');

然后在 PITR 中使用该命名恢复点:

./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": { "name": "shit_incoming" }}'

按 XID 恢复

如果您有一个事务意外删除了某些数据,最好的恢复方式是将数据库恢复到该事务之前的状态。

./pgsql-pitr.yml -e '{"pg_pitr": { "xid": "250000", exclusive: true }}'

您可以从监控仪表盘找到确切的事务 ID,或从 CSVLOG 中的 TXID 字段获取。

按 LSN 恢复

PostgreSQL 使用 LSN(日志序列号)来标识 WAL 记录的位置。 您可以在很多地方找到它,比如 Pigsty 仪表盘的 PG LSN 面板。

./pgsql-pitr.yml -e '{"pg_pitr": { "lsn": "0/4001C80", timeline: "1" }}'

要恢复到 WAL 流中的确切位置,您还可以指定 timeline 参数(默认为 latest


恢复来源

  • cluster:从哪个集群恢复?默认使用当前的 pg_cluster,您可以使用同一 pgbackrest 仓库中的任何其他集群
  • repo:覆盖备份仓库,使用与 pgbackrest_repo 相同的格式
  • set:默认使用 latest 备份集,但您可以通过标签指定特定的 pgbackrest 备份

Pigsty 将从 pgbackrest 备份仓库恢复。如果您使用集中式备份仓库(如 MinIO/S3), 可以指定另一个 “stanza”(另一个集群的备份目录)作为恢复来源。

pg-meta2:
  hosts: { 10.10.10.11: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta2
    pg_pitr: { cluster: pg-meta }  # 从 pg-meta 集群备份恢复

上述配置将标记 PITR 过程使用 pg-meta stanza。 您也可以通过 CLI 参数传递 pg_pitr 参数:

./pgsql-pitr.yml -l pg-meta2 -e '{"pg_pitr": { "cluster": "pg-meta" }}'

从另一个集群 PITR 时也可以使用这些目标:

./pgsql-pitr.yml -l pg-meta2 -e '{"pg_pitr": { "cluster": "pg-meta", "time": "2025-07-14 08:00:00+00" }}'

分步执行

这种方式是半自动的,您将参与 PITR 过程以做出关键决策。

例如,此配置将把 pg-meta 集群本身恢复到指定时间点:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta2
    pg_pitr: { time: '2025-07-13 10:00:00+00' }  # 从最新备份恢复

让我们逐步执行:

./pgsql-pitr.yml -l pg-meta -t down     # 暂停 patroni 高可用
./pgsql-pitr.yml -l pg-meta -t pitr     # 运行 pitr 过程
./pgsql-pitr.yml -l pg-meta -t up       # 生成 pgbackrest 配置和恢复脚本
# down                 : # 停止高可用并关闭 patroni 和 postgres
#   - pause            : # 暂停 patroni 自动故障切换
#   - stop             : # 停止 patroni 和 postgres 服务
#     - stop_patroni   : # 停止 patroni 服务
#     - stop_postgres  : # 停止 postgres 服务
# pitr                 : # 执行 PITR 过程
#   - config           : # 生成 pgbackrest 配置和恢复脚本
#   - restore          : # 运行 pgbackrest 恢复命令
#   - recovery         : # 启动 postgres 并完成恢复
#   - verify           : # 验证恢复后的集群控制数据
# up:                  : # 启动 postgres / patroni 并恢复高可用
#   - etcd             : # 启动前清理 etcd 元数据
#   - start            : # 启动 patroni 和 postgres 服务
#     - start_postgres : # 启动 postgres 服务
#     - start_patroni  : # 启动 patroni 服务
#   - resume           : # 恢复 patroni 自动故障切换

PITR 参数定义

pg_pitr 参数还有更多可用选项:

pg_pitr:                           # 定义 PITR 任务
    cluster: "some_pg_cls_name"    # 源集群名称
    type: default                   # 恢复目标类型:time, xid, name, lsn, immediate, default
    time: "2025-01-01 10:00:00+00" # 恢复目标:时间,与 xid, name, lsn 互斥
    name: "some_restore_point"     # 恢复目标:命名恢复点,与 time, xid, lsn 互斥
    xid:  "100000"                 # 恢复目标:事务 ID,与 time, name, lsn 互斥
    lsn:  "0/3000000"              # 恢复目标:日志序列号,与 time, name, xid 互斥
    timeline: latest               # 目标时间线,可以是整数,默认为 latest
    exclusive: false               # 是否排除目标点,默认为 false
    action: pause                  # 恢复后操作:pause, promote, shutdown
    archive: false                 # 是否保留归档设置?默认为 false
    db_exclude: [ template0, template1 ]
    db_include: []
    link_map:
      pg_wal: '/data/wal'
      pg_xact: '/data/pg_xact'
    process: 4                     # 并行恢复进程数
    repo: {}                       # 恢复来源仓库
    data: /pg/data                 # 数据恢复位置
    port: 5432                     # 恢复实例的监听端口

7.6 - 克隆数据库集群

如何利用 PITR 创建一个新的 PostgreSQL 集群,并恢复到指定时间点?

快速上手

  • 利用 Standby Cluster 创建现有集群的在线副本
  • 利用 PITR 创建现有集群的时间点快照
  • 在 PITR 完成后进行善后,确保新集群的备份流程正常运行

您可以使用 PG PITR 机制克隆整个数据库集群。

重置一个集群的状态

您也可以考虑创建一个全新的空集群,然后利用 PITR,将其重置为 pg-meta 集群的特定状态。

利用这种技术,您可以将现有集群 pg-meta 的任意时间点(备份保留期内)状态克隆到一个新的集群中。

我们依然以 Pigsty 4 节点沙箱环境为例,使用以下命令将 pg-test 集群重置为 pg-meta 集群的最新状态:

./pgsql-pitr.yml -l pg-test -e '{"pg_pitr": { "cluster": "pg-meta" }}'

PITR 善后工作

当你使用 PITR 恢复一个集群后,这个新集群本身的 PITR 功能是被禁用的。 因为如果它也尝试去生成备份,归档 WAL,有可能会写脏数据之前集群的备份仓库。

因此,当你确认这个 PITR 恢复出来的新集群状态符合预期后,你需要执行以下善后工作。

  • 升级备份仓库 Stanza,允许它接纳来自不同集群的新备份(仅当从别的集群恢复时)。
  • 启用 archive_mode,允许新集群归档 WAL 日志(需要重启集群)
  • 执行一个新的全量备份,确保新集群的数据被纳入(可选,也可以等 crontab 定时执行)
pb stanza-upgrade
psql -c 'ALTER SYSTEM RESET archive_mode;'
pg-backup full

通过这些操作,你的新集群将从第一次全量备份开始时,拥有自己的备份历史。 如果你跳过这些步骤,新集群本身的备份将无法进行,WAL 归档也不会生效。 意味着你将无法对新集群执行任何备份或 PITR 操作。

不善后的后果

假设您在 pg-test 集群上执行了 PITR 恢复,使用了另外一个集群 pg-meta 的数据,但没有进行善后工作。

那么在下一次例行备份的时候,你会看到下面的错误:

postgres@pg-test-1:~$ pb backup
2025-12-27 10:20:29.336 P00   INFO: backup command begin 2.57.0: --annotation=pg_cluster=pg-test --compress-type=lz4 --delta --exec-id=21034-171fb30b --expire-auto --log-level-console=info --log-level-file=info --log-path=/pg/log/pgbackrest --pg1-path=/pg/data --pg1-port=5432 --repo1-block --repo1-bundle --repo1-bundle-limit=20MiB --repo1-bundle-size=128MiB --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=/pgbackrest --repo1-retention-full=14 --repo1-retention-full-type=time --repo1-s3-bucket=pgsql --repo1-s3-endpoint=sss.pigsty --repo1-s3-key=<redacted> --repo1-s3-key-secret=<redacted> --repo1-s3-region=us-east-1 --repo1-s3-uri-style=path --repo1-storage-ca-file=/etc/pki/ca.crt --repo1-storage-port=9000 --repo1-type=s3 --stanza=pg-test --start-fast
2025-12-27 10:20:29.357 P00  ERROR: [051]: PostgreSQL version 18, system-id 7588470953413201282 do not match stanza version 18, system-id 7588470974940466058
                                    HINT: is this the correct stanza?
2025-12-27 10:20:29.357 P00   INFO: backup command end: aborted with exception [051]
postgres@pg-test-1:~$

WAL 日志归档被 pgBackrest 关闭了,因此也不会有 WAL 归档。

克隆一个新集群

例如,假设您有一个集群 pg-meta,现在你想要从 pg-meta 克隆一个 pg-meta2 的新集群。

您可以考虑使用 备份集群 的方式创建一个新的集群 pg-meta2

pgBackrest 支持增量备份/还原,因此如果您已经通过物理复制拉取了 pg-meta 的数据,通常增量 PITR 还原会非常快。


pb stop --force
pb stanza-delete --force
pb start
pb stanza-create
./pgsql-rm.yml -t pg_backup -l pg-test -e pg_rm_backup=true
./pgsql.yml    -t pg_backup -l pg-test

如果您想要将 pg-test 集群重置为 pg-meta 集群在 2025 年 12 月 26 日 15:30 的状态,可以使用以下命令:

./pgsql-pitr.yml -l pg-test -e '{"pg_pitr": { "cluster": "pg-meta", "time": "2025-12-27 17:50:00+08" ,archive: true }}'

当然,您也可以直接创建一个全新的集群,然后使用 pgsql-pitr.yml 剧本从 pg-meta 恢复数据到新集群 pg-meta2 并顶替新集群的数据目录。

使用这种技术,您不仅可以克隆 pg-meta 集群的最新状态,还可以克隆到任意时间点,例如:

8 - 数据迁移

如何将现有的 PostgreSQL 集群以最小的停机时间迁移至新的、由Pigsty管理的 PostgreSQL 集群?

Pigsty 内置了一个剧本 pgsql-migration.yml ,基于逻辑复制来实现在线数据库迁移。

通过预生成的自动化脚本,应用停机时间可以缩减到几秒内。但请注意,逻辑复制需要 PostgreSQL 10 以上的版本才能工作。

当然如果您有充足的停机时间预算,那么总是可以使用 pg_dump | psql 的方式进行停机迁移。


定义迁移任务

想要使用Pigsty提供的在线迁移剧本,您需要创建一个定义文件,来描述迁移任务的细节。

请查看任务定义文件示例作为参考: files/migration/pg-meta.yml

这个迁移任务要将 pg-meta.meta 在线迁移到 pg-test.test,前者称为 源集群(SRC), 后者称为 宿集群(DST)

pg-meta-1	10.10.10.10  --> pg-test-1	10.10.10.11 (10.10.10.12,10.10.10.13)

基于逻辑复制的迁移以数据库为单位,您需要指定需要迁移的数据库名称,以及数据库源宿集群主节点的 IP 地址,以及超级用户的连接信息。

---
#-----------------------------------------------------------------
# PG_MIGRATION
#-----------------------------------------------------------------
context_dir: ~/migration  # 迁移手册 & 脚本的放置目录
#-----------------------------------------------------------------
# SRC Cluster (旧集群)
#-----------------------------------------------------------------
src_cls: pg-meta      # 源集群名称                  <必填>
src_db: meta          # 源数据库名称                <必填>
src_ip: 10.10.10.10   # 源集群主 IP                <必填>
#src_pg: ''            # 如果定义,使用此作为源 dbsu pgurl 代替:
#                      # postgres://{{ pg_admin_username }}@{{ src_ip }}/{{ src_db }}
#                      # 例如: 'postgres://dbuser_dba:DBUser.DBA@10.10.10.10:5432/meta'
#sub_conn: ''          # 如果定义,使用此作为订阅连接字符串代替:
#                      # host={{ src_ip }} dbname={{ src_db }} user={{ pg_replication_username }}'
#                      # 例如: 'host=10.10.10.10 dbname=meta user=replicator password=DBUser.Replicator'
#-----------------------------------------------------------------
# DST Cluster (新集群)
#-----------------------------------------------------------------
dst_cls: pg-test      # 宿集群名称                  <必填>
dst_db: test          # 宿数据库名称                 <必填>
dst_ip: 10.10.10.11   # 宿集群主 IP                <必填>
#dst_pg: ''            # 如果定义,使用此作为目标 dbsu pgurl 代替:
#                      # postgres://{{ pg_admin_username }}@{{ dst_ip }}/{{ dst_db }}
#                      # 例如: 'postgres://dbuser_dba:DBUser.DBA@10.10.10.11:5432/test'
#-----------------------------------------------------------------
# PGSQL
#-----------------------------------------------------------------
pg_dbsu: postgres
pg_replication_username: replicator
pg_replication_password: DBUser.Replicator
pg_admin_username: dbuser_dba
pg_admin_password: DBUser.DBA
pg_monitor_username: dbuser_monitor
pg_monitor_password: DBUser.Monitor
#-----------------------------------------------------------------
...

默认情况下,源宿集群两侧的超级用户连接串会使用全局的管理员用户和各自主库的 IP 地址拼接而成,但您总是可以通过 src_pgdst_pg 参数来覆盖这些默认值。 同理,您也可以通过 sub_conn 参数来覆盖订阅连接串的默认值。


生成迁移计划

此剧本不会主动完成集群的迁移工作,但它会生成迁移所需的操作手册与自动化脚本。

默认情况下,你会在 ~/migration/pg-meta.meta 下找到迁移上下文目录。 按照 README.md 的说明,依次执行这些脚本,你就可以完成数据库迁移了!

# 激活迁移上下文:启用相关环境变量
. ~/migration/pg-meta.meta/activate

# 这些脚本用于检查 src 集群状态,并帮助在 pigsty 中生成新的集群定义
./check-user     # 检查 src 用户
./check-db       # 检查 src 数据库
./check-hba      # 检查 src hba 规则
./check-repl     # 检查 src 复制身份
./check-misc     # 检查 src 特殊对象

# 这些脚本用于在现有的 src 集群和由 pigsty 管理的 dst 集群之间建立逻辑复制,除序列外的数据将实时同步
./copy-schema    # 将模式复制到目标
./create-pub     # 在 src 上创建发布
./create-sub     # 在 dst 上创建订阅
./copy-progress  # 打印逻辑复制进度
./copy-diff      # 通过计数表快速比较 src 和 dst 的差异

# 这些脚本将在线迁移中运行,该迁移将停止 src 集群,复制序列号(逻辑复制不复制序列号!)
./copy-seq [n]   # 同步序列号,如果给出了 n,则会应用额外的偏移

# 你必须根据你的访问方式(dns,vip,haproxy,pgbouncer等),将应用流量切换至新的集群!
#./disable-src   # 将 src 集群访问限制为管理节点和新集群(你的实现)
#./re-routing    # 从 SRC 到 DST 重新路由应用流量!(你的实现)

# 然后进行清理以删除订阅和发布
./drop-sub       # 迁移后在 dst 上删除订阅
./drop-pub       # 迁移后在 src 上删除发布

注意事项

如果担心拷贝序列号时出现主键冲突,您可以在拷贝时将所有序列号向前推进一段距离,例如 +1000 ,你可以使用 ./copy-seq 加一个参数 1000 来实现这一点。

你必须实现自己的 ./re-routing 脚本,以将你的应用流量从 src 路由到 dst。 因为我们不知道你的流量是如何路由的(例如 dns, VIP, haproxy 或 pgbouncer)。 当然,您也可以手动完成这项操作…

你可以实现一个 ./disable-src 脚本来限制应用对 src 集群的访问,这是可选的:如果你能确保所有应用流量都在 ./re-routing 中干净利落地切完,其实不用这一步。

但如果您有未知来源的各种访问无法梳理干净,那么最好使用更为彻底的方式:更改 HBA 规则并重新加载来实现(推荐),或者只是简单粗暴地关停源主库上的 postgres、pgbouncer 或 haproxy 进程。

9 - 任务教程

如何去完成单个任务。每个任务页面是一般通过给出若干步骤展示如何执行完成某事。

9.1 - 故障排查

常见故障与分析排查思路

本文档列举了 PostgreSQL 和 Pigsty 中可能出现的故障,以及定位、处理、分析问题的 SOP。


磁盘空间写满

磁盘空间写满是最常见的故障类型。

现象

当数据库所在磁盘空间耗尽时,PostgreSQL 将无法正常工作,可能出现以下现象:数据库日志反复报错"no space left on device"(磁盘空间不足), 新数据无法写入,甚至 PostgreSQL 可能触发 PANIC 强制关闭。

Pigsty 带有 NodeFsSpaceFull 告警规则,当文件系统可用空间不足 10% 时触发告警。 使用监控系统 NODE Instance 面板查阅 FS 指标面板定位问题。

诊断

您也可以登录数据库节点,使用 df -h 查看各挂载盘符使用率,确定哪个分区被写满。 对于数据库节点,重点检查以下目录及其大小,以判断是哪个类别的文件占满了空间:

  • 数据目录/pg/data/base):存放表和索引的数据文件,大量写入与临时文件需要关注
  • WAL目录(如 pg/data/pg_wal):存放 PG WAL,WAL 堆积/复制槽保留是常见的磁盘写满原因。
  • 数据库日志目录(如 pg/log):如果 PG 日志未及时轮转写大量报错写入,也可能占用大量空间。
  • 本地备份目录(如 data/backups):使用 pgBackRest 等在本机保存备份时,也有可能撑满磁盘。

如果问题出在 Pigsty 管理节点或监控节点,还需考虑:

  • 监控数据:VictoriaMetrics 的时序指标和 VictoriaLogs 日志存储都会占用磁盘,可检查保留策略。
  • 对象存储数据:Pigsty 集成的 MinIO 对象存储可能会被用于 PG 备份保存。

明确占用空间最大的目录后,可进一步使用 du -sh <目录> 深入查找特定大型文件或子目录。

处理

磁盘写满属于紧急问题,需立即采取措施释放空间并保证数据库继续运行。 当数据盘并未与系统盘区分时,写满磁盘可能导致 Shell 命令无法执行。这种情况下,可以删除 /pg/dummy 占位文件,释放少量应急空间以便 shell 命令恢复正常。 如果数据库由于 pg_wal 写满已经宕机,清理空间后需要重启数据库服务并仔细检查数据完整性。


事务号回卷

PostgreSQL 循环使用 32 位事务ID (XID),耗尽时会出现"事务号回卷"故障(XID Wraparound)。

现象

第一阶段的典型征兆是 PGSQL Persist - Age Usage 面板年龄饱和度进入警告区域。 数据库日志开始出现:WARNING: database "postgres" must be vacuumed within xxxxxxxx transactions 字样的信息。

若问题持续恶化,PostgreSQL 会进入保护模式:当剩余事务ID不到约100万时数据库切换为只读模式;达到上限约21亿(2^31)时则拒绝任何新事务并迫使服务器停机以避免数据错误。

诊断

PostgreSQL 与 Pigsty 默认启用自动垃圾回收(AutoVacuum),因此此类故障出现通常有更深层次的根因。 常见的原因包括:超长事务(SAGE),Autovacuum 配置失当,复制槽阻塞,资源不足,存储引擎/扩展BUG,磁盘坏块。

首先定位年龄最大的数据库,然后可通过 Pigsty PGCAT Database - Tables 面板来确认表的年龄分布。 同时查阅数据库错误日志,通常可以找到定位根因的线索。

处理

  1. 立即冻结老事务:如果数据库尚未进入只读保护状态,立刻对受影响的库执行一次手动 VACUUM FREEZE。可以从老化最严重的表开始逐个冻结,而不是整库一起做,以加快效果。使用超级用户连接数据库,针对识别出的 relfrozenxid 最大的表运行 VACUUM FREEZE 表名;,优先冻结那些XID年龄最大的表元组。这样可以迅速回收大量事务ID空间。
  2. 单用户模式救援:如果数据库已经拒绝写入或宕机保护,此时需要启动数据库到单用户模式执行冻结操作。在单用户模式下运行 VACUUM FREEZE database_name; 对整个数据库进行冻结清理。完成后再以多用户模式重启数据库。这样做可以解除回卷锁定,让数据库重新可写。需要注意在单用户模式下操作要非常谨慎,并确保有足够的事务ID余量完成冻结。
  3. 备用节点接管:在某些复杂场景(例如遭遇硬件问题导致 vacuum 无法完成),可考虑提升集群中的只读备节点为主,以获取一个相对干净的环境来处理冻结。例如主库因坏块导致无法 vacuum,此时可以手动Failover提升备库为新的主库,再对其进行紧急 vacuum freeze。确保新主库已冻结老事务后,再将负载切回来。

连接耗尽

PostgreSQL 有一个最大连接数配置 (max_connections),当客户端连接数超过此上限时,新的连接请求将被拒绝。典型现象是在应用端看到数据库无法连接,并报出类似 FATAL: remaining connection slots are reserved for non-replication superuser connectionstoo many clients already 的错误。 这表示普通连接数已用完,仅剩下保留给超管或复制的槽位

诊断

连接耗尽通常由客户端大量并发请求引起。您可以通过 PGCAT Instance / PGCAT Database / PGCAT Locks 直接查阅数据库当前的活跃会话。 并判断是什么样的查询填满了系统,并进行进一步的处理。特别需要关注是否存在大量 Idle in Transaction 状态的连接以及长时间运行的事务(以及慢查询)。

处理

杀查询:对于已经耗尽导致业务受阻的情况,通常立即使用 pg_terminate_backend(pid) 进行紧急降压。 对于使用连接池的情况,则可以调整连接池大小参数,并执行 reload 重载的方式减少数据库层面的连接数量。

您也可以修改 max_connections 参数为更大的值,但本参数需要重启数据库后才能生效。


etcd 配额写满

etcd 配额写满将导致 PG 高可用控制面失效,无法进行配置变更。

诊断

Pigsty 在实现高可用时使用 etcd 作为分布式配置存储(DCS),etcd 自身有一个存储配额(默认约为2GB)。 当 etcd 存储用量达到配额上限时,etcd 将拒绝写入操作,报错 “etcdserver: mvcc: database space exceeded"。在这种情况下,Patroni 无法向 etcd 写入心跳或更新配置,从而导致集群管理功能失效。

解决

在 Pigsty v2.0.0 - v2.5.1 之间的版本默认受此问题影响。Pigsty v2.6.0 为部署的 etcd 新增了自动压实的配置项,如果您仅将其用于 PG 高可用租约,则常规用例下不会再有此问题。


有缺陷的存储引擎

目前,TimescaleDB 的试验性存储引擎 Hypercore 被证实存在缺陷,已经出现 VACUUM 无法回收出现 XID 回卷故障的案例。 请使用该功能的用户及时迁移至 PostgreSQL 原生表或者 TimescaleDB 默认引擎

详细介绍:《PG新存储引擎故障案例

9.2 - 误删处理

处理误删数据,误删表,误删数据库

误删数据

如果是小批量 DELETE 误操作,可以考虑使用 pg_surgery 或者 pg_dirtyread 扩展进行原地手术恢复。

-- 立即关闭此表上的 Auto Vacuum 并中止 Auto Vacuum 本表的 worker 进程
ALTER TABLE public.some_table SET (autovacuum_enabled = off, toast.autovacuum_enabled = off);

CREATE EXTENSION pg_dirtyread;
SELECT * FROM pg_dirtyread('tablename') AS t(col1 type1, col2 type2, ...);

如果被删除的数据已经被 VACUUM 回收,那么使用通用的误删处理流程。

误删对象

当出现 DROP/DELETE 类误操作,通常按照以下流程决定恢复方案。

  1. 确认此数据是否可以通过业务系统或其他数据系统找回,如果可以,直接从业务侧修复。
  2. 确认是否有延迟从库,如果有,推进延迟从库至误删时间点,查询出来恢复。
  3. 如果数据已经确认删除,确认备份信息,恢复范围是否覆盖误删时间点,如果覆盖,开始 PITR
  4. 确认是整集群原地 PITR 回滚,还是新开服务器重放,还是用从库来重放,并执行恢复策略

误删集群

如果出现整个数据库集群通过 Pigsty 管理命令被误删的情况,例如错误的执行 pgsql-rm.yml 剧本或 bin/pgsql-rm 命令。 除非您指定了 pg_rm_backup 参数为 false,否则备份会与数据库集群一起被删除。

警告:在这种情况,您的数据将无法找回!请务必三思而后行!

建议:对于生产环境,您可以在配置清单中全局配置此参数为 false,在移除集群时保留备份。

9.3 - 手工恢复

在沙箱环境中按照提示脚本手动执行 PITR

您可以使用 pgsql-pitr.yml 剧本执行 PITR,但在某些情况下,您可能希望手动执行 PITR,直接使用 pgbackrest 原语实现精细的控制。 我们将使用带有 MinIO 备份仓库的 四节点沙箱 集群来演示该过程。

pigsty-sandbox


初始化沙箱

使用 vagrantterraform 准备四节点沙箱环境,然后:

curl https://repo.pigsty.io/get | bash; cd ~/pigsty/
./configure -c full
./install

现在以管理节点上的管理员用户(或 dbsu)身份操作。


检查备份

要检查备份状态,您需要切换到 postgres 用户并使用 pb 命令:

sudo su - postgres    # 切换到 dbsu: postgres 用户
pb info               # 打印 pgbackrest 备份信息

pbpgbackrest 的别名,会自动从 pgbackrest 配置中获取 stanza 名称。

function pb() {
    local stanza=$(grep -o '\[[^][]*]' /etc/pgbackrest/pgbackrest.conf | head -n1 | sed 's/.*\[\([^]]*\)].*/\1/')
    pgbackrest --stanza=$stanza $@
}

您可以看到初始备份信息,这是一个全量备份:

root@pg-meta-1:~# pb info
stanza: pg-meta
    status: ok
    cipher: aes-256-cbc

    db (current)
        wal archive min/max (17): 000000010000000000000001/000000010000000000000007

        full backup: 20250713-022731F
            timestamp start/stop: 2025-07-13 02:27:31+00 / 2025-07-13 02:27:33+00
            wal start/stop: 000000010000000000000004 / 000000010000000000000004
            database size: 44MB, database backup size: 44MB
            repo1: backup size: 8.4MB

备份完成于 2025-07-13 02:27:33+00,这是您可以恢复到的最早时间。 由于 WAL 归档处于活动状态,您可以恢复到备份之后的任何时间点,直到 WAL 结束(即现在)。


生成心跳

您可以生成一些心跳来模拟工作负载。/pg-bin/pg-heartbeat 就是用于此目的的, 它每秒向 monitor.heartbeat 表写入一个心跳时间戳。

make rh     # 运行心跳: ssh 10.10.10.10 'sudo -iu postgres /pg/bin/pg-heartbeat'
ssh 10.10.10.10 'sudo -iu postgres /pg/bin/pg-heartbeat'
   cls   |              ts               |    lsn     |  lsn_int  | txid | status  |       now       |  elapse
---------+-------------------------------+------------+-----------+------+---------+-----------------+----------
 pg-meta | 2025-07-13 03:01:20.318234+00 | 0/115BF5C0 | 291239360 | 4812 | leading | 03:01:20.318234 | 00:00:00

您甚至可以向集群添加更多工作负载,让我们使用 pgbench 生成一些随机写入:

make ri     # 初始化 pgbench
make rw     # 运行 pgbench 读写工作负载
pgbench -is10 postgres://dbuser_meta:DBUser.Meta@10.10.10.10:5433/meta
while true; do pgbench -nv -P1 -c4 --rate=64 -T10 postgres://dbuser_meta:DBUser.Meta@10.10.10.10:5433/meta; done
while true; do pgbench -nv -P1 -c4 --rate=64 -T10 postgres://dbuser_meta:DBUser.Meta@10.10.10.10:5433/meta; done
pgbench (17.5 (Homebrew), server 17.4 (Ubuntu 17.4-1.pgdg24.04+2))
progress: 1.0 s, 60.9 tps, lat 7.295 ms stddev 4.219, 0 failed, lag 1.818 ms
progress: 2.0 s, 69.1 tps, lat 6.296 ms stddev 1.983, 0 failed, lag 1.397 ms
...

PITR 手册

现在让我们选择一个恢复时间点,比如 2025-07-13 03:03:03+00,这是初始备份(和心跳)之后的一个时间点。 要执行手动 PITR,使用 pg-pitr 工具:

$ pg-pitr -t "2025-07-13 03:03:00+00"

它会为您生成执行恢复的指令,通常需要四个步骤:

Perform time PITR on pg-meta
[1. Stop PostgreSQL] ===========================================
   1.1 Pause Patroni (if there are any replicas)
       $ pg pause <cls>  # 暂停 patroni 自动故障切换
   1.2 Shutdown Patroni
       $ pt-stop         # sudo systemctl stop patroni
   1.3 Shutdown Postgres
       $ pg-stop         # pg_ctl -D /pg/data stop -m fast

[2. Perform PITR] ===========================================
   2.1 Restore Backup
       $ pgbackrest --stanza=pg-meta --type=time --target='2025-07-13 03:03:00+00' restore
   2.2 Start PG to Replay WAL
       $ pg-start        # pg_ctl -D /pg/data start
   2.3 Validate and Promote
     - If database content is ok, promote it to finish recovery, otherwise goto 2.1
       $ pg-promote      # pg_ctl -D /pg/data promote
[3. Restore Primary] ===========================================
   3.1 Enable Archive Mode (Restart Required)
       $ psql -c 'ALTER SYSTEM SET archive_mode = on;'
   3.1 Restart Postgres to Apply Changes
       $ pg-restart      # pg_ctl -D /pg/data restart
   3.3 Restart Patroni
       $ pt-restart      # sudo systemctl restart patroni

[4. Restore Cluster] ===========================================
   4.1 Re-Init All [**REPLICAS**] (if any)
       - 4.1.1 option 1: restore replicas with same pgbackrest cmd (require central backup repo)
           $ pgbackrest --stanza=pg-meta --type=time --target='2025-07-13 03:03:00+00' restore
       - 4.1.2 option 2: nuke the replica data dir and restart patroni (may take long time to restore)
           $ rm -rf /pg/data/*; pt-restart
       - 4.1.3 option 3: reinit with patroni, which may fail if primary lsn < replica lsn
           $ pg reinit pg-meta
   4.2 Resume Patroni
       $ pg resume pg-meta
   4.3 Full Backup (optional)
       $ pg-backup full      # 建议在 PITR 后执行新的全量备份

单节点示例

让我们从简单的单节点 pg-meta 集群开始,作为一个更简单的示例。

关闭数据库

pt-stop         # sudo systemctl stop patroni,关闭 patroni(和 postgres)
# 可选,因为如果 patroni 未暂停,postgres 会被 patroni 关闭
$ pg_stop        # pg_ctl -D /pg/data stop -m fast,关闭 postgres

pg_ctl: PID file "/pg/data/postmaster.pid" does not exist
Is server running?

$ pg-ps           # 打印 postgres 相关进程

 UID         PID   PPID  C STIME TTY      STAT   TIME CMD
postgres  31048      1  0 02:27 ?        Ssl    0:19 /usr/sbin/pgbouncer /etc/pgbouncer/pgbouncer.ini
postgres  32026      1  0 02:28 ?        Ssl    0:03 /usr/bin/pg_exporter ...
postgres  35510  35480  0 03:01 pts/2    S+     0:00 /bin/bash /pg/bin/pg-heartbeat

确保本地 postgres 没有运行,然后执行手册中给出的恢复命令:

恢复备份

pgbackrest --stanza=pg-meta --type=time --target='2025-07-13 03:03:00+00' restore
postgres@pg-meta-1:~$ pgbackrest --stanza=pg-meta --type=time --target='2025-07-13 03:03:00+00' restore
2025-07-13 03:17:07.443 P00   INFO: restore command begin 2.54.2: ...
2025-07-13 03:17:07.470 P00   INFO: repo1: restore backup set 20250713-022731F, recovery will start at 2025-07-13 02:27:31
2025-07-13 03:17:07.471 P00   INFO: remove invalid files/links/paths from '/pg/data'
2025-07-13 03:17:08.523 P00   INFO: write updated /pg/data/postgresql.auto.conf
2025-07-13 03:17:08.527 P00   INFO: restore size = 44MB, file total = 1436
2025-07-13 03:17:08.527 P00   INFO: restore command end: completed successfully (1087ms)

验证数据

我们不希望 patroni HA 接管,直到确定数据正确,所以手动启动 postgres:

pg-start
waiting for server to start....2025-07-13 03:19:33.133 UTC [39294] LOG:  redirecting log output to logging collector process
2025-07-13 03:19:33.133 UTC [39294] HINT:  Future log output will appear in directory "/pg/log/postgres".
 done
server started

现在您可以检查数据,看看是否处于您想要的时间点。 您可以通过检查业务表中的最新时间戳来验证,或者在本例中通过心跳表检查。

postgres@pg-meta-1:~$ psql -c 'table monitor.heartbeat'
   id    |              ts               |    lsn    | txid
---------+-------------------------------+-----------+------
 pg-meta | 2025-07-13 03:02:59.214104+00 | 302005504 | 4912

时间戳正好在我们指定的时间点之前!(2025-07-13 03:03:00+00)。 如果这不是您想要的时间点,可以使用不同的时间点重复恢复。 由于恢复是以增量和并行方式执行的,速度非常快。 可以重试直到找到正确的时间点。

提升主库

恢复后的 postgres 集群处于 recovery 模式,因此在提升为主库之前会拒绝任何写操作。 这些恢复参数是由 pgBackRest 在配置文件中生成的。

postgres@pg-meta-1:~$ cat /pg/data/postgresql.auto.conf
# Do not edit this file or use ALTER SYSTEM manually!
# It is managed by Pigsty & Ansible automatically!

# Recovery settings generated by pgBackRest restore on 2025-07-13 03:17:08
archive_mode = 'off'
restore_command = 'pgbackrest --stanza=pg-meta archive-get %f "%p"'
recovery_target_time = '2025-07-13 03:03:00+00'

如果数据正确,您可以提升它为主库,将其标记为新的领导者并准备接受写入。

pg-promote
waiting for server to promote.... done
server promoted
psql -c 'SELECT pg_is_in_recovery()'   # 'f' 表示已提升为主库
 pg_is_in_recovery
-------------------
 f
(1 row)

恢复集群

最后,不仅需要恢复数据,还需要恢复集群状态,例如:

  • patroni 接管
  • 归档模式
  • 备份集
  • 从库

Patroni 接管

您的 postgres 是直接启动的,要恢复 HA 接管,您需要启动 patroni 服务:

pt-start   # sudo systemctl start patroni
pg resume pg-meta      # 恢复 patroni 自动故障切换(如果之前暂停过)

归档模式

archive_mode 在恢复期间被 pgbackrest 禁用。 如果您希望新领导者的写入归档到备份仓库,还需要启用 archive_mode 配置。

psql -c 'show archive_mode'

 archive_mode
--------------
 off
psql -c 'ALTER SYSTEM RESET archive_mode;'
psql -c 'SELECT pg_reload_conf();'
psql -c 'show archive_mode'
# 您也可以直接编辑 postgresql.auto.conf 并使用 pg_ctl 重载
sed -i '/archive_mode/d' /pg/data/postgresql.auto.conf
pg_ctl -D /pg/data reload

备份集

通常建议在 PITR 后执行新的全量备份,但这是可选的。

从库

如果您的 postgres 集群有从库,您也需要在每个从库上执行 PITR。 或者,更简单的方法是删除从库数据目录并重启 patroni,这将从主库重新初始化从库。 我们将在下一个多节点集群示例中介绍这种情况。


多节点示例

现在让我们以三节点 pg-test 集群作为 PITR 示例。

9.4 - 利用 xfs 实现实例 Fork

在同一台机器上克隆实例并执行时间点恢复

Pigsty 提供了两个实用脚本,用于在同一台机器上快速克隆实例并执行时间点恢复:

  • pg-fork:在同一台机器上快速克隆一个新的 PostgreSQL 实例
  • pg-pitr:使用 pgbackrest 手动执行时间点恢复

这两个脚本可以配合使用:先用 pg-fork 克隆实例,再用 pg-pitr 将克隆实例恢复到指定时间点。


pg-fork

pg-fork 可以在同一台机器上快速克隆一个新的 PostgreSQL 实例。

快速上手

使用 postgres 用户(dbsu)执行以下命令,即可创建一个新的实例:

pg-fork 1                         # 从 /pg/data 克隆到 /pg/data1,端口 15432
pg-fork 2 -d /pg/data1            # 从 /pg/data1 克隆到 /pg/data2,端口 25432
pg-fork 3 -D /tmp/test -P 5555    # 克隆到自定义目录和端口

克隆完成后,可以启动并访问新实例:

pg_ctl -D /pg/data1 start         # 启动克隆实例
psql -p 15432                     # 连接克隆实例

命令语法

pg-fork <FORK_ID> [options]

必填参数:

参数说明
<FORK_ID>克隆实例编号(1-9),决定默认端口和数据目录

可选参数:

参数说明默认值
-d, --data <datadir>源实例数据目录/pg/data$PG_DATA
-D, --dst <dst_dir>目标数据目录/pg/data<FORK_ID>
-p, --port <port>源实例端口5432$PG_PORT
-P, --dst-port <port>目标实例端口<FORK_ID>5432
-s, --skip跳过备份 API,使用冷拷贝模式-
-y, --yes跳过确认提示-
-h, --help显示帮助信息-

使用示例

# 从默认实例克隆到 /pg/data1,端口 15432
pg-fork 1

# 从默认实例克隆到 /pg/data2,端口 25432
pg-fork 2
# 从端口 5433 的实例克隆
pg-fork 1 -p 5433

# 使用环境变量指定源端口
PG_PORT=5433 pg-fork 1
# 从 /pg/data1 克隆到 /pg/data2
pg-fork 2 -d /pg/data1

# 从 /pg/data2 克隆到 /pg/data3
pg-fork 3 -d /pg/data2
# 克隆到自定义目录和端口
pg-fork 1 -D /tmp/pgtest -P 5555

# 完全自定义
pg-fork 1 -d /pg/data -D /mnt/backup/pgclone -P 6543
# 源实例已停止时使用冷拷贝
pg-fork 1 -s

# 跳过确认直接执行
pg-fork 1 -s -y

工作原理

pg-fork 支持两种工作模式:

热备份模式(默认,源实例运行中):

  1. 调用 pg_backup_start() 开始备份
  2. 使用 cp --reflink=auto 拷贝数据目录
  3. 调用 pg_backup_stop() 结束备份
  4. 修改配置文件,避免与源实例冲突

冷拷贝模式(使用 -s 参数或源实例未运行):

  1. 直接使用 cp --reflink=auto 拷贝数据目录
  2. 修改配置文件

克隆后配置

pg-fork 会自动修改克隆实例的以下配置:

配置项修改内容
port改为目标端口(避免冲突)
archive_mode设为 off(避免污染 WAL 归档)
log_directory设为 log(使用数据目录下的日志)
primary_conninfo移除(创建独立实例)
standby.signal移除(创建独立实例)
pg_replslot/*清空(避免复制槽冲突)

典型工作流

# 1. 克隆实例用于测试
pg-fork 1 -y

# 2. 启动克隆实例
pg_ctl -D /pg/data1 start

# 3. 在克隆实例上测试(不影响生产)
psql -p 15432 -c "DROP TABLE important_data;"  # 安全测试

# 4. 测试完成后清理
pg_ctl -D /pg/data1 stop
rm -rf /pg/data1

pg-pitr

pg-pitr 是一个用于手动执行时间点恢复的脚本,基于 pgbackrest。

快速上手

pg-pitr -d                                  # 恢复到最新状态
pg-pitr -i                                  # 恢复到备份完成时间
pg-pitr -t "2025-01-01 12:00:00+08"         # 恢复到指定时间点
pg-pitr -n my-savepoint                     # 恢复到命名恢复点
pg-pitr -l "0/7C82CB8"                      # 恢复到指定 LSN
pg-pitr -x 12345678 -X                      # 恢复到事务之前
pg-pitr -b 20251225-120000F                 # 恢复到指定备份集

命令语法

pg-pitr [options] [recovery_target]

恢复目标(选择一个):

参数说明
-d, --default恢复到 WAL 归档流末尾(最新状态)
-i, --immediate恢复到数据库一致性点(最快恢复)
-t, --time <timestamp>恢复到指定时间点
-n, --name <restore_point>恢复到命名恢复点
-l, --lsn <lsn>恢复到指定 LSN
-x, --xid <xid>恢复到指定事务 ID
-b, --backup <label>恢复到指定备份集

可选参数:

参数说明默认值
-D, --data <path>恢复目标数据目录/pg/data
-s, --stanza <name>pgbackrest stanza 名称自动检测
-X, --exclusive排除目标点(恢复到目标之前)-
-P, --promote恢复后自动提升(默认暂停)-
-c, --check干运行模式,仅打印命令-
-y, --yes跳过确认和倒计时-
-h, --help显示帮助信息-

恢复目标类型

# 恢复到 WAL 归档流末尾(最新状态)
pg-pitr -d

# 这是默认行为,会重放所有可用的 WAL
# 恢复到数据库一致性点
pg-pitr -i

# 最快的恢复方式,不重放额外的 WAL
# 适用于快速验证备份是否可用
# 恢复到指定时间点
pg-pitr -t "2025-01-01 12:00:00+08"

# 使用 UTC 时间
pg-pitr -t "2025-01-01 04:00:00+00"

# 时间格式:YYYY-MM-DD HH:MM:SS[.usec][+/-TZ]
# 恢复到命名恢复点
pg-pitr -n my-savepoint

# 恢复点需要事先使用 pg_create_restore_point() 创建
# SELECT pg_create_restore_point('my-savepoint');
# 恢复到指定 LSN
pg-pitr -l "0/7C82CB8"

# LSN 可以从监控面板或 pg_current_wal_lsn() 获取
# 恢复到指定事务 ID
pg-pitr -x 12345678

# 恢复到事务之前(不包含该事务)
pg-pitr -x 12345678 -X
# 恢复到指定备份集
pg-pitr -b 20251225-120000F

# 查看可用备份集
pgbackrest info

使用示例

恢复到指定时间点:

# 1. 停止 PostgreSQL
pg_ctl -D /pg/data stop -m fast

# 2. 执行 PITR
pg-pitr -t "2025-12-27 10:00:00+08"

# 3. 启动并验证
pg_ctl -D /pg/data start
psql -c "SELECT * FROM important_table;"

# 4. 确认无误后提升
pg_ctl -D /pg/data promote

# 5. 启用归档并执行新备份
psql -c "ALTER SYSTEM SET archive_mode = on;"
pg_ctl -D /pg/data restart
pg-backup full

恢复到克隆实例:

# 1. 克隆实例
pg-fork 1 -y

# 2. 在克隆实例上执行 PITR
pg-pitr -D /pg/data1 -t "2025-12-27 10:00:00+08"

# 3. 启动克隆实例验证
pg_ctl -D /pg/data1 start
psql -p 15432

干运行模式:

# 仅打印命令,不执行
pg-pitr -t "2025-12-27 10:00:00+08" -c

# 输出示例:
# Command:
#   pgbackrest --stanza=pg-meta --delta --force --type=time --target="2025-12-27 10:00:00+08" restore

恢复后处理

恢复完成后,实例会处于恢复暂停状态(除非使用 -P 参数)。您需要:

  1. 启动实例pg_ctl -D /pg/data start
  2. 验证数据:检查数据是否符合预期
  3. 提升实例pg_ctl -D /pg/data promote
  4. 启用归档psql -c "ALTER SYSTEM SET archive_mode = on;"
  5. 重启实例pg_ctl -D /pg/data restart
  6. 执行备份pg-backup full

组合使用

pg-forkpg-pitr 可以组合使用,实现安全的 PITR 验证流程:

# 1. 克隆当前实例
pg-fork 1 -y

# 2. 在克隆实例上执行 PITR(不影响生产)
pg-pitr -D /pg/data1 -t "2025-12-27 10:00:00+08"

# 3. 启动克隆实例
pg_ctl -D /pg/data1 start

# 4. 验证恢复结果
psql -p 15432 -c "SELECT count(*) FROM orders WHERE created_at < '2025-12-27 10:00:00';"

# 5. 确认无误后,可以选择:
#    - 方案A:在生产实例上执行相同的 PITR
#    - 方案B:将克隆实例提升为新的生产实例

# 6. 清理测试实例
pg_ctl -D /pg/data1 stop
rm -rf /pg/data1

注意事项

运行要求

  • 必须以 postgres 用户(或 postgres 组成员)执行
  • pg-pitr 执行前必须停止目标实例的 PostgreSQL
  • pg-fork 热备份模式需要源实例正在运行

文件系统

  • 推荐使用 XFS(启用 reflink)或 Btrfs 文件系统
  • CoW 文件系统上克隆几乎瞬间完成,且不占用额外空间
  • 非 CoW 文件系统会执行完整拷贝,耗时较长

端口规划

FORK_ID默认端口默认数据目录
115432/pg/data1
225432/pg/data2
335432/pg/data3
995432/pg/data9

安全建议

  • 克隆实例仅用于测试和验证,不应长期运行
  • 验证完成后及时清理克隆实例
  • 生产环境 PITR 建议使用 pgsql-pitr.yml 剧本
  • 重要操作前先使用 -c 干运行模式确认命令

原理剖析

有时候,您想要用现有的 PostgreSQL 实例在 同一台机器 上创建一个新的实例 (用于测试,PITR 恢复),可以使用 postgres 用户执行下面的命令:

psql <<EOF
CHECKPOINT;
SELECT pg_backup_start('pgfork', true);
\! rm -rf /pg/data2 && cp -r --reflink=auto /pg/data /pg/data2 && ls -alhd /pg/data2
SELECT * FROM pg_backup_stop(false);
EOF

# 修改配置,避免与现有实例冲突:端口,日志,归档等
sed -i 's/^port.*/port = 5431/' /pg/data2/postgresql.conf;
sed -i 's/^log_destination.*/log_destination = stderr/' /pg/data2/postgresql.conf;
sed -i 's/^archive_mode.*/archive_mode = off/' /pg/data2/postgresql.conf;
rm -rf /pg/data2/postmaster.pid /pg/data2/postmaster.opts
pg_ctl -D /pg/data2 start -l /pg/log/pgfork.log
pg_ctl -D /pg/data2 stop
psql -p 5431  # 访问新实例

上面的命令会创建一个新的数据目录 /pg/data2,它是现有数据目录 /pg/data 的一个完整拷贝。 如果您使用的是 XFS (启用了 reflink COW 特性),那么同磁盘拷贝目录会非常快,通常几百毫秒的常数时间内即可完成。

您在原地拉起新实例前,务必 修改 postgresql.conf 里的 port / archive_mode / log_destination 参数,避免影响现有生产实例等运行。 您可以使用一个没有被占用的端口,例如 5431,并将日志输出到 /pg/log/xxxx.log 避免写脏现有实例的日志文件。

我们建议同时修改 shared_buffers Pigsty 默认情况通常分配 25% 的系统内存给 PostgreSQL 实例, 开启新实例时,会与现有实例争夺内存资源。您可以适当调小,以减小对现有生产实例的影响。

9.5 - 为 PostgreSQL 集群启用 HugePage

为 PostgreSQL 集群启用大页,减少大内存实例的页表开销并提高性能

使用 node_hugepage_countnode_hugepage_ratio/pg/bin/pg-tune-hugepage

如果你计划启用大页(HugePage),请考虑使用 node_hugepage_countnode_hugepage_ratio,并配合 ./node.yml -t node_tune 进行应用。

大页对于数据库来说有利有弊,利是内存是专门管理的,不用担心被挪用,降低数据库 OOM 风险。缺点是某些场景下可能对性能由负面影响。

在 PostgreSQL 启动前,您需要分配 足够多的 大页,浪费的部分可以使用 pg-tune-hugepage 脚本对其进行回收,不过此脚本仅 PostgreSQL 15+ 可用。

如果你的 PostgreSQL 已经在运行,你可以使用下面的办法启动大页(仅 PG15+ 可用):

sync; echo 3 > /proc/sys/vm/drop_caches   # 刷盘,释放系统缓存(请做好数据库性能受到冲击的准备)
sudo /pg/bin/pg-tune-hugepage             # 将 nr_hugepages 写入 /etc/sysctl.d/hugepage.conf
pg restart <cls>                          # 重启 postgres 以使用 hugepage

9.6 - 3坏2应急处理

高可用典型场景处理预案:三节点坏了两个节点,高可用不生效了,怎么从紧急状态中恢复?

如果经典3节点高可用部署同时出现两台(多数主体)故障,系统通常无法自动完成故障切换,需要人工介入:

首先判断另外两台服务器的情况,如果短时间内可以拉起,优先选择拉起另外两台服务。否则进入 紧急止血流程

紧急止血流程假设您的管理节点故障,只有单台普通数据库节点存活,在这种情况下,最快的恢复操作流程为:

  • 调整 HAProxy 配置,将流量指向主库。
  • 关闭 Patroni,手动提升 PostgreSQL 从库为主库。

调整HAProxy配置

如果你通过其他方式绕开 HAProxy 访问集群,那么可以跳过这一步。 如果你通过 HAProxy 方式访问数据库集群,那么你需要调整负载均衡配置,将读写流量手工指向主库。

  • 编辑 /etc/haproxy/<pg_cluster>-primary.cfg 配置文件,其中 <pg_cluster> 为你的 PostgreSQL 集群名称,例如 pg-meta
  • 将健康检查配置选项注释,停止进行健康鉴擦好
  • 将服务器列表中,其他两台故障的机器注释掉,只保留当前主库服务器。
listen pg-meta-primary
    bind *:5433
    mode tcp
    maxconn 5000
    balance roundrobin

    # 注释掉以下四行健康检查配置
    #option httpchk                               # <---- remove this
    #option http-keep-alive                       # <---- remove this
    #http-check send meth OPTIONS uri /primary    # <---- remove this
    #http-check expect status 200                 # <---- remove this

    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    server pg-meta-1 10.10.10.10:6432 check port 8008 weight 100

    # 注释掉其他两台故障的机器
    #server pg-meta-2 10.10.10.11:6432 check port 8008 weight 100 <---- comment this
    #server pg-meta-3 10.10.10.12:6432 check port 8008 weight 100 <---- comment this

配置调整完成后,先不着急执行 systemctl reload haproxy 重载生效,等待后续主库提升后一起执行。 以上配置的效果是,HAProxy 将不再进行主库健康检查(默认使用 Patroni),而是直接将写入流量指向当前主库


手工提升备库

登陆目标服务器,切换至 dbsu 用户,执行 CHECKPOINT 刷盘后,关闭 Patroni,重启 PostgreSQL 并执行 Promote。

sudo su - postgres                     # 切换到数据库 dbsu 用户
psql -c 'checkpoint; checkpoint;'      # 两次 Checkpoint 刷脏页,避免PG后重启耗时过久
sudo systemctl stop patroni            # 关闭 Patroni
pg-restart                             # 重新拉起 PostgreSQL
pg-promote                             # 将 PostgreSQL 从库提升为主库
psql -c 'SELECT pg_is_in_recovery();'  # 如果结果为 f,表示已经提升为主库

如果你上面调整了 HAProxy 配置,那么现在可以执行 systemctl reload haproxy 重载 HAProxy 配置,将流量指向新的主库。

systemctl reload haproxy                # 重载 HAProxy 配置,将写入流量指向当前实例

避免脑裂

紧急止血后,第二优先级问题为:避免脑裂。用户应当防止另外两台服务器重新上线后,与当前主库形成脑裂,导致数据不一致。

简单的做法是:

  • 将另外两台服务器直接 断电/断网,确保它们不会在不受控的情况下再次上线。
  • 调整应用使用的数据库连接串,将其 HOST 直接指向唯一幸存服务器上的主库。

然后应当根据具体情况,决定下一步的操作:

  • A:这两台服务器是临时故障(比如断网断电),可以原地修复后继续服务
  • B:这两台故障服务器是永久故障(比如硬件损坏),将移除并下线。

临时故障后的复原

如果另外两台服务器是临时故障,可以修复后继续服务,那么可以按照以下步骤进行修复与重建:

  • 每次处理一台故障服务器,优先处理 管理节点 / INFRA 管理节点
  • 启动故障服务器,并在启动后关停 Patroni

ETCD 集群在法定人数恢复后,将恢复工作,此时可以启动幸存服务器(当前主库)上的 Patroni,接管现有 PostgreSQL,并重新获取集群领导者身份。 Patroni 启动后进入维护模式。

systemctl restart patroni
pg pause <pg_cluster>

在另外两台实例上以 postgres 用户身份创建 touch /pg/data/standby.signal 标记文件将其标记为从库,然后拉起 Patroni:

systemctl restart patroni

确认 Patroni 集群身份/角色正常后,退出维护模式:

pg resume <pg_cluster>

永久故障后的复原

出现永久故障后,首先需要恢复管理节点上的 ~/pigsty 目录,主要是需要 pigsty.ymlfiles/pki/ca/ca.key 两个核心文件。

如果您无法取回或没有备份这两个文件,您可以选择部署一套新的 Pigsty,并通过 备份集群 的方式将现有集群迁移至新部署中。

请定期备份 pigsty 目录(例如使用 Git 进行版本管理)。建议吸取教训,下次不要犯这样的错误。

配置修复

您可以将幸存的节点作为新的管理节点,将 ~/pigsty 目录拷贝到新的管理节点上,然后开始调整配置。 例如,将原本默认的管理节点 10.10.10.10 替换为幸存节点 10.10.10.12

all:
  vars:
    admin_ip: 10.10.10.12               # 使用新的管理节点地址
    node_etc_hosts: [10.10.10.12 h.pigsty a.pigsty p.pigsty g.pigsty sss.pigsty]
    infra_portal: {}                    # 一并修改其他引用旧管理节点 IP (10.10.10.10) 的配置

  children:

    infra:                              # 调整 Infra 集群
      hosts:
        # 10.10.10.10: { infra_seq: 1 } # 老的 Infra 节点
        10.10.10.12: { infra_seq: 3 }   # 新增 Infra 节点

    etcd:                               # 调整 ETCD 集群
      hosts:
        #10.10.10.10: { etcd_seq: 1 }   # 注释掉此故障节点
        #10.10.10.11: { etcd_seq: 2 }   # 注释掉此故障节点
        10.10.10.12: { etcd_seq: 3 }    # 保留幸存节点
      vars:
        etcd_cluster: etcd

    pg-meta:                            # 调整 PGSQL 集群配置
      hosts:
        #10.10.10.10: { pg_seq: 1, pg_role: primary }
        #10.10.10.11: { pg_seq: 2, pg_role: replica }
        #10.10.10.12: { pg_seq: 3, pg_role: replica , pg_offline_query: true }
        10.10.10.12: { pg_seq: 3, pg_role: primary , pg_offline_query: true }
      vars:
        pg_cluster: pg-meta

ETCD修复

然后执行以下命令,将 ETCD 重置为单节点集群:

./etcd.yml -e etcd_safeguard=false -e etcd_clean=true

根据 ETCD重载配置 的说明,调整对 ETCD Endpoint 的引用。

INFRA修复

如果幸存节点上没有 INFRA 模块,请在当前节点上配置新的 INFRA 模块并安装。执行以下命令,将 INFRA 模块部署到幸存节点上:

./infra.yml -l 10.10.10.12

修复当前节点的监控

./node.yml -t node_monitor

PGSQL修复

./pgsql.yml -t pg_conf                            # 重新生成 PG 配置文件
systemctl reload patroni                          # 在幸存节点上重载 Patroni 配置

各模块修复后,您可以参考标准扩容流程,将新的节点加入集群,恢复集群的高可用性。

9.7 - 使用 VIP-Manager 为 PostgreSQL 集群配置二层 VIP

您可以在 PostgreSQL 集群上绑定一个可选的 L2 VIP —— 前提条件是:集群中的所有节点都在一个二层网络中。

这个 L2 VIP 强制使用 Master - Backup 模式,Master 始终指向在数据库集群主库实例所在的节点。

这个 VIP 由 VIP-Manager 组件管理,它会从 DCS (etcd) 中直接读取由 Patroni 写入的 Leader Key,从而判断自己是否是 Master。


启用VIP

在 PostgreSQL 集群上定义 pg_vip_enabled 参数为 true,即可在集群上启用 VIP 组件。当然您也可以在全局配置中启用此配置项。

# pgsql 3 node ha cluster: pg-test
pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }   # primary instance, leader of cluster
    10.10.10.12: { pg_seq: 2, pg_role: replica }   # replica instance, follower of leader
    10.10.10.13: { pg_seq: 3, pg_role: replica, pg_offline_query: true } # replica with offline access
  vars:
    pg_cluster: pg-test           # define pgsql cluster name
    pg_users:  [{ name: test , password: test , pgbouncer: true , roles: [ dbrole_admin ] }]
    pg_databases: [{ name: test }]

    # 启用 L2 VIP
    pg_vip_enabled: true
    pg_vip_address: 10.10.10.3/24
    pg_vip_interface: eth1

请注意,pg_vip_address 必须是一个合法的 IP 地址,带有网段,且在当前二层网络中可用。

请注意,pg_vip_interface 必须是一个合法的网络接口名,并且应当是与 inventory 中使用 IPv4 地址一致的网卡。 如果集群成员的网卡名不一样,用户应当为每个实例显式指定 pg_vip_interface 参数,例如:

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary , pg_vip_interface: eth0  }
    10.10.10.12: { pg_seq: 2, pg_role: replica , pg_vip_interface: eth1  }
    10.10.10.13: { pg_seq: 3, pg_role: replica , pg_vip_interface: ens33 }
  vars:
    pg_cluster: pg-test           # define pgsql cluster name
    pg_users:  [{ name: test , password: test , pgbouncer: true , roles: [ dbrole_admin ] }]
    pg_databases: [{ name: test }]

    # 启用 L2 VIP
    pg_vip_enabled: true
    pg_vip_address: 10.10.10.3/24
    #pg_vip_interface: eth1

使用以下命令,刷新 PG 的 vip-manager 配置并重启生效:

./pgsql.yml -t pg_vip 

9.8 - Citus 集群部署

如何部署 Citus 高可用分布式集群?

Citus 是一个 PostgreSQL 扩展,可以将 PostgreSQL 原地转换为一个分布式数据库,并实现在多个节点上水平扩展,以处理大量数据和大量查询。

Patroni 在 v3.0 后,提供了对 Citus 原生高可用的支持,简化了 Citus 集群的搭建,Pigsty 也对此提供了原生支持。

注意:Citus 当前最新版本(13.0)支持 PostgreSQL 17、16、15、14 四个大版本。Pigsty 扩展仓库提供了 Citus ARM64 软件包。


Citus集群

Pigsty 原生支持 Citus。可以参考 conf/citus.yml

这里使用 Pigsty 四节点沙箱,定义了一个 Citus 集群 pg-citus,其中包括一个两节点的协调者集群 pg-citus0, 以及两个 Worker 集群 pg-citus1pg-citus2

pg-citus:
  hosts:
    10.10.10.10: { pg_group: 0, pg_cluster: pg-citus0 ,pg_vip_address: 10.10.10.2/24 ,pg_seq: 1, pg_role: primary }
    10.10.10.11: { pg_group: 0, pg_cluster: pg-citus0 ,pg_vip_address: 10.10.10.2/24 ,pg_seq: 2, pg_role: replica }
    10.10.10.12: { pg_group: 1, pg_cluster: pg-citus1 ,pg_vip_address: 10.10.10.3/24 ,pg_seq: 1, pg_role: primary }
    10.10.10.13: { pg_group: 2, pg_cluster: pg-citus2 ,pg_vip_address: 10.10.10.4/24 ,pg_seq: 1, pg_role: primary }
  vars:
    pg_mode: citus                            # pgsql cluster mode: citus
    pg_version: 17                            # citus 13.0 supports PG 14-17
    pg_shard: pg-citus                        # citus shard name: pg-citus
    pg_primary_db: citus                      # primary database used by citus
    pg_vip_enabled: true                      # enable vip for citus cluster
    pg_vip_interface: eth1                    # vip interface for all members
    pg_dbsu_password: DBUser.Postgres         # all dbsu password access for citus cluster
    pg_extensions: [ citus, postgis, pgvector, topn, pg_cron, hll ]  # install these extensions
    pg_libs: 'citus, pg_cron, pg_stat_statements' # citus will be added by patroni automatically
    pg_users: [{ name: dbuser_citus ,password: DBUser.Citus ,pgbouncer: true ,roles: [ dbrole_admin ]    }]
    pg_databases: [{ name: citus ,owner: dbuser_citus ,extensions: [ citus, vector, topn, pg_cron, hll ] }]
    pg_parameters:
      cron.database_name: citus
      citus.node_conninfo: 'sslmode=require sslrootcert=/pg/cert/ca.crt sslmode=verify-full'
    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'  }

相比标准 PostgreSQL 集群,Citus 集群的配置有一些特殊之处,首先,你需要确保 Citus 扩展被下载,安装,加载并启用,这涉及到以下四个参数

  • repo_packages:必须包含 citus 扩展,或者你需要使用带有 Citus 扩展的 PostgreSQL 离线安装包。
  • pg_extensions:必须包含 citus 扩展,即你必须在每个节点上安装 citus 扩展。
  • pg_libs:必须包含 citus 扩展,而且首位必须为 citus,但现在 Patroni 会自动完成这件事了。
  • pg_databases: 这里要定义一个首要数据库,该数据库必须安装 citus 扩展。

其次,你需要确保 Citus 集群的配置正确:

  • pg_mode: 必须设置为 citus,从而告知 Patroni 使用 Citus 模式。
  • pg_primary_db:必须指定一个首要数据库的名称,该数据库必须安装 citus 扩展,这里名为 citus
  • pg_shard:必须指定一个统一的名称,字符串,作为所有水平分片PG集群的集群名称前缀,这里为 pg-citus
  • pg_group:必须指定一个分片号,从零开始依次分配的整数,0 号固定代表协调者集群,其他为 Worker 集群。
  • pg_cluster 必须与 pg_shardpg_group 组合后的结果对应。
  • pg_dbsu_password:必须设置为非空的纯文本密码,否则 Citus 无法正常工作。
  • pg_parameters:建议设置 citus.node_conninfo 参数,强制要求 SSL 访问并要求节点间验证客户端证书。

配置完成后,您可以像创建普通 PostgreSQL 集群一样,使用 pgsql.yml 部署 Citus 集群。


管理Citus集群

定义好 Citus 集群后,部署 Citus 集群同样使用的剧本 pgsql.yml

./pgsql.yml -l pg-citus    # 部署 Citus 集群 pg-citus

使用任意成员的 DBSU(postgres)用户,都能通过 patronictlalias: pg) 列出 Citus 集群的状态:

$ pg list
+ Citus cluster: pg-citus ----------+---------+-----------+----+-----------+--------------------+
| Group | Member      | Host        | Role    | State     | TL | Lag in MB | Tags               |
+-------+-------------+-------------+---------+-----------+----+-----------+--------------------+
|     0 | pg-citus0-1 | 10.10.10.10 | Leader  | running   |  1 |           | clonefrom: true    |
|       |             |             |         |           |    |           | conf: tiny.yml     |
|       |             |             |         |           |    |           | spec: 20C.40G.125G |
|       |             |             |         |           |    |           | version: '16'      |
+-------+-------------+-------------+---------+-----------+----+-----------+--------------------+
|     1 | pg-citus1-1 | 10.10.10.11 | Leader  | running   |  1 |           | clonefrom: true    |
|       |             |             |         |           |    |           | conf: tiny.yml     |
|       |             |             |         |           |    |           | spec: 10C.20G.125G |
|       |             |             |         |           |    |           | version: '16'      |
+-------+-------------+-------------+---------+-----------+----+-----------+--------------------+
|     2 | pg-citus2-1 | 10.10.10.12 | Leader  | running   |  1 |           | clonefrom: true    |
|       |             |             |         |           |    |           | conf: tiny.yml     |
|       |             |             |         |           |    |           | spec: 10C.20G.125G |
|       |             |             |         |           |    |           | version: '16'      |
+-------+-------------+-------------+---------+-----------+----+-----------+--------------------+
|     2 | pg-citus2-2 | 10.10.10.13 | Replica | streaming |  1 |         0 | clonefrom: true    |
|       |             |             |         |           |    |           | conf: tiny.yml     |
|       |             |             |         |           |    |           | spec: 10C.20G.125G |
|       |             |             |         |           |    |           | version: '16'      |
+-------+-------------+-------------+---------+-----------+----+-----------+--------------------+

您可以将每个水平分片集群视为一个独立的 PGSQL 集群,使用 pg (patronictl) 命令管理它们。 但是务必注意,当你使用 pg 命令管理 Citus 集群时,需要额外使用 --group 参数指定集群分片号

pg list pg-citus --group 0   # 需要使用 --group 0 指定集群分片号

Citus 中有一个名为 pg_dist_node 的系统表,用于记录 Citus 集群的节点信息,Patroni 会自动维护该表。

PGURL=postgres://postgres:DBUser.Postgres@10.10.10.10/citus

psql $PGURL -c 'SELECT * FROM pg_dist_node;'       # 查看节点信息
 nodeid | groupid |  nodename   | nodeport | noderack | hasmetadata | isactive | noderole  | nodecluster | metadatasynced | shouldhaveshards
--------+---------+-------------+----------+----------+-------------+----------+-----------+-------------+----------------+------------------
      1 |       0 | 10.10.10.10 |     5432 | default  | t           | t        | primary   | default     | t              | f
      4 |       1 | 10.10.10.12 |     5432 | default  | t           | t        | primary   | default     | t              | t
      5 |       2 | 10.10.10.13 |     5432 | default  | t           | t        | primary   | default     | t              | t
      6 |       0 | 10.10.10.11 |     5432 | default  | t           | t        | secondary | default     | t              | f

此外,你还可以查看用户认证信息(仅限超级用户访问):

$ psql $PGURL -c 'SELECT * FROM pg_dist_authinfo;'   # 查看节点认证信息(仅限超级用户访问)

然后,你可以使用普通业务用户(例如,具有 DDL 权限的 dbuser_citus)来访问 Citus 集群:

psql postgres://dbuser_citus:DBUser.Citus@10.10.10.10/citus -c 'SELECT * FROM pg_dist_node;'

使用Citus集群

在使用 Citus 集群时,我们强烈建议您先阅读 Citus 官方文档,了解其架构设计与核心概念。

其中核心是了解 Citus 中的五种表,以及其特点与应用场景:

  • 分布式表(Distributed Table)
  • 参考表(Reference Table)
  • 本地表(Local Table)
  • 本地管理表(Local Management Table)
  • 架构表(Schema Table)

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

我们可以使用 pgbench 来创建一些表,并将其中的主表(pgbench_accounts)分布到各个节点上,然后将其他小表作为引用表:

PGURL=postgres://dbuser_citus:DBUser.Citus@10.10.10.10/citus
pgbench -i $PGURL

psql $PGURL <<-EOF
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');
EOF

执行读写测试:

pgbench -nv -P1 -c10 -T500 postgres://dbuser_citus:DBUser.Citus@10.10.10.10/citus      # 直连协调者 5432 端口
pgbench -nv -P1 -c10 -T500 postgres://dbuser_citus:DBUser.Citus@10.10.10.10:6432/citus # 通过连接池,减少客户端连接数压力,可以有效提高整体吞吐。
pgbench -nv -P1 -c10 -T500 postgres://dbuser_citus:DBUser.Citus@10.10.10.13/citus      # 任意 primary 节点都可以作为 coordinator
pgbench --select-only -nv -P1 -c10 -T500 postgres://dbuser_citus:DBUser.Citus@10.10.10.11/citus # 可以发起只读查询

更严肃的生产部署

要将 Citus 用于生产环境,您通常需要为 Coordinator 和每个 Worker 集群设置流复制物理副本。

例如,在 simu.yml 中定义了一个 10 节点的 Citus 集群。

pg-citus: # citus group
  hosts:
    10.10.10.50: { pg_group: 0, pg_cluster: pg-citus0 ,pg_vip_address: 10.10.10.60/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.51: { pg_group: 0, pg_cluster: pg-citus0 ,pg_vip_address: 10.10.10.60/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.52: { pg_group: 1, pg_cluster: pg-citus1 ,pg_vip_address: 10.10.10.61/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.53: { pg_group: 1, pg_cluster: pg-citus1 ,pg_vip_address: 10.10.10.61/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.54: { pg_group: 2, pg_cluster: pg-citus2 ,pg_vip_address: 10.10.10.62/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.55: { pg_group: 2, pg_cluster: pg-citus2 ,pg_vip_address: 10.10.10.62/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.56: { pg_group: 3, pg_cluster: pg-citus3 ,pg_vip_address: 10.10.10.63/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.57: { pg_group: 3, pg_cluster: pg-citus3 ,pg_vip_address: 10.10.10.63/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.58: { pg_group: 4, pg_cluster: pg-citus4 ,pg_vip_address: 10.10.10.64/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.59: { pg_group: 4, pg_cluster: pg-citus4 ,pg_vip_address: 10.10.10.64/24 ,pg_seq: 1, pg_role: replica }
  vars:
    pg_mode: citus                            # pgsql cluster mode: citus
    pg_version: 17                            # citus 13.0 supports PG 14-17
    pg_shard: pg-citus                        # citus shard name: pg-citus
    pg_primary_db: citus                      # primary database used by citus
    pg_vip_enabled: true                      # enable vip for citus cluster
    pg_vip_interface: eth1                    # vip interface for all members
    pg_dbsu_password: DBUser.Postgres         # enable dbsu password access for citus
    pg_extensions: [ citus, postgis, pgvector, topn, pg_cron, hll ]  # install these extensions
    pg_libs: 'citus, pg_cron, pg_stat_statements' # citus will be added by patroni automatically
    pg_users: [{ name: dbuser_citus ,password: DBUser.Citus ,pgbouncer: true ,roles: [ dbrole_admin ]    }]
    pg_databases: [{ name: citus ,owner: dbuser_citus ,extensions: [ citus, vector, topn, pg_cron, hll ] }]
    pg_parameters:
      cron.database_name: citus
      citus.node_conninfo: 'sslrootcert=/pg/cert/ca.crt sslmode=verify-full'
    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'  }

我们将在后续教程中覆盖一系列关于 Citus 的高级主题

  • 读写分离
  • 故障处理
  • 一致性备份与恢复
  • 高级监控与问题诊断
  • 连接池

10 - 参考资料

参数配置与参考文档

11 - 监控系统

Pigsty监控系统架构概览,以及如何监控现存的 PostgreSQL 实例?

本文介绍了 Pigsty 的监控系统架构,包括监控指标,日志,与目标管理的方式。以及如何 监控现有PG集群 与远程 RDS服务


监控概览

Pigsty使用现代的可观测技术栈对 PostgreSQL 进行监控:

  • 使用 Grafana 进行指标可视化和 PostgreSQL 数据源。
  • 使用 VictoriaMetrics 来采集 PostgreSQL / Pgbouncer / Patroni / HAProxy / Node 的指标
  • 使用 VictoriaLogs 来记录 PostgreSQL / Pgbouncer / Patroni / pgBackRest 以及主机组件的日志
  • Pigsty 提供了开箱即用的 Grafana 仪表盘,展示与 PostgreSQL 有关的方方面面。

监控指标

PostgreSQL 本身的监控指标完全由 pg_exporter 配置文件所定义:pg_exporter.yml 它将进一步被 Prometheus 记录规则和告警规则进行加工处理:files/prometheus/rules/pgsql.yml

Pigsty使用三个身份标签:clsinsip,它们将附加到所有指标和日志上。此外,Pgbouncer的监控指标,主机节点 NODE,与负载均衡器的监控指标也会被 Pigsty 所使用,并尽可能地使用相同的标签以便于关联分析。

{ cls: pg-meta, ins: pg-meta-1, ip: 10.10.10.10 }
{ cls: pg-meta, ins: pg-test-1, ip: 10.10.10.11 }
{ cls: pg-meta, ins: pg-test-2, ip: 10.10.10.12 }
{ cls: pg-meta, ins: pg-test-3, ip: 10.10.10.13 }

日志

与 PostgreSQL 有关的日志由 vector 负责收集,并发送至 infra 节点上的 VictoriaLogs 日志存储/查询服务。

目标管理

Prometheus的监控目标在 /etc/prometheus/targets/pgsql/ 下的静态文件中定义,每个实例都有一个相应的文件。以 pg-meta-1 为例:

# pg-meta-1 [primary] @ 10.10.10.10
- labels: { cls: pg-meta, ins: pg-meta-1, ip: 10.10.10.10 }
  targets:
    - 10.10.10.10:9630    # <--- pg_exporter 用于PostgreSQL指标
    - 10.10.10.10:9631    # <--- pg_exporter 用于pgbouncer指标
    - 10.10.10.10:8008    # <--- patroni指标(未启用 API SSL 时)

当全局标志 patroni_ssl_enabled 被设置时,patroni目标将被移动到单独的文件 /etc/prometheus/targets/patroni/<ins>.yml。 因为此时使用的是 https 抓取端点。当您 监控RDS 实例时,监控目标会被单独放置于: /etc/prometheus/targets/pgrds/ 目录下,并以集群为单位进行管理。

当使用 bin/pgsql-rmpgsql-rm.yml 移除集群时,Prometheus监控目标将被移除。您也可以手动移除它,或使用剧本里的子任务:

bin/pgmon-rm <cls|ins>    # 从所有infra节点中移除 prometheus 监控目标

远程 RDS 监控目标会被放置于 /etc/prometheus/targets/pgrds/<cls>.yml,它们是由 pgsql-monitor.yml 剧本或 bin/pgmon-add 脚本所创建的。


监控模式

Pigsty 提供三种监控模式,以适应不同的监控需求。

事项\等级L1L2L3
名称基础部署托管部署标准部署
英文RDSMANAGEDFULL
场景只有连接串,例如RDSDB已存在,节点可管理实例由 Pigsty 创建
PGCAT功能✅ 完整可用✅ 完整可用✅ 完整可用
PGSQL功能✅ 限PG指标✅ 限PG与节点指标✅ 完整功能
连接池指标❌ 不可用⚠️ 选装✅ 预装项
负载均衡器指标❌ 不可用⚠️ 选装✅ 预装项
PGLOG功能❌ 不可用⚠️ 选装✅ 预装项
PG Exporter⚠️ 部署于Infra节点✅ 部署于DB节点✅ 部署于DB节点
Node Exporter❌ 不部署✅ 部署于DB节点✅ 部署于DB节点
侵入DB节点✅ 无侵入⚠️ 安装Exporter⚠️ 完全由Pigsty管理
监控现有实例✅ 可支持✅ 可支持❌ 仅用于Pigsty托管实例
监控用户与视图人工创建人工创建Pigsty自动创建
部署使用剧本bin/pgmon-add <cls>部分执行 pgsql.ym/node.ymlpgsql.yml
所需权限Infra 节点可达的 PGURLDB节点ssh与sudo权限DB节点ssh与sudo权限
功能概述PGCAT + PGRDS大部分功能完整功能

由Pigsty完全管理的数据库会自动纳入监控,并拥有最好的监控支持,通常不需要任何配置。对于现有的 PostgreSQL 集群或者 RDS 服务,如果如果目标DB节点可以被Pigsty所管理(ssh可达,sudo可用),那么您可以考虑 托管部署,实现与 Pigsty 基本类似的监控管理体验。如果您只能通过PGURL(数据库连接串)的方式访问目标数据库,例如远程的RDS服务,则可以考虑使用 精简模式 监控目标数据库。


监控现有集群

如果目标DB节点可以被Pigsty所管理ssh可达且sudo可用),那么您可以使用 pgsql.yml 剧本中的pg_exporter任务, 使用与标准部署相同的方式,在目标节点上部署监控组件:PG Exporter。您也可以使用该剧本的 pgbouncerpgbouncer_exporter 任务在已有实例节点上部署连接池及其监控。此外,您也可以使用 node.yml 中的 node_exporterhaproxyvector 部署主机监控,负载均衡,日志收集组件。从而获得与原生Pigsty数据库实例完全一致的使用体验。

现有集群的定义方式与 Pigsty 所管理的集群定义方式完全相同,您只是选择性执行 pgsql.yml 剧本中的部分任务,而不是执行整个剧本。

./node.yml  -l <cls> -t node_repo,node_pkg           # 在主机节点上添加 INFRA节点的 YUM 源并安装软件包。
./node.yml  -l <cls> -t node_exporter,node_register  # 配置主机监控,并加入 VictoriaMetrics
./node.yml  -l <cls> -t vector                       # 配置主机日志采集,并发送至 victoria-logs
./pgsql.yml -l <cls> -t pg_exporter,pg_register      # 配置 PostgreSQL 监控,并注册至 Victoria/Grafana

因为目标数据库集群已存在,所以您需要手工在目标数据库集群上 创建监控用户、模式与扩展


监控RDS

如果您只能通过PGURL(数据库连接串)的方式访问目标数据库,那么可以参照这里的说明进行配置。在这种模式下,Pigsty 在 INFRA节点 上部署对应的 PG Exporter,抓取远端数据库指标信息。如下图所示:

------ infra ------
|                 |
|   prometheus    |            v---- pg-foo-1 ----v
|       ^         |  metrics   |         ^        |
|   pg_exporter <-|------------|----  postgres    |
|   (port: 20001) |            | 10.10.10.10:5432 |
|       ^         |            ^------------------^
|       ^         |                      ^
|       ^         |            v---- pg-foo-2 ----v
|       ^         |  metrics   |         ^        |
|   pg_exporter <-|------------|----  postgres    |
|   (port: 20002) |            | 10.10.10.11:5433 |
-------------------            ^------------------^

在这种模式下,监控系统不会有主机,连接池,负载均衡器,高可用组件的相关指标,但数据库本身,以及数据目录(Catalog)中的实时状态信息仍然可用。Pigsty提供了两个专用的监控面板,专注于 PostgreSQL 本身的监控指标: PGRDS ClusterPGRDS Instance,总览与数据库内监控则复用现有监控面板。因为Pigsty不能管理您的RDS,所以用户需要在目标数据库上提前 配置好监控对象

下面我们使用沙箱环境作为示例:现在我们假设 pg-meta 集群是一个有待监控的 RDS 实例 pg-foo-1,而 pg-test 集群则是一个有待监控的RDS集群 pg-bar

  1. 在目标上创建监控模式、用户和权限。详情请参考 监控对象配置

  2. 在配置清单中声明集群。例如,假设我们想要监控“远端”的 pg-meta & pg-test 集群:

    infra:            # 代理、监控、警报等的infra集群..
      hosts: { 10.10.10.10: { infra_seq: 1 } }
      vars:           # 在组'infra'上为远程postgres RDS安装pg_exporter
        pg_exporters: # 在此列出所有远程实例,为k分配一个唯一的未使用的本地端口
          20001: { pg_cluster: pg-foo, pg_seq: 1, pg_host: 10.10.10.10 , pg_databases: [{ name: meta }] } # 注册 meta 数据库为 Grafana 数据源
    
          20002: { pg_cluster: pg-bar, pg_seq: 1, pg_host: 10.10.10.11 , pg_port: 5432 } # 几种不同的连接串拼接方法
          20003: { pg_cluster: pg-bar, pg_seq: 2, pg_host: 10.10.10.12 , pg_exporter_url: 'postgres://dbuser_monitor:DBUser.Monitor@10.10.10.12:5432/postgres?sslmode=disable'}
          20004: { pg_cluster: pg-bar, pg_seq: 3, pg_host: 10.10.10.13 , pg_monitor_username: dbuser_monitor, pg_monitor_password: DBUser.Monitor }
    

    其中, pg_databases 字段中所列出的数据库,将会被注册至 Grafana 中,成为一个 PostgreSQL 数据源,为 PGCAT 监控面板提供数据支持。如果您不想使用PGCAT,将注册数据库到Grafana中,只需要将 pg_databases 设置为空数组或直接留空即可。

    pigsty-monitor.jpg

  3. 执行添加监控命令:bin/pgmon-add <clsname>

    bin/pgmon-add pg-foo  # 将 pg-foo 集群纳入监控
    bin/pgmon-add pg-bar  # 将 pg-bar 集群纳入监控
    
  4. 要删除远程集群的监控目标,可以使用 bin/pgmon-rm <clsname>

    bin/pgmon-rm pg-foo  # 将 pg-foo 从 Pigsty 监控中移除
    bin/pgmon-rm pg-bar  # 将 pg-bar 从 Pigsty 监控中移除
    

您可以使用更多的参数来覆盖默认 pg_exporter 的选项,下面是一个使用 Pigsty 监控阿里云 RDS 与 PolarDB 的配置样例:

示例:监控阿里云 RDS for PostgreSQL 与 PolarDB

详情请参考:remote.yml

infra:            # 代理、监控、警报等的infra集群..
  hosts: { 10.10.10.10: { infra_seq: 1 } }
  vars:
    pg_exporters:   # 在此列出所有待监控的远程 RDS PG 实例

      20001:        # 分配一个唯一的未使用的本地端口,供本地监控 Agent 使用,这里是一个 PolarDB 的主库
        pg_cluster: pg-polar                  # RDS 集群名 (身份参数,手工指定分配监控系统内名称)
        pg_seq: 1                             # RDS 实例号 (身份参数,手工指定分配监控系统内名称)
        pg_host: pc-2ze379wb1d4irc18x.polardbpg.rds.aliyuncs.com # RDS 主机地址
        pg_port: 1921                         # RDS 端口(从控制台连接信息获取)
        pg_exporter_auto_discovery: true      # 禁用新数据库自动发现功能
        pg_exporter_include_database: 'test'  # 仅监控这个列表中的数据库(多个数据库用逗号分隔)
        pg_monitor_username: dbuser_monitor   # 监控用的用户名,覆盖全局配置
        pg_monitor_password: DBUser_Monitor   # 监控用的密码,覆盖全局配置
        pg_databases: [{ name: test }]        # 希望启用PGCAT的数据库列表,只要name字段即可,register_datasource设置为false则不注册。

      20002:       # 这是一个 PolarDB  从库
        pg_cluster: pg-polar                  # RDS 集群名 (身份参数,手工指定分配监控系统内名称)
        pg_seq: 2                             # RDS 实例号 (身份参数,手工指定分配监控系统内名称)
        pg_host: pe-2ze7tg620e317ufj4.polarpgmxs.rds.aliyuncs.com # RDS 主机地址
        pg_port: 1521                         # RDS 端口(从控制台连接信息获取)
        pg_exporter_auto_discovery: true      # 禁用新数据库自动发现功能
        pg_exporter_include_database: 'test,postgres'  # 仅监控这个列表中的数据库(多个数据库用逗号分隔)
        pg_monitor_username: dbuser_monitor   # 监控用的用户名
        pg_monitor_password: DBUser_Monitor   # 监控用的密码
        pg_databases: [ { name: test } ]        # 希望启用PGCAT的数据库列表,只要name字段即可,register_datasource设置为false则不注册。

      20004: # 这是一个基础版的单节点 RDS for PostgreSQL 实例
        pg_cluster: pg-rds                    # RDS 集群名 (身份参数,手工指定分配监控系统内名称)
        pg_seq: 1                             # RDS 实例号 (身份参数,手工指定分配监控系统内名称)
        pg_host: pgm-2zern3d323fe9ewk.pg.rds.aliyuncs.com  # RDS 主机地址
        pg_port: 5432                         # RDS 端口(从控制台连接信息获取)
        pg_exporter_auto_discovery: true      # 禁用新数据库自动发现功能
        pg_exporter_include_database: 'rds'   # 仅监控这个列表中的数据库(多个数据库用逗号分隔)
        pg_monitor_username: dbuser_monitor   # 监控用的用户名
        pg_monitor_password: DBUser_Monitor   # 监控用的密码
        pg_databases: [ { name: rds } ]       # 希望启用PGCAT的数据库列表,只要name字段即可,register_datasource设置为false则不注册。

      20005: # 这是一个高可用版的 RDS for PostgreSQL 集群主库
        pg_cluster: pg-rdsha                  # RDS 集群名 (身份参数,手工指定分配监控系统内名称)
        pg_seq: 1                             # RDS 实例号 (身份参数,手工指定分配监控系统内名称)
        pg_host: pgm-2ze3d35d27bq08wu.pg.rds.aliyuncs.com  # RDS 主机地址
        pg_port: 5432                         # RDS 端口(从控制台连接信息获取)
        pg_exporter_include_database: 'rds'   # 仅监控这个列表中的数据库(多个数据库用逗号分隔)
        pg_databases: [ { name: rds }, {name : test} ]  # 将这两个数据库纳入 PGCAT 管理,注册为 Grafana 数据源

      20006: # 这是一个高可用版的 RDS for PostgreSQL 集群只读实例(从库)
        pg_cluster: pg-rdsha                  # RDS 集群名 (身份参数,手工指定分配监控系统内名称)
        pg_seq: 2                             # RDS 实例号 (身份参数,手工指定分配监控系统内名称)
        pg_host: pgr-2zexqxalk7d37edt.pg.rds.aliyuncs.com  # RDS 主机地址
        pg_port: 5432                         # RDS 端口(从控制台连接信息获取)
        pg_exporter_include_database: 'rds'   # 仅监控这个列表中的数据库(多个数据库用逗号分隔)
        pg_databases: [ { name: rds }, {name : test} ]  # 将这两个数据库纳入 PGCAT 管理,注册为 Grafana 数据源

监控对象配置

当您想要监控现有实例时,不论是 RDS,还是自建的 PostgreSQL 实例,您都需要在目标数据库上进行一些配置,以便 Pigsty 可以访问它们。

为了将外部现存PostgreSQL实例纳入监控,您需要有一个可用于访问该实例/集群的连接串。任何可达连接串(业务用户,超级用户)均可使用,但我们建议使用一个专用监控用户以避免权限泄漏。

  • 监控用户:默认使用的用户名为 dbuser_monitor, 该用户属于 pg_monitor 角色组,或确保具有相关视图访问权限。
  • 监控认证:默认使用密码访问,您需要确保HBA策略允许监控用户从管理机或DB节点本地访问数据库。
  • 监控模式:固定使用名称 monitor,用于安装额外的监控视图与扩展插件,非必选,但建议创建。
  • 监控扩展强烈建议启用PG自带的监控扩展 pg_stat_statements
  • 监控视图:监控视图是可选项,可以提供更多的监控指标支持。

监控用户

以Pigsty默认使用的监控用户dbuser_monitor为例,在目标数据库集群创建以下用户。

CREATE USER dbuser_monitor;                                       -- 创建监控用户
COMMENT ON ROLE dbuser_monitor IS 'system monitor user';          -- 监控用户备注
GRANT pg_monitor TO dbuser_monitor;                               -- 授予监控用户 pg_monitor 权限,否则一些指标将无法采集

ALTER USER dbuser_monitor PASSWORD 'DBUser.Monitor';              -- 按需修改监控用户密码(强烈建议修改!但请与Pigsty配置一致)
ALTER USER dbuser_monitor SET log_min_duration_statement = 1000;  -- 建议设置此参数,避免日志塞满监控慢查询
ALTER USER dbuser_monitor SET search_path = monitor,public;       -- 建议设置此参数,避免 pg_stat_statements 扩展无法生效

请注意,这里创建的监控用户与密码需要与 pg_monitor_usernamepg_monitor_password 保持一致。


监控认证

配置数据库 pg_hba.conf 文件,添加以下规则以允许监控用户从本地,以及管理机使用密码访问所有数据库。

# allow local role monitor with password
local   all  dbuser_monitor                    md5
host    all  dbuser_monitor  127.0.0.1/32      md5
host    all  dbuser_monitor  <管理机器IP地址>/32 md5

如果您的 RDS 不支持定义 HBA,那么把安装 Pigsty 机器的内网 IP 地址开白即可。


监控模式

监控模式可选项,即使没有,Pigsty监控系统的主体也可以正常工作,但我们强烈建议设置此模式。

CREATE SCHEMA IF NOT EXISTS monitor;               -- 创建监控专用模式
GRANT USAGE ON SCHEMA monitor TO dbuser_monitor;   -- 允许监控用户使用

监控扩展

监控扩展是可选项,但我们强烈建议启用 pg_stat_statements 扩展该扩展提供了关于查询性能的重要数据。

注意:该扩展必须列入数据库参数 shared_preload_libraries 中方可生效,而修改该参数需要重启数据库。

CREATE EXTENSION IF NOT EXISTS "pg_stat_statements" WITH SCHEMA "monitor";

请注意,您应当在默认的管理数据库 postgres 中安装此扩展。有些时候,RDS不允许您在 postgres 数据库中创建监控模式, 在这种情况下,您可以将 pg_stat_statements 插件安装到默认的 public 下,只要确保监控用户的 search_path 按照上面的配置,能够找到 pg_stat_statements 视图即可。

CREATE EXTENSION IF NOT EXISTS "pg_stat_statements";
ALTER USER dbuser_monitor SET search_path = monitor,public; -- 建议设置此参数,避免 pg_stat_statements 扩展无法生效

监控视图

监控视图提供了若干常用的预处理结果,并对某些需要高权限的监控指标进行权限封装(例如共享内存分配),便于查询与使用。强烈建议在所有需要监控的数据库中创建

监控模式与监控视图定义
----------------------------------------------------------------------
-- Table bloat estimate : monitor.pg_table_bloat
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_table_bloat CASCADE;
CREATE OR REPLACE VIEW monitor.pg_table_bloat AS
SELECT CURRENT_CATALOG AS datname, nspname, relname , tblid , bs * tblpages AS size,
       CASE WHEN tblpages - est_tblpages_ff > 0 THEN (tblpages - est_tblpages_ff)/tblpages::FLOAT ELSE 0 END AS ratio
FROM (
         SELECT ceil( reltuples / ( (bs-page_hdr)*fillfactor/(tpl_size*100) ) ) + ceil( toasttuples / 4 ) AS est_tblpages_ff,
                tblpages, fillfactor, bs, tblid, nspname, relname, is_na
         FROM (
                  SELECT
                      ( 4 + tpl_hdr_size + tpl_data_size + (2 * ma)
                          - CASE WHEN tpl_hdr_size % ma = 0 THEN ma ELSE tpl_hdr_size % ma END
                          - CASE WHEN ceil(tpl_data_size)::INT % ma = 0 THEN ma ELSE ceil(tpl_data_size)::INT % ma END
                          ) AS tpl_size, (heappages + toastpages) AS tblpages, heappages,
                      toastpages, reltuples, toasttuples, bs, page_hdr, tblid, nspname, relname, fillfactor, is_na
                  FROM (
                           SELECT
                               tbl.oid AS tblid, ns.nspname , tbl.relname, tbl.reltuples,
                               tbl.relpages AS heappages, coalesce(toast.relpages, 0) AS toastpages,
                               coalesce(toast.reltuples, 0) AS toasttuples,
                               coalesce(substring(array_to_string(tbl.reloptions, ' ') FROM 'fillfactor=([0-9]+)')::smallint, 100) AS fillfactor,
                               current_setting('block_size')::numeric AS bs,
                               CASE WHEN version()~'mingw32' OR version()~'64-bit|x86_64|ppc64|ia64|amd64' THEN 8 ELSE 4 END AS ma,
                               24 AS page_hdr,
                               23 + CASE WHEN MAX(coalesce(s.null_frac,0)) > 0 THEN ( 7 + count(s.attname) ) / 8 ELSE 0::int END
                                   + CASE WHEN bool_or(att.attname = 'oid' and att.attnum < 0) THEN 4 ELSE 0 END AS tpl_hdr_size,
                               sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 0) ) AS tpl_data_size,
                               bool_or(att.atttypid = 'pg_catalog.name'::regtype)
                                   OR sum(CASE WHEN att.attnum > 0 THEN 1 ELSE 0 END) <> count(s.attname) AS is_na
                           FROM pg_attribute AS att
                                    JOIN pg_class AS tbl ON att.attrelid = tbl.oid
                                    JOIN pg_namespace AS ns ON ns.oid = tbl.relnamespace
                                    LEFT JOIN pg_stats AS s ON s.schemaname=ns.nspname AND s.tablename = tbl.relname AND s.inherited=false AND s.attname=att.attname
                                    LEFT JOIN pg_class AS toast ON tbl.reltoastrelid = toast.oid
                           WHERE NOT att.attisdropped AND tbl.relkind = 'r' AND nspname NOT IN ('pg_catalog','information_schema')
                           GROUP BY 1,2,3,4,5,6,7,8,9,10
                       ) AS s
              ) AS s2
     ) AS s3
WHERE NOT is_na;
COMMENT ON VIEW monitor.pg_table_bloat IS 'postgres table bloat estimate';

GRANT SELECT ON monitor.pg_table_bloat TO pg_monitor;

----------------------------------------------------------------------
-- Index bloat estimate : monitor.pg_index_bloat
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_index_bloat CASCADE;
CREATE OR REPLACE VIEW monitor.pg_index_bloat AS
SELECT CURRENT_CATALOG AS datname, nspname, idxname AS relname, tblid, idxid, relpages::BIGINT * bs AS size,
       COALESCE((relpages - ( reltuples * (6 + ma - (CASE WHEN index_tuple_hdr % ma = 0 THEN ma ELSE index_tuple_hdr % ma END)
                                               + nulldatawidth + ma - (CASE WHEN nulldatawidth % ma = 0 THEN ma ELSE nulldatawidth % ma END))
                                  / (bs - pagehdr)::FLOAT  + 1 )), 0) / relpages::FLOAT AS ratio
FROM (
         SELECT nspname,idxname,indrelid AS tblid,indexrelid AS idxid,
                reltuples,relpages,
                current_setting('block_size')::INTEGER                                                               AS bs,
                (CASE WHEN version() ~ 'mingw32' OR version() ~ '64-bit|x86_64|ppc64|ia64|amd64' THEN 8 ELSE 4 END)  AS ma,
                24                                                                                                   AS pagehdr,
                (CASE WHEN max(COALESCE(pg_stats.null_frac, 0)) = 0 THEN 2 ELSE 6 END)                               AS index_tuple_hdr,
                sum((1.0 - COALESCE(pg_stats.null_frac, 0.0)) *
                    COALESCE(pg_stats.avg_width, 1024))::INTEGER                                                     AS nulldatawidth
         FROM pg_attribute
                  JOIN (
             SELECT pg_namespace.nspname,
                    ic.relname                                                   AS idxname,
                    ic.reltuples,
                    ic.relpages,
                    pg_index.indrelid,
                    pg_index.indexrelid,
                    tc.relname                                                   AS tablename,
                    regexp_split_to_table(pg_index.indkey::TEXT, ' ') :: INTEGER AS attnum,
                    pg_index.indexrelid                                          AS index_oid
             FROM pg_index
                      JOIN pg_class ic ON pg_index.indexrelid = ic.oid
                      JOIN pg_class tc ON pg_index.indrelid = tc.oid
                      JOIN pg_namespace ON pg_namespace.oid = ic.relnamespace
                      JOIN pg_am ON ic.relam = pg_am.oid
             WHERE pg_am.amname = 'btree' AND ic.relpages > 0 AND nspname NOT IN ('pg_catalog', 'information_schema')
         ) ind_atts ON pg_attribute.attrelid = ind_atts.indexrelid AND pg_attribute.attnum = ind_atts.attnum
                  JOIN pg_stats ON pg_stats.schemaname = ind_atts.nspname
             AND ((pg_stats.tablename = ind_atts.tablename AND pg_stats.attname = pg_get_indexdef(pg_attribute.attrelid, pg_attribute.attnum, TRUE))
                 OR (pg_stats.tablename = ind_atts.idxname AND pg_stats.attname = pg_attribute.attname))
         WHERE pg_attribute.attnum > 0
         GROUP BY 1, 2, 3, 4, 5, 6
     ) est;
COMMENT ON VIEW monitor.pg_index_bloat IS 'postgres index bloat estimate (btree-only)';

GRANT SELECT ON monitor.pg_index_bloat TO pg_monitor;

----------------------------------------------------------------------
-- Relation Bloat : monitor.pg_bloat
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_bloat CASCADE;
CREATE OR REPLACE VIEW monitor.pg_bloat AS
SELECT coalesce(ib.datname, tb.datname)                                                   AS datname,
       coalesce(ib.nspname, tb.nspname)                                                   AS nspname,
       coalesce(ib.tblid, tb.tblid)                                                       AS tblid,
       coalesce(tb.nspname || '.' || tb.relname, ib.nspname || '.' || ib.tblid::RegClass) AS tblname,
       tb.size                                                                            AS tbl_size,
       CASE WHEN tb.ratio < 0 THEN 0 ELSE round(tb.ratio::NUMERIC, 6) END                 AS tbl_ratio,
       (tb.size * (CASE WHEN tb.ratio < 0 THEN 0 ELSE tb.ratio::NUMERIC END)) ::BIGINT    AS tbl_wasted,
       ib.idxid,
       ib.nspname || '.' || ib.relname                                                    AS idxname,
       ib.size                                                                            AS idx_size,
       CASE WHEN ib.ratio < 0 THEN 0 ELSE round(ib.ratio::NUMERIC, 5) END                 AS idx_ratio,
       (ib.size * (CASE WHEN ib.ratio < 0 THEN 0 ELSE ib.ratio::NUMERIC END)) ::BIGINT    AS idx_wasted
FROM monitor.pg_index_bloat ib
         FULL OUTER JOIN monitor.pg_table_bloat tb ON ib.tblid = tb.tblid;

COMMENT ON VIEW monitor.pg_bloat IS 'postgres relation bloat detail';
GRANT SELECT ON monitor.pg_bloat TO pg_monitor;

----------------------------------------------------------------------
-- monitor.pg_index_bloat_human
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_index_bloat_human CASCADE;
CREATE OR REPLACE VIEW monitor.pg_index_bloat_human AS
SELECT idxname                            AS name,
       tblname,
       idx_wasted                         AS wasted,
       pg_size_pretty(idx_size)           AS idx_size,
       round(100 * idx_ratio::NUMERIC, 2) AS idx_ratio,
       pg_size_pretty(idx_wasted)         AS idx_wasted,
       pg_size_pretty(tbl_size)           AS tbl_size,
       round(100 * tbl_ratio::NUMERIC, 2) AS tbl_ratio,
       pg_size_pretty(tbl_wasted)         AS tbl_wasted
FROM monitor.pg_bloat
WHERE idxname IS NOT NULL;
COMMENT ON VIEW monitor.pg_index_bloat_human IS 'postgres index bloat info in human-readable format';
GRANT SELECT ON monitor.pg_index_bloat_human TO pg_monitor;


----------------------------------------------------------------------
-- monitor.pg_table_bloat_human
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_table_bloat_human CASCADE;
CREATE OR REPLACE VIEW monitor.pg_table_bloat_human AS
SELECT tblname                                          AS name,
       idx_wasted + tbl_wasted                          AS wasted,
       pg_size_pretty(idx_wasted + tbl_wasted)          AS all_wasted,
       pg_size_pretty(tbl_wasted)                       AS tbl_wasted,
       pg_size_pretty(tbl_size)                         AS tbl_size,
       tbl_ratio,
       pg_size_pretty(idx_wasted)                       AS idx_wasted,
       pg_size_pretty(idx_size)                         AS idx_size,
       round(idx_wasted::NUMERIC * 100.0 / idx_size, 2) AS idx_ratio
FROM (SELECT datname,
             nspname,
             tblname,
             coalesce(max(tbl_wasted), 0)                         AS tbl_wasted,
             coalesce(max(tbl_size), 1)                           AS tbl_size,
             round(100 * coalesce(max(tbl_ratio), 0)::NUMERIC, 2) AS tbl_ratio,
             coalesce(sum(idx_wasted), 0)                         AS idx_wasted,
             coalesce(sum(idx_size), 1)                           AS idx_size
      FROM monitor.pg_bloat
      WHERE tblname IS NOT NULL
      GROUP BY 1, 2, 3
     ) d;
COMMENT ON VIEW monitor.pg_table_bloat_human IS 'postgres table bloat info in human-readable format';
GRANT SELECT ON monitor.pg_table_bloat_human TO pg_monitor;


----------------------------------------------------------------------
-- Activity Overview: monitor.pg_session
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_session CASCADE;
CREATE OR REPLACE VIEW monitor.pg_session AS
SELECT coalesce(datname, 'all') AS datname, numbackends, active, idle, ixact, max_duration, max_tx_duration, max_conn_duration
FROM (
         SELECT datname,
                count(*)                                         AS numbackends,
                count(*) FILTER ( WHERE state = 'active' )       AS active,
                count(*) FILTER ( WHERE state = 'idle' )         AS idle,
                count(*) FILTER ( WHERE state = 'idle in transaction'
                    OR state = 'idle in transaction (aborted)' ) AS ixact,
                max(extract(epoch from now() - state_change))
                FILTER ( WHERE state = 'active' )                AS max_duration,
                max(extract(epoch from now() - xact_start))      AS max_tx_duration,
                max(extract(epoch from now() - backend_start))   AS max_conn_duration
         FROM pg_stat_activity
         WHERE backend_type = 'client backend'
           AND pid <> pg_backend_pid()
         GROUP BY ROLLUP (1)
         ORDER BY 1 NULLS FIRST
     ) t;
COMMENT ON VIEW monitor.pg_session IS 'postgres activity group by session';
GRANT SELECT ON monitor.pg_session TO pg_monitor;


----------------------------------------------------------------------
-- Sequential Scan: monitor.pg_seq_scan
----------------------------------------------------------------------
DROP VIEW IF EXISTS monitor.pg_seq_scan CASCADE;
CREATE OR REPLACE VIEW monitor.pg_seq_scan AS
SELECT schemaname                                                        AS nspname,
       relname,
       seq_scan,
       seq_tup_read,
       seq_tup_read / seq_scan                                           AS seq_tup_avg,
       idx_scan,
       n_live_tup + n_dead_tup                                           AS tuples,
       round(n_live_tup * 100.0::NUMERIC / (n_live_tup + n_dead_tup), 2) AS live_ratio
FROM pg_stat_user_tables
WHERE seq_scan > 0
  and (n_live_tup + n_dead_tup) > 0
ORDER BY seq_scan DESC;
COMMENT ON VIEW monitor.pg_seq_scan IS 'table that have seq scan';
GRANT SELECT ON monitor.pg_seq_scan TO pg_monitor;
查看共享内存分配的函数(PG13以上可用)
DROP FUNCTION IF EXISTS monitor.pg_shmem() CASCADE;
CREATE OR REPLACE FUNCTION monitor.pg_shmem() RETURNS SETOF
    pg_shmem_allocations AS $$ SELECT * FROM pg_shmem_allocations;$$ LANGUAGE SQL SECURITY DEFINER;
COMMENT ON FUNCTION monitor.pg_shmem() IS 'security wrapper for system view pg_shmem';
REVOKE ALL ON FUNCTION monitor.pg_shmem() FROM PUBLIC;
GRANT EXECUTE ON FUNCTION monitor.pg_shmem() TO pg_monitor;

12 - 监控面板

Pigsty 为 PostgreSQL 提供了诸多开箱即用的 Grafana 监控仪表盘

Pigsty 为 PostgreSQL 提供了诸多开箱即用的 Grafana 监控仪表盘: Demo & Gallery

在 Pigsty 中共有 26 个与 PostgreSQL 相关的监控面板,按照层次分为 总览,集群,实例,数据库四大类,按照数据来源又分为 PGSQLPGCATPGLOG 三大类。

pigsty-dashboard.jpg


总览

总览集群实例数据库
PGSQL OverviewPGSQL ClusterPGSQL InstancePGSQL Database
PGSQL AlertPGRDS ClusterPGRDS InstancePGCAT Database
PGSQL ShardPGSQL ActivityPGCAT InstancePGSQL Tables
PGSQL ReplicationPGSQL PersistPGSQL Table
PGSQL ServicePGSQL ProxyPGCAT Table
PGSQL DatabasesPGSQL PgbouncerPGSQL Query
PGSQL PatroniPGSQL SessionPGCAT Query
PGSQL PITRPGSQL XactsPGCAT Locks
PGSQL ExporterPGCAT Schema

概览

  • pgsql-overview : PGSQL模块的主仪表板
  • pgsql-alert : PGSQL的全局关键指标和警报事件
  • pgsql-shard : 关于水平分片的PGSQL集群的概览,例如 citus / gpsql 集群

集群

  • pgsql-cluster: 一个PGSQL集群的主仪表板
  • pgrds-cluster: PGSQL Cluster 的RDS版本,专注于所有 PostgreSQL 本身的指标
  • pgsql-activity: 关注PGSQL集群的会话/负载/QPS/TPS/锁定情况
  • pgsql-replication: 关注PGSQL集群复制、插槽和发布/订阅
  • pgsql-service: 关注PGSQL集群服务、代理、路由和负载均衡
  • pgsql-databases: 关注所有实例的数据库CRUD、慢查询和表统计信息
  • pgsql-patroni: 关注集群高可用状态,Patroni组件状态
  • pgsql-pitr: 关注集群 PITR 过程的上下文,用于辅助时间点恢复

实例

数据库

  • pgsql-database: 单个PGSQL数据库的主仪表板
  • pgcat-database: 直接从数据库目录获取的数据库信息
  • pgsql-tables : 单个数据库内的表/索引访问指标
  • pgsql-table: 单个表的详细信息(QPS/RT/索引/序列…)
  • pgcat-table: 直接从数据库目录获取的单个表的详细信息(统计/膨胀…)
  • pgsql-query: 单个查询的详细信息(QPS/RT)
  • pgcat-query: 直接从数据库目录获取的单个查询的详细信息(SQL/统计)
  • pgcat-schema: 直接从数据库目录获取关于模式的信息(表/索引/序列…)
  • pgcat-locks: 直接从数据库目录获取的关于活动与锁等待的信息

总览

PGSQL Overview:PGSQL模块的主仪表板

PGSQL Overview

pgsql-overview.jpg

PGSQL Alert:PGSQL 全局核心指标总览与告警事件一览

PGSQL Alert

pgsql-alert.jpg

PGSQL Shard:展示一个PGSQL 水平分片集群内的横向指标对比:例如 CITUS / GPSQL 集群。

PGSQL Shard

pgsql-shard.jpg


集群

PGSQL Cluster:一个PGSQL集群的主仪表板

PGSQL Cluster

pgsql-cluster.jpg

PGRDS Cluster:PGSQL Cluster 的RDS版本,专注于所有 PostgreSQL 本身的指标

PGRDS Cluster

pgrds-cluster.jpg

PGSQL Service:关注PGSQL集群服务、代理、路由和负载均衡。

PGSQL Service

pgsql-service.jpg

PGSQL Activity:关注PGSQL集群的会话/负载/QPS/TPS/锁定情况

PGSQL Activity

pgsql-activity.jpg

PGSQL Replication:关注PGSQL集群复制、插槽和发布/订阅。

PGSQL Replication

pgsql-replication.jpg

PGSQL Databases:关注所有实例的数据库CRUD、慢查询和表统计信息。

PGSQL Databases

pgsql-databases.jpg

PGSQL Patroni:关注集群高可用状态,Patroni组件状态

PGSQL Patroni

pgsql-patroni.jpg

PGSQL PITR:关注集群 PITR 过程的上下文,用于辅助时间点恢复

PGSQL PITR

pgsql-patroni.jpg


实例

PGSQL Instance:单个PGSQL实例的主仪表板

PGSQL Instance

pgsql-instance.jpg

PGRDS Instance:PGSQL Instance 的RDS版本,专注于所有 PostgreSQL 本身的指标

PGRDS Instance

pgrds-instance.jpg

PGSQL Proxy:单个haproxy负载均衡器的详细指标

PGSQL Proxy

pgsql-proxy.jpg

PGSQL Pgbouncer:单个Pgbouncer连接池实例中的指标总览

PGSQL Pgbouncer

pgsql-pgbouncer.jpg

PGSQL Persist:持久性指标:WAL、XID、检查点、存档、IO

PGSQL Persist

pgsql-persist.jpg

PGSQL Xacts:关于事务、锁、TPS/QPS相关的指标

PGSQL Xacts

pgsql-xacts.jpg

PGSQL Session:单个实例中的会话和活动/空闲时间的指标

PGSQL Session

pgsql-session.jpg

PGSQL Exporter:Postgres/Pgbouncer 监控组件自我监控指标

PGSQL Exporter

pgsql-exporter.jpg


数据库

PGSQL Database:单个PGSQL数据库的主仪表板

PGSQL Database

pgsql-database.jpg

PGSQL Tables:单个数据库内的表/索引访问指标

PGSQL Tables

pgsql-tables.jpg

PGSQL Table:单个表的详细信息(QPS/RT/索引/序列…)

PGSQL Table

pgsql-table.jpg

PGSQL Query:单类查询的详细信息(QPS/RT)

PGSQL Query

pgsql-query.jpg


PGCAT

PGCAT Instance:直接从数据库目录获取的实例信息

PGCAT Instance

pgcat-instance.jpg

PGCAT Database:直接从数据库目录获取的数据库信息

PGCAT Database

pgcat-database.jpg

PGCAT Schema:直接从数据库目录获取关于模式的信息(表/索引/序列…)

PGCAT Schema

pgcat-schema.jpg

PGCAT Table:直接从数据库目录获取的单个表的详细信息(统计/膨胀…)

PGCAT Table

pgcat-table.jpg

PGCAT Query:直接从数据库目录获取的单类查询的详细信息(SQL/统计)

PGCAT Query

pgcat-query.jpg

PGCAT Locks:直接从数据库目录获取的关于活动与锁等待的信息

PGCAT Locks

pgcat-locks.jpg


PGLOG

PGLOG Overview:总览 Pigsty CMDB 中的CSV日志样本

PGLOG Overview

pglog-overview.jpg

PGLOG Overview:Pigsty CMDB 中的CSV日志样本中某一条会话的日志详情

PGLOG Session

pglog-session.jpg


画廊

详情请参考 pigsty/wiki/gallery

PGSQL Overview

pgsql-overview.jpg

PGSQL Shard

pgsql-shard.jpg

PGSQL Cluster

pgsql-cluster.jpg

PGSQL Service

pgsql-service.jpg

PGSQL Activity

pgsql-activity.jpg

PGSQL Replication

pgsql-replication.jpg

PGSQL Databases

pgsql-databases.jpg

PGSQL Instance

pgsql-instance.jpg

PGSQL Proxy

pgsql-proxy.jpg

PGSQL Pgbouncer

pgsql-pgbouncer.jpg

PGSQL Session

pgsql-session.jpg

PGSQL Xacts

pgsql-xacts.jpg

PGSQL Persist

pgsql-persist.jpg

PGSQL Database

pgsql-database.jpg

PGSQL Tables

pgsql-tables.jpg

PGSQL Table

pgsql-table.jpg

PGSQL Query

pgsql-query.jpg

PGCAT Instance

pgcat-instance.jpg

PGCAT Database

pgcat-database.jpg

PGCAT Schema

pgcat-schema.jpg

PGCAT Table

pgcat-table.jpg

PGCAT Lock

pgcat-locks.jpg

PGCAT Query

pgcat-query.jpg

PGLOG Overview

pglog-overview.jpg

PGLOG Session

pglog-session.jpg

12.1 - 总览面板

PostgreSQL 模块全局总览类监控面板

PostgreSQL 模块全局总览类监控面板,包括:

12.1.1 - PGSQL Overview

PGSQL 模块的主仪表板

PGSQL 模块的主仪表板:Demo

PGSQL Overview 是 PostgreSQL 模块的主仪表板,提供整个 PGSQL 模块的全局概览视图。

pgsql-overview

12.1.2 - PGSQL Alert

PGSQL 的全局关键指标和警报事件

PGSQL 的全局关键指标和警报事件:Demo

PGSQL Alert 仪表板展示 PGSQL 全局核心指标总览与告警事件一览。

pgsql-alert

12.1.3 - PGSQL Shard

关于水平分片的 PGSQL 集群的概览

关于水平分片的 PGSQL 集群的概览:Demo

PGSQL Shard 仪表板展示一个 PGSQL 水平分片集群内的横向指标对比,例如 Citus / GPSQL 集群。

pgsql-shard

12.2 - 集群面板

PostgreSQL 集群级别监控面板

PostgreSQL 集群级别监控面板,包括:

  • PGSQL Cluster:一个 PGSQL 集群的主仪表板
  • PGRDS Cluster:PGSQL Cluster 的 RDS 版本,专注于 PostgreSQL 本身的指标
  • PGSQL Activity:关注 PGSQL 集群的会话/负载/QPS/TPS/锁定情况
  • PGSQL Replication:关注 PGSQL 集群复制、插槽和发布/订阅
  • PGSQL Service:关注 PGSQL 集群服务、代理、路由和负载均衡
  • PGSQL Databases:关注所有实例的数据库 CRUD、慢查询和表统计信息
  • PGSQL Patroni:关注集群高可用状态,Patroni 组件状态
  • PGSQL PITR:关注集群 PITR 过程的上下文,用于辅助时间点恢复

12.2.1 - PGSQL Cluster

一个 PGSQL 集群的主仪表板

一个 PGSQL 集群的主仪表板:Demo

PGSQL Cluster 是单个 PostgreSQL 集群的主仪表板,提供集群级别的核心指标概览。

pgsql-cluster

12.2.2 - PGRDS Cluster

PGSQL Cluster 的 RDS 版本,专注于 PostgreSQL 本身的指标

PGSQL Cluster 的 RDS 版本:Demo

PGRDS Cluster 是 PGSQL Cluster 的 RDS 版本,专注于所有 PostgreSQL 本身的指标,适用于云数据库 RDS 监控场景。

pgrds-cluster

12.2.3 - PGSQL Activity

关注 PGSQL 集群的会话/负载/QPS/TPS/锁定情况

关注 PGSQL 集群的会话/负载/QPS/TPS/锁定情况:Demo

PGSQL Activity 仪表板关注 PGSQL 集群的会话、负载、QPS、TPS 以及锁定情况。

pgsql-activity

12.2.4 - PGSQL Replication

关注 PGSQL 集群复制、插槽和发布/订阅

关注 PGSQL 集群复制、插槽和发布/订阅:Demo

PGSQL Replication 仪表板关注 PGSQL 集群的复制状态、复制插槽和发布/订阅信息。

pgsql-replication

12.2.5 - PGSQL Service

关注 PGSQL 集群服务、代理、路由和负载均衡

关注 PGSQL 集群服务、代理、路由和负载均衡:Demo

PGSQL Service 仪表板关注 PGSQL 集群的服务、代理、路由和负载均衡状态。

pgsql-service

12.2.6 - PGSQL Databases

关注所有实例的数据库 CRUD、慢查询和表统计信息

关注所有实例的数据库 CRUD、慢查询和表统计信息:Demo

PGSQL Databases 仪表板关注集群中所有实例的数据库 CRUD、慢查询和表统计信息。

pgsql-databases

12.2.7 - PGSQL Patroni

关注集群高可用状态,Patroni 组件状态

关注集群高可用状态,Patroni 组件状态:Demo

PGSQL Patroni 仪表板关注集群的高可用状态以及 Patroni 组件的运行状态。

pgsql-patroni

12.2.8 - PGSQL PITR

关注集群 PITR 过程的上下文,用于辅助时间点恢复

关注集群 PITR 过程的上下文:Demo

PGSQL PITR 仪表板关注集群 PITR 过程的上下文,用于辅助时间点恢复操作。

pgsql-pitr

12.3 - 实例面板

PostgreSQL 实例级别监控面板

PostgreSQL 实例级别监控面板,包括:

12.3.1 - PGSQL Instance

单个 PGSQL 实例的主仪表板

单个 PGSQL 实例的主仪表板:Demo

PGSQL Instance 是单个 PostgreSQL 实例的主仪表板,提供实例级别的核心指标概览。

pgsql-instance

12.3.2 - PGRDS Instance

PGSQL Instance 的 RDS 版本,专注于 PostgreSQL 本身的指标

PGSQL Instance 的 RDS 版本:Demo

PGRDS Instance 是 PGSQL Instance 的 RDS 版本,专注于所有 PostgreSQL 本身的指标,适用于云数据库 RDS 监控场景。

pgrds-instance

12.3.3 - PGCAT Instance

直接从数据库目录获取的实例信息

直接从数据库目录获取的实例信息:Demo

PGCAT Instance 仪表板展示直接从数据库系统目录获取的实例信息。

pgcat-instance

12.3.4 - PGSQL Persist

持久性指标:WAL、XID、检查点、存档、IO

持久性指标:WAL、XID、检查点、存档、IO:Demo

PGSQL Persist 仪表板关注持久性相关指标:WAL、XID、检查点、存档和 IO。

pgsql-persist

12.3.5 - PGSQL Proxy

单个 HAProxy 负载均衡器的详细指标

单个 HAProxy 负载均衡器的详细指标:Demo

PGSQL Proxy 仪表板展示单个 HAProxy 负载均衡器的详细指标。

pgsql-proxy

12.3.6 - PGSQL Pgbouncer

单个 Pgbouncer 连接池实例中的指标总览

单个 Pgbouncer 连接池实例中的指标总览:Demo

PGSQL Pgbouncer 仪表板展示单个 Pgbouncer 连接池实例中的指标总览。

pgsql-pgbouncer

12.3.7 - PGSQL Session

单个实例中的会话和活动/空闲时间的指标

单个实例中的会话和活动/空闲时间的指标:Demo

PGSQL Session 仪表板展示单个实例中的会话和活动/空闲时间的指标。

pgsql-session

12.3.8 - PGSQL Xacts

关于事务、锁、TPS/QPS 相关的指标

关于事务、锁、TPS/QPS 相关的指标:Demo

PGSQL Xacts 仪表板关注事务、锁、TPS/QPS 相关的指标。

pgsql-xacts

12.3.9 - PGSQL Exporter

Postgres 与 Pgbouncer 监控组件自我监控指标

Postgres 与 Pgbouncer 监控组件自我监控指标:Demo

PGSQL Exporter 仪表板展示 Postgres 与 Pgbouncer 监控组件的自我监控指标。

pgsql-exporter

12.4 - 数据库面板

PostgreSQL 数据库级别监控面板

PostgreSQL 数据库级别监控面板,包括:

  • PGSQL Database:单个 PGSQL 数据库的主仪表板
  • PGCAT Database:直接从数据库目录获取的数据库信息
  • PGSQL Tables:单个数据库内的表/索引访问指标
  • PGSQL Table:单个表的详细信息(QPS/RT/索引/序列……)
  • PGCAT Table:直接从数据库目录获取的单个表的详细信息
  • PGSQL Query:单类查询的详细信息(QPS/RT)
  • PGCAT Query:直接从数据库目录获取的单类查询的详细信息
  • PGCAT Locks:直接从数据库目录获取的关于活动与锁等待的信息
  • PGCAT Schema:直接从数据库目录获取关于模式的信息

12.4.1 - PGSQL Database

单个 PGSQL 数据库的主仪表板

单个 PGSQL 数据库的主仪表板:Demo

PGSQL Database 是单个 PostgreSQL 数据库的主仪表板,提供数据库级别的核心指标概览。

pgsql-database

12.4.2 - PGCAT Database

直接从数据库目录获取的数据库信息

直接从数据库目录获取的数据库信息:Demo

PGCAT Database 仪表板展示直接从数据库系统目录获取的数据库信息。

pgcat-database

12.4.3 - PGSQL Tables

单个数据库内的表/索引访问指标

单个数据库内的表/索引访问指标:Demo

PGSQL Tables 仪表板展示单个数据库内的表和索引访问指标。

pgsql-tables

12.4.4 - PGSQL Table

单个表的详细信息(QPS/RT/索引/序列……)

单个表的详细信息:Demo

PGSQL Table 仪表板展示单个表的详细信息,包括 QPS、RT、索引、序列等指标。

pgsql-table

12.4.5 - PGCAT Table

直接从数据库目录获取的单个表的详细信息

直接从数据库目录获取的单个表的详细信息:Demo

PGCAT Table 仪表板展示直接从数据库系统目录获取的单个表的详细信息,包括统计和膨胀信息。

pgcat-table

12.4.6 - PGSQL Query

单类查询的详细信息(QPS/RT)

单类查询的详细信息:Demo

PGSQL Query 仪表板展示单类查询的详细信息,包括 QPS 和 RT 指标。

pgsql-query

12.4.7 - PGCAT Query

直接从数据库目录获取的单类查询的详细信息

直接从数据库目录获取的单类查询的详细信息:Demo

PGCAT Query 仪表板展示直接从数据库系统目录获取的单类查询的详细信息,包括 SQL 和统计信息。

pgcat-query

12.4.8 - PGCAT Locks

直接从数据库目录获取的关于活动与锁等待的信息

直接从数据库目录获取的关于活动与锁等待的信息:Demo

PGCAT Locks 仪表板展示直接从数据库系统目录获取的关于活动与锁等待的信息。

pgcat-locks

12.4.9 - PGCAT Schema

直接从数据库目录获取关于模式的信息

直接从数据库目录获取关于模式的信息:Demo

PGCAT Schema 仪表板展示直接从数据库系统目录获取的关于模式的信息,包括表、索引、序列等。

pgcat-schema

13 - 指标列表

Pigsty PGSQL 模块提供的完整监控指标列表与释义

PGSQL 模块包含有 638 类可用监控指标。

Metric NameTypeLabelsDescription
ALERTSUnknowncategory, job, level, ins, severity, ip, alertname, alertstate, instance, clsN/A
ALERTS_FOR_STATEUnknowncategory, job, level, ins, severity, ip, alertname, instance, clsN/A
cls:pressure1Unknownjob, clsN/A
cls:pressure15Unknownjob, clsN/A
cls:pressure5Unknownjob, clsN/A
go_gc_duration_secondssummaryjob, ins, ip, instance, quantile, clsA summary of the pause duration of garbage collection cycles.
go_gc_duration_seconds_countUnknownjob, ins, ip, instance, clsN/A
go_gc_duration_seconds_sumUnknownjob, ins, ip, instance, clsN/A
go_goroutinesgaugejob, ins, ip, instance, clsNumber of goroutines that currently exist.
go_infogaugeversion, job, ins, ip, instance, clsInformation about the Go environment.
go_memstats_alloc_bytesgaugejob, ins, ip, instance, clsNumber of bytes allocated and still in use.
go_memstats_alloc_bytes_totalcounterjob, ins, ip, instance, clsTotal number of bytes allocated, even if freed.
go_memstats_buck_hash_sys_bytesgaugejob, ins, ip, instance, clsNumber of bytes used by the profiling bucket hash table.
go_memstats_frees_totalcounterjob, ins, ip, instance, clsTotal number of frees.
go_memstats_gc_sys_bytesgaugejob, ins, ip, instance, clsNumber of bytes used for garbage collection system metadata.
go_memstats_heap_alloc_bytesgaugejob, ins, ip, instance, clsNumber of heap bytes allocated and still in use.
go_memstats_heap_idle_bytesgaugejob, ins, ip, instance, clsNumber of heap bytes waiting to be used.
go_memstats_heap_inuse_bytesgaugejob, ins, ip, instance, clsNumber of heap bytes that are in use.
go_memstats_heap_objectsgaugejob, ins, ip, instance, clsNumber of allocated objects.
go_memstats_heap_released_bytesgaugejob, ins, ip, instance, clsNumber of heap bytes released to OS.
go_memstats_heap_sys_bytesgaugejob, ins, ip, instance, clsNumber of heap bytes obtained from system.
go_memstats_last_gc_time_secondsgaugejob, ins, ip, instance, clsNumber of seconds since 1970 of last garbage collection.
go_memstats_lookups_totalcounterjob, ins, ip, instance, clsTotal number of pointer lookups.
go_memstats_mallocs_totalcounterjob, ins, ip, instance, clsTotal number of mallocs.
go_memstats_mcache_inuse_bytesgaugejob, ins, ip, instance, clsNumber of bytes in use by mcache structures.
go_memstats_mcache_sys_bytesgaugejob, ins, ip, instance, clsNumber of bytes used for mcache structures obtained from system.
go_memstats_mspan_inuse_bytesgaugejob, ins, ip, instance, clsNumber of bytes in use by mspan structures.
go_memstats_mspan_sys_bytesgaugejob, ins, ip, instance, clsNumber of bytes used for mspan structures obtained from system.
go_memstats_next_gc_bytesgaugejob, ins, ip, instance, clsNumber of heap bytes when next garbage collection will take place.
go_memstats_other_sys_bytesgaugejob, ins, ip, instance, clsNumber of bytes used for other system allocations.
go_memstats_stack_inuse_bytesgaugejob, ins, ip, instance, clsNumber of bytes in use by the stack allocator.
go_memstats_stack_sys_bytesgaugejob, ins, ip, instance, clsNumber of bytes obtained from system for stack allocator.
go_memstats_sys_bytesgaugejob, ins, ip, instance, clsNumber of bytes obtained from system.
go_threadsgaugejob, ins, ip, instance, clsNumber of OS threads created.
ins:pressure1Unknownjob, ins, ip, clsN/A
ins:pressure15Unknownjob, ins, ip, clsN/A
ins:pressure5Unknownjob, ins, ip, clsN/A
patroni_cluster_unlockedgaugejob, ins, ip, instance, cls, scopeValue is 1 if the cluster is unlocked, 0 if locked.
patroni_dcs_last_seengaugejob, ins, ip, instance, cls, scopeEpoch timestamp when DCS was last contacted successfully by Patroni.
patroni_failsafe_mode_is_activegaugejob, ins, ip, instance, cls, scopeValue is 1 if failsafe mode is active, 0 if inactive.
patroni_is_pausedgaugejob, ins, ip, instance, cls, scopeValue is 1 if auto failover is disabled, 0 otherwise.
patroni_mastergaugejob, ins, ip, instance, cls, scopeValue is 1 if this node is the leader, 0 otherwise.
patroni_pending_restartgaugejob, ins, ip, instance, cls, scopeValue is 1 if the node needs a restart, 0 otherwise.
patroni_postgres_in_archive_recoverygaugejob, ins, ip, instance, cls, scopeValue is 1 if Postgres is replicating from archive, 0 otherwise.
patroni_postgres_runninggaugejob, ins, ip, instance, cls, scopeValue is 1 if Postgres is running, 0 otherwise.
patroni_postgres_server_versiongaugejob, ins, ip, instance, cls, scopeVersion of Postgres (if running), 0 otherwise.
patroni_postgres_streaminggaugejob, ins, ip, instance, cls, scopeValue is 1 if Postgres is streaming, 0 otherwise.
patroni_postgres_timelinecounterjob, ins, ip, instance, cls, scopePostgres timeline of this node (if running), 0 otherwise.
patroni_postmaster_start_timegaugejob, ins, ip, instance, cls, scopeEpoch seconds since Postgres started.
patroni_primarygaugejob, ins, ip, instance, cls, scopeValue is 1 if this node is the leader, 0 otherwise.
patroni_replicagaugejob, ins, ip, instance, cls, scopeValue is 1 if this node is a replica, 0 otherwise.
patroni_standby_leadergaugejob, ins, ip, instance, cls, scopeValue is 1 if this node is the standby_leader, 0 otherwise.
patroni_sync_standbygaugejob, ins, ip, instance, cls, scopeValue is 1 if this node is a sync standby replica, 0 otherwise.
patroni_upUnknownjob, ins, ip, instance, clsN/A
patroni_versiongaugejob, ins, ip, instance, cls, scopePatroni semver without periods.
patroni_xlog_locationcounterjob, ins, ip, instance, cls, scopeCurrent location of the Postgres transaction log, 0 if this node is not the leader.
patroni_xlog_pausedgaugejob, ins, ip, instance, cls, scopeValue is 1 if the Postgres xlog is paused, 0 otherwise.
patroni_xlog_received_locationcounterjob, ins, ip, instance, cls, scopeCurrent location of the received Postgres transaction log, 0 if this node is not a replica.
patroni_xlog_replayed_locationcounterjob, ins, ip, instance, cls, scopeCurrent location of the replayed Postgres transaction log, 0 if this node is not a replica.
patroni_xlog_replayed_timestampgaugejob, ins, ip, instance, cls, scopeCurrent timestamp of the replayed Postgres transaction log, 0 if null.
pg:cls:active_backendsUnknownjob, clsN/A
pg:cls:active_time_rate15mUnknownjob, clsN/A
pg:cls:active_time_rate1mUnknownjob, clsN/A
pg:cls:active_time_rate5mUnknownjob, clsN/A
pg:cls:ageUnknownjob, clsN/A
pg:cls:buf_alloc_rate1mUnknownjob, clsN/A
pg:cls:buf_clean_rate1mUnknownjob, clsN/A
pg:cls:buf_flush_backend_rate1mUnknownjob, clsN/A
pg:cls:buf_flush_checkpoint_rate1mUnknownjob, clsN/A
pg:cls:cpu_countUnknownjob, clsN/A
pg:cls:cpu_usageUnknownjob, clsN/A
pg:cls:cpu_usage_15mUnknownjob, clsN/A
pg:cls:cpu_usage_1mUnknownjob, clsN/A
pg:cls:cpu_usage_5mUnknownjob, clsN/A
pg:cls:db_sizeUnknownjob, clsN/A
pg:cls:file_sizeUnknownjob, clsN/A
pg:cls:ixact_backendsUnknownjob, clsN/A
pg:cls:ixact_time_rate1mUnknownjob, clsN/A
pg:cls:lag_bytesUnknownjob, clsN/A
pg:cls:lag_secondsUnknownjob, clsN/A
pg:cls:leaderUnknownjob, ins, ip, instance, clsN/A
pg:cls:load1Unknownjob, clsN/A
pg:cls:load15Unknownjob, clsN/A
pg:cls:load5Unknownjob, clsN/A
pg:cls:lock_countUnknownjob, clsN/A
pg:cls:locksUnknownjob, cls, modeN/A
pg:cls:log_sizeUnknownjob, clsN/A
pg:cls:lsn_rate1mUnknownjob, clsN/A
pg:cls:membersUnknownjob, ins, ip, clsN/A
pg:cls:num_backendsUnknownjob, clsN/A
pg:cls:partitionUnknownjob, clsN/A
pg:cls:receiverUnknownstate, slot_name, job, appname, ip, cls, sender_host, sender_portN/A
pg:cls:rlock_countUnknownjob, clsN/A
pg:cls:saturation1Unknownjob, clsN/A
pg:cls:saturation15Unknownjob, clsN/A
pg:cls:saturation5Unknownjob, clsN/A
pg:cls:senderUnknownpid, usename, address, job, ins, appname, ip, clsN/A
pg:cls:session_time_rate1mUnknownjob, clsN/A
pg:cls:sizeUnknownjob, clsN/A
pg:cls:slot_countUnknownjob, clsN/A
pg:cls:slot_retained_bytesUnknownjob, clsN/A
pg:cls:standby_countUnknownjob, clsN/A
pg:cls:sync_stateUnknownjob, clsN/A
pg:cls:timelineUnknownjob, clsN/A
pg:cls:tup_deleted_rate1mUnknownjob, clsN/A
pg:cls:tup_fetched_rate1mUnknownjob, clsN/A
pg:cls:tup_inserted_rate1mUnknownjob, clsN/A
pg:cls:tup_modified_rate1mUnknownjob, clsN/A
pg:cls:tup_returned_rate1mUnknownjob, clsN/A
pg:cls:wal_sizeUnknownjob, clsN/A
pg:cls:xact_commit_rate15mUnknownjob, clsN/A
pg:cls:xact_commit_rate1mUnknownjob, clsN/A
pg:cls:xact_commit_rate5mUnknownjob, clsN/A
pg:cls:xact_rollback_rate15mUnknownjob, clsN/A
pg:cls:xact_rollback_rate1mUnknownjob, clsN/A
pg:cls:xact_rollback_rate5mUnknownjob, clsN/A
pg:cls:xact_total_rate15mUnknownjob, clsN/A
pg:cls:xact_total_rate1mUnknownjob, clsN/A
pg:cls:xact_total_sigma15mUnknownjob, clsN/A
pg:cls:xlock_countUnknownjob, clsN/A
pg:db:active_backendsUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:active_time_rate15mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:active_time_rate1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:active_time_rate5mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:ageUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:age_deriv1hUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:age_exhaustUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:blk_io_time_seconds_rate1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:blk_read_time_seconds_rate1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:blk_write_time_seconds_rate1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:blks_access_1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:blks_hit_1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:blks_hit_ratio1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:blks_read_1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:conn_limitUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:conn_usageUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:db_sizeUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:ixact_backendsUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:ixact_time_rate1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:lock_countUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:num_backendsUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:rlock_countUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:session_time_rate1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:temp_bytes_rate1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:temp_files_1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:tup_deleted_rate1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:tup_fetched_rate1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:tup_inserted_rate1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:tup_modified_rate1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:tup_returned_rate1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:wlock_countUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:xact_commit_rate15mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:xact_commit_rate1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:xact_commit_rate5mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:xact_rollback_rate15mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:xact_rollback_rate1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:xact_rollback_rate5mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:xact_total_rate15mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:xact_total_rate1mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:xact_total_rate5mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:xact_total_sigma15mUnknowndatname, job, ins, ip, instance, clsN/A
pg:db:xlock_countUnknowndatname, job, ins, ip, instance, clsN/A
pg:env:active_backendsUnknownjobN/A
pg:env:active_time_rate15mUnknownjobN/A
pg:env:active_time_rate1mUnknownjobN/A
pg:env:active_time_rate5mUnknownjobN/A
pg:env:ageUnknownjobN/A
pg:env:cpu_countUnknownjobN/A
pg:env:cpu_usageUnknownjobN/A
pg:env:cpu_usage_15mUnknownjobN/A
pg:env:cpu_usage_1mUnknownjobN/A
pg:env:cpu_usage_5mUnknownjobN/A
pg:env:ixact_backendsUnknownjobN/A
pg:env:ixact_time_rate1mUnknownjobN/A
pg:env:lag_bytesUnknownjobN/A
pg:env:lag_secondsUnknownjobN/A
pg:env:lsn_rate1mUnknownjobN/A
pg:env:session_time_rate1mUnknownjobN/A
pg:env:tup_deleted_rate1mUnknownjobN/A
pg:env:tup_fetched_rate1mUnknownjobN/A
pg:env:tup_inserted_rate1mUnknownjobN/A
pg:env:tup_modified_rate1mUnknownjobN/A
pg:env:tup_returned_rate1mUnknownjobN/A
pg:env:xact_commit_rate15mUnknownjobN/A
pg:env:xact_commit_rate1mUnknownjobN/A
pg:env:xact_commit_rate5mUnknownjobN/A
pg:env:xact_rollback_rate15mUnknownjobN/A
pg:env:xact_rollback_rate1mUnknownjobN/A
pg:env:xact_rollback_rate5mUnknownjobN/A
pg:env:xact_total_rate15mUnknownjobN/A
pg:env:xact_total_rate1mUnknownjobN/A
pg:env:xact_total_sigma15mUnknownjobN/A
pg:ins:active_backendsUnknownjob, ins, ip, instance, clsN/A
pg:ins:active_time_rate15mUnknownjob, ins, ip, instance, clsN/A
pg:ins:active_time_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:active_time_rate5mUnknownjob, ins, ip, instance, clsN/A
pg:ins:ageUnknownjob, ins, ip, instance, clsN/A
pg:ins:blks_hit_ratio1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:buf_alloc_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:buf_clean_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:buf_flush_backend_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:buf_flush_checkpoint_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:ckpt_1hUnknownjob, ins, ip, instance, clsN/A
pg:ins:ckpt_req_1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:ckpt_timed_1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:conn_limitUnknownjob, ins, ip, instance, clsN/A
pg:ins:conn_usageUnknownjob, ins, ip, instance, clsN/A
pg:ins:cpu_countUnknownjob, ins, ip, instance, clsN/A
pg:ins:cpu_usageUnknownjob, ins, ip, instance, clsN/A
pg:ins:cpu_usage_15mUnknownjob, ins, ip, instance, clsN/A
pg:ins:cpu_usage_1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:cpu_usage_5mUnknownjob, ins, ip, instance, clsN/A
pg:ins:db_sizeUnknownjob, ins, ip, instance, clsN/A
pg:ins:file_sizeUnknownjob, ins, ip, instance, clsN/A
pg:ins:fs_sizeUnknownjob, ins, ip, instance, clsN/A
pg:ins:is_leaderUnknownjob, ins, ip, instance, clsN/A
pg:ins:ixact_backendsUnknownjob, ins, ip, instance, clsN/A
pg:ins:ixact_time_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:lag_bytesUnknownjob, ins, ip, instance, clsN/A
pg:ins:lag_secondsUnknownjob, ins, ip, instance, clsN/A
pg:ins:load1Unknownjob, ins, ip, instance, clsN/A
pg:ins:load15Unknownjob, ins, ip, instance, clsN/A
pg:ins:load5Unknownjob, ins, ip, instance, clsN/A
pg:ins:lock_countUnknownjob, ins, ip, instance, clsN/A
pg:ins:locksUnknownjob, ins, ip, mode, instance, clsN/A
pg:ins:log_sizeUnknownjob, ins, ip, instance, clsN/A
pg:ins:lsn_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:mem_sizeUnknownjob, ins, ip, instance, clsN/A
pg:ins:num_backendsUnknownjob, ins, ip, instance, clsN/A
pg:ins:rlock_countUnknownjob, ins, ip, instance, clsN/A
pg:ins:saturation1Unknownjob, ins, ip, clsN/A
pg:ins:saturation15Unknownjob, ins, ip, clsN/A
pg:ins:saturation5Unknownjob, ins, ip, clsN/A
pg:ins:session_time_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:slot_retained_bytesUnknownjob, ins, ip, instance, clsN/A
pg:ins:space_usageUnknownjob, ins, ip, instance, clsN/A
pg:ins:statusUnknownjob, ins, ip, instance, clsN/A
pg:ins:sync_stateUnknownjob, ins, instance, clsN/A
pg:ins:target_countUnknownjob, cls, insN/A
pg:ins:timelineUnknownjob, ins, ip, instance, clsN/A
pg:ins:tup_deleted_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:tup_fetched_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:tup_inserted_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:tup_modified_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:tup_returned_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:wal_sizeUnknownjob, ins, ip, instance, clsN/A
pg:ins:wlock_countUnknownjob, ins, ip, instance, clsN/A
pg:ins:xact_commit_rate15mUnknownjob, ins, ip, instance, clsN/A
pg:ins:xact_commit_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:xact_commit_rate5mUnknownjob, ins, ip, instance, clsN/A
pg:ins:xact_rollback_rate15mUnknownjob, ins, ip, instance, clsN/A
pg:ins:xact_rollback_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:xact_rollback_rate5mUnknownjob, ins, ip, instance, clsN/A
pg:ins:xact_total_rate15mUnknownjob, ins, ip, instance, clsN/A
pg:ins:xact_total_rate1mUnknownjob, ins, ip, instance, clsN/A
pg:ins:xact_total_rate5mUnknownjob, ins, ip, instance, clsN/A
pg:ins:xact_total_sigma15mUnknownjob, ins, ip, instance, clsN/A
pg:ins:xlock_countUnknownjob, ins, ip, instance, clsN/A
pg:query:call_rate1mUnknowndatname, query, job, ins, ip, instance, clsN/A
pg:query:rt_1mUnknowndatname, query, job, ins, ip, instance, clsN/A
pg:table:scan_rate1mUnknowndatname, relname, job, ins, ip, instance, clsN/A
pg_activity_countgaugedatname, state, job, ins, ip, instance, clsCount of connection among (datname,state)
pg_activity_max_conn_durationgaugedatname, state, job, ins, ip, instance, clsMax backend session duration since state change among (datname, state)
pg_activity_max_durationgaugedatname, state, job, ins, ip, instance, clsMax duration since last state change among (datname, state)
pg_activity_max_tx_durationgaugedatname, state, job, ins, ip, instance, clsMax transaction duration since state change among (datname, state)
pg_archiver_failed_countcounterjob, ins, ip, instance, clsNumber of failed attempts for archiving WAL files
pg_archiver_finish_countcounterjob, ins, ip, instance, clsNumber of WAL files that have been successfully archived
pg_archiver_last_failed_timecounterjob, ins, ip, instance, clsTime of the last failed archival operation
pg_archiver_last_finish_timecounterjob, ins, ip, instance, clsTime of the last successful archive operation
pg_archiver_reset_timegaugejob, ins, ip, instance, clsTime at which archive statistics were last reset
pg_backend_countgaugetype, job, ins, ip, instance, clsDatabase backend process count by backend_type
pg_bgwriter_buffers_alloccounterjob, ins, ip, instance, clsNumber of buffers allocated
pg_bgwriter_buffers_backendcounterjob, ins, ip, instance, clsNumber of buffers written directly by a backend
pg_bgwriter_buffers_backend_fsynccounterjob, ins, ip, instance, clsNumber of times a backend had to execute its own fsync call
pg_bgwriter_buffers_checkpointcounterjob, ins, ip, instance, clsNumber of buffers written during checkpoints
pg_bgwriter_buffers_cleancounterjob, ins, ip, instance, clsNumber of buffers written by the background writer
pg_bgwriter_checkpoint_sync_timecounterjob, ins, ip, instance, clsTotal amount of time that has been spent in the portion of checkpoint processing where files are synchronized to disk, in seconds
pg_bgwriter_checkpoint_write_timecounterjob, ins, ip, instance, clsTotal amount of time that has been spent in the portion of checkpoint processing where files are written to disk, in seconds
pg_bgwriter_checkpoints_reqcounterjob, ins, ip, instance, clsNumber of requested checkpoints that have been performed
pg_bgwriter_checkpoints_timedcounterjob, ins, ip, instance, clsNumber of scheduled checkpoints that have been performed
pg_bgwriter_maxwritten_cleancounterjob, ins, ip, instance, clsNumber of times the background writer stopped a cleaning scan because it had written too many buffers
pg_bgwriter_reset_timecounterjob, ins, ip, instance, clsTime at which bgwriter statistics were last reset
pg_boot_timegaugejob, ins, ip, instance, clsunix timestamp when postmaster boot
pg_checkpoint_checkpoint_lsncounterjob, ins, ip, instance, clsLatest checkpoint location
pg_checkpoint_elapsegaugejob, ins, ip, instance, clsSeconds elapsed since latest checkpoint in seconds
pg_checkpoint_full_page_writesgaugejob, ins, ip, instance, clsLatest checkpoint’s full_page_writes enabled
pg_checkpoint_newest_commit_ts_xidcounterjob, ins, ip, instance, clsLatest checkpoint’s newestCommitTsXid
pg_checkpoint_next_multi_offsetcounterjob, ins, ip, instance, clsLatest checkpoint’s NextMultiOffset
pg_checkpoint_next_multixact_idcounterjob, ins, ip, instance, clsLatest checkpoint’s NextMultiXactId
pg_checkpoint_next_oidcounterjob, ins, ip, instance, clsLatest checkpoint’s NextOID
pg_checkpoint_next_xidcounterjob, ins, ip, instance, clsLatest checkpoint’s NextXID xid
pg_checkpoint_next_xid_epochcounterjob, ins, ip, instance, clsLatest checkpoint’s NextXID epoch
pg_checkpoint_oldest_active_xidcounterjob, ins, ip, instance, clsLatest checkpoint’s oldestActiveXID
pg_checkpoint_oldest_commit_ts_xidcounterjob, ins, ip, instance, clsLatest checkpoint’s oldestCommitTsXid
pg_checkpoint_oldest_multi_dbidgaugejob, ins, ip, instance, clsLatest checkpoint’s oldestMulti’s DB OID
pg_checkpoint_oldest_multi_xidcounterjob, ins, ip, instance, clsLatest checkpoint’s oldestMultiXid
pg_checkpoint_oldest_xidcounterjob, ins, ip, instance, clsLatest checkpoint’s oldestXID
pg_checkpoint_oldest_xid_dbidgaugejob, ins, ip, instance, clsLatest checkpoint’s oldestXID’s DB OID
pg_checkpoint_prev_tlicounterjob, ins, ip, instance, clsLatest checkpoint’s PrevTimeLineID
pg_checkpoint_redo_lsncounterjob, ins, ip, instance, clsLatest checkpoint’s REDO location
pg_checkpoint_timecounterjob, ins, ip, instance, clsTime of latest checkpoint
pg_checkpoint_tlicounterjob, ins, ip, instance, clsLatest checkpoint’s TimeLineID
pg_conf_reload_timegaugejob, ins, ip, instance, clsseconds since last configuration reload
pg_db_active_timecounterdatname, job, ins, ip, instance, clsTime spent executing SQL statements in this database, in seconds
pg_db_agegaugedatname, job, ins, ip, instance, clsAge of database calculated from datfrozenxid
pg_db_allow_conngaugedatname, job, ins, ip, instance, clsIf false(0) then no one can connect to this database.
pg_db_blk_read_timecounterdatname, job, ins, ip, instance, clsTime spent reading data file blocks by backends in this database, in seconds
pg_db_blk_write_timecounterdatname, job, ins, ip, instance, clsTime spent writing data file blocks by backends in this database, in seconds
pg_db_blks_accesscounterdatname, job, ins, ip, instance, clsNumber of times disk blocks that accessed read+hit
pg_db_blks_hitcounterdatname, job, ins, ip, instance, clsNumber of times disk blocks were found already in the buffer cache
pg_db_blks_readcounterdatname, job, ins, ip, instance, clsNumber of disk blocks read in this database
pg_db_cks_fail_timegaugedatname, job, ins, ip, instance, clsTime at which the last data page checksum failure was detected in this database
pg_db_cks_failscounterdatname, job, ins, ip, instance, clsNumber of data page checksum failures detected in this database, -1 for not enabled
pg_db_confl_confl_bufferpincounterdatname, job, ins, ip, instance, clsNumber of queries in this database that have been canceled due to pinned buffers
pg_db_confl_confl_deadlockcounterdatname, job, ins, ip, instance, clsNumber of queries in this database that have been canceled due to deadlocks
pg_db_confl_confl_lockcounterdatname, job, ins, ip, instance, clsNumber of queries in this database that have been canceled due to lock timeouts
pg_db_confl_confl_snapshotcounterdatname, job, ins, ip, instance, clsNumber of queries in this database that have been canceled due to old snapshots
pg_db_confl_confl_tablespacecounterdatname, job, ins, ip, instance, clsNumber of queries in this database that have been canceled due to dropped tablespaces
pg_db_conflictscounterdatname, job, ins, ip, instance, clsNumber of queries canceled due to conflicts with recovery in this database
pg_db_conn_limitgaugedatname, job, ins, ip, instance, clsSets maximum number of concurrent connections that can be made to this database. -1 means no limit.
pg_db_datidgaugedatname, job, ins, ip, instance, clsOID of the database
pg_db_deadlockscounterdatname, job, ins, ip, instance, clsNumber of deadlocks detected in this database
pg_db_frozen_xidgaugedatname, job, ins, ip, instance, clsAll transaction IDs before this one have been frozened
pg_db_is_templategaugedatname, job, ins, ip, instance, clsIf true(1), then this database can be cloned by any user with CREATEDB privileges
pg_db_ixact_timecounterdatname, job, ins, ip, instance, clsTime spent idling while in a transaction in this database, in seconds
pg_db_numbackendsgaugedatname, job, ins, ip, instance, clsNumber of backends currently connected to this database
pg_db_reset_timecounterdatname, job, ins, ip, instance, clsTime at which database statistics were last reset
pg_db_session_timecounterdatname, job, ins, ip, instance, clsTime spent by database sessions in this database, in seconds
pg_db_sessionscounterdatname, job, ins, ip, instance, clsTotal number of sessions established to this database
pg_db_sessions_abandonedcounterdatname, job, ins, ip, instance, clsNumber of database sessions to this database that were terminated because connection to the client was lost
pg_db_sessions_fatalcounterdatname, job, ins, ip, instance, clsNumber of database sessions to this database that were terminated by fatal errors
pg_db_sessions_killedcounterdatname, job, ins, ip, instance, clsNumber of database sessions to this database that were terminated by operator intervention
pg_db_temp_bytescounterdatname, job, ins, ip, instance, clsTotal amount of data written to temporary files by queries in this database.
pg_db_temp_filescounterdatname, job, ins, ip, instance, clsNumber of temporary files created by queries in this database
pg_db_tup_deletedcounterdatname, job, ins, ip, instance, clsNumber of rows deleted by queries in this database
pg_db_tup_fetchedcounterdatname, job, ins, ip, instance, clsNumber of rows fetched by queries in this database
pg_db_tup_insertedcounterdatname, job, ins, ip, instance, clsNumber of rows inserted by queries in this database
pg_db_tup_modifiedcounterdatname, job, ins, ip, instance, clsNumber of rows modified by queries in this database
pg_db_tup_returnedcounterdatname, job, ins, ip, instance, clsNumber of rows returned by queries in this database
pg_db_tup_updatedcounterdatname, job, ins, ip, instance, clsNumber of rows updated by queries in this database
pg_db_xact_commitcounterdatname, job, ins, ip, instance, clsNumber of transactions in this database that have been committed
pg_db_xact_rollbackcounterdatname, job, ins, ip, instance, clsNumber of transactions in this database that have been rolled back
pg_db_xact_totalcounterdatname, job, ins, ip, instance, clsNumber of transactions in this database
pg_downstream_countgaugestate, job, ins, ip, instance, clsCount of corresponding state
pg_exporter_agent_upUnknownjob, ins, ip, instance, clsN/A
pg_exporter_last_scrape_timegaugejob, ins, ip, instance, clsseconds exporter spending on scrapping
pg_exporter_query_cache_ttlgaugedatname, query, job, ins, ip, instance, clstimes to live of query cache
pg_exporter_query_scrape_durationgaugedatname, query, job, ins, ip, instance, clsseconds query spending on scrapping
pg_exporter_query_scrape_error_countgaugedatname, query, job, ins, ip, instance, clstimes the query failed
pg_exporter_query_scrape_hit_countgaugedatname, query, job, ins, ip, instance, clsnumbers been scrapped from this query
pg_exporter_query_scrape_metric_countgaugedatname, query, job, ins, ip, instance, clsnumbers of metrics been scrapped from this query
pg_exporter_query_scrape_total_countgaugedatname, query, job, ins, ip, instance, clstimes exporter server was scraped for metrics
pg_exporter_scrape_durationgaugejob, ins, ip, instance, clsseconds exporter spending on scrapping
pg_exporter_scrape_error_countcounterjob, ins, ip, instance, clstimes exporter was scraped for metrics and failed
pg_exporter_scrape_total_countcounterjob, ins, ip, instance, clstimes exporter was scraped for metrics
pg_exporter_server_scrape_durationgaugedatname, job, ins, ip, instance, clsseconds exporter server spending on scrapping
pg_exporter_server_scrape_error_countUnknowndatname, job, ins, ip, instance, clsN/A
pg_exporter_server_scrape_total_countgaugedatname, job, ins, ip, instance, clstimes exporter server was scraped for metrics
pg_exporter_server_scrape_total_secondsgaugedatname, job, ins, ip, instance, clsseconds exporter server spending on scrapping
pg_exporter_upgaugejob, ins, ip, instance, clsalways be 1 if your could retrieve metrics
pg_exporter_uptimegaugejob, ins, ip, instance, clsseconds since exporter primary server inited
pg_flush_lsncounterjob, ins, ip, instance, clsprimary only, location of current wal syncing
pg_func_callscounterdatname, funcname, job, ins, ip, instance, clsNumber of times this function has been called
pg_func_self_timecounterdatname, funcname, job, ins, ip, instance, clsTotal time spent in this function itself, not including other functions called by it, in ms
pg_func_total_timecounterdatname, funcname, job, ins, ip, instance, clsTotal time spent in this function and all other functions called by it, in ms
pg_in_recoverygaugejob, ins, ip, instance, clsserver is in recovery mode? 1 for yes 0 for no
pg_index_idx_blks_hitcounterdatname, relname, job, ins, relid, ip, instance, cls, idxnameNumber of buffer hits in this index
pg_index_idx_blks_readcounterdatname, relname, job, ins, relid, ip, instance, cls, idxnameNumber of disk blocks read from this index
pg_index_idx_scancounterdatname, relname, job, ins, relid, ip, instance, cls, idxnameNumber of index scans initiated on this index
pg_index_idx_tup_fetchcounterdatname, relname, job, ins, relid, ip, instance, cls, idxnameNumber of live table rows fetched by simple index scans using this index
pg_index_idx_tup_readcounterdatname, relname, job, ins, relid, ip, instance, cls, idxnameNumber of index entries returned by scans on this index
pg_index_relpagesgaugedatname, relname, job, ins, relid, ip, instance, cls, idxnameSize of the on-disk representation of this index in pages
pg_index_reltuplesgaugedatname, relname, job, ins, relid, ip, instance, cls, idxnameEstimate relation tuples
pg_insert_lsncounterjob, ins, ip, instance, clsprimary only, location of current wal inserting
pg_io_evictionscountertype, job, ins, object, ip, context, instance, clsNumber of times a block has been written out from a shared or local buffer
pg_io_extend_timecountertype, job, ins, object, ip, context, instance, clsTime spent in extend operations in seconds
pg_io_extendscountertype, job, ins, object, ip, context, instance, clsNumber of relation extend operations, each of the size specified in op_bytes.
pg_io_fsync_timecountertype, job, ins, object, ip, context, instance, clsTime spent in fsync operations in seconds
pg_io_fsyncscountertype, job, ins, object, ip, context, instance, clsNumber of fsync calls. These are only tracked in context normal
pg_io_hitscountertype, job, ins, object, ip, context, instance, clsThe number of times a desired block was found in a shared buffer.
pg_io_op_bytesgaugetype, job, ins, object, ip, context, instance, clsThe number of bytes per unit of I/O read, written, or extended. 8192 by default
pg_io_read_timecountertype, job, ins, object, ip, context, instance, clsTime spent in read operations in seconds
pg_io_readscountertype, job, ins, object, ip, context, instance, clsNumber of read operations, each of the size specified in op_bytes.
pg_io_reset_timegaugetype, job, ins, object, ip, context, instance, clsTimestamp at which these statistics were last reset
pg_io_reusescountertype, job, ins, object, ip, context, instance, clsThe number of times an existing buffer in reused
pg_io_write_timecountertype, job, ins, object, ip, context, instance, clsTime spent in write operations in seconds
pg_io_writeback_timecountertype, job, ins, object, ip, context, instance, clsTime spent in writeback operations in seconds
pg_io_writebackscountertype, job, ins, object, ip, context, instance, clsNumber of units of size op_bytes which the process requested the kernel write out to permanent storage.
pg_io_writescountertype, job, ins, object, ip, context, instance, clsNumber of write operations, each of the size specified in op_bytes.
pg_is_in_recoverygaugejob, ins, ip, instance, cls1 if in recovery mode
pg_is_wal_replay_pausedgaugejob, ins, ip, instance, cls1 if wal play paused
pg_laggaugejob, ins, ip, instance, clsreplica only, replication lag in seconds
pg_last_replay_timegaugejob, ins, ip, instance, clstime when last transaction been replayed
pg_lock_countgaugedatname, job, ins, ip, mode, instance, clsNumber of locks of corresponding mode and database
pg_lsncounterjob, ins, ip, instance, clslog sequence number, current write location
pg_meta_infogaugecls, extensions, version, job, ins, primary_conninfo, conf_path, hba_path, ip, cluster_id, instance, listen_port, wal_level, ver_num, cluster_name, data_dirconstant 1
pg_query_callscounterdatname, query, job, ins, ip, instance, clsNumber of times the statement was executed
pg_query_exec_timecounterdatname, query, job, ins, ip, instance, clsTotal time spent executing the statement, in seconds
pg_query_io_timecounterdatname, query, job, ins, ip, instance, clsTotal time the statement spent reading and writing blocks, in seconds
pg_query_rowscounterdatname, query, job, ins, ip, instance, clsTotal number of rows retrieved or affected by the statement
pg_query_sblk_dirtiedcounterdatname, query, job, ins, ip, instance, clsTotal number of shared blocks dirtied by the statement
pg_query_sblk_hitcounterdatname, query, job, ins, ip, instance, clsTotal number of shared block cache hits by the statement
pg_query_sblk_readcounterdatname, query, job, ins, ip, instance, clsTotal number of shared blocks read by the statement
pg_query_sblk_writtencounterdatname, query, job, ins, ip, instance, clsTotal number of shared blocks written by the statement
pg_query_wal_bytescounterdatname, query, job, ins, ip, instance, clsTotal amount of WAL bytes generated by the statement
pg_receive_lsncounterjob, ins, ip, instance, clsreplica only, location of wal synced to disk
pg_recovery_backup_end_lsncounterjob, ins, ip, instance, clsBackup end location
pg_recovery_backup_start_lsncounterjob, ins, ip, instance, clsBackup start location
pg_recovery_min_lsncounterjob, ins, ip, instance, clsMinimum recovery ending location
pg_recovery_min_timelinecounterjob, ins, ip, instance, clsMin recovery ending loc’s timeline
pg_recovery_prefetch_block_distancegaugejob, ins, ip, instance, clsHow many blocks ahead the prefetcher is looking
pg_recovery_prefetch_hitcounterjob, ins, ip, instance, clsNumber of blocks not prefetched because they were already in the buffer pool
pg_recovery_prefetch_io_depthgaugejob, ins, ip, instance, clsHow many prefetches have been initiated but are not yet known to have completed
pg_recovery_prefetch_prefetchcounterjob, ins, ip, instance, clsNumber of blocks prefetched because they were not in the buffer pool
pg_recovery_prefetch_reset_timecounterjob, ins, ip, instance, clsTime at which these recovery prefetch statistics were last reset
pg_recovery_prefetch_skip_fpwgaugejob, ins, ip, instance, clsNumber of blocks not prefetched because a full page image was included in the WAL
pg_recovery_prefetch_skip_initcounterjob, ins, ip, instance, clsNumber of blocks not prefetched because they would be zero-initialized
pg_recovery_prefetch_skip_newcounterjob, ins, ip, instance, clsNumber of blocks not prefetched because they didn’t exist yet
pg_recovery_prefetch_skip_repcounterjob, ins, ip, instance, clsNumber of blocks not prefetched because they were already recently prefetched
pg_recovery_prefetch_wal_distancegaugejob, ins, ip, instance, clsHow many bytes ahead the prefetcher is looking
pg_recovery_require_recordgaugejob, ins, ip, instance, clsEnd-of-backup record required
pg_recv_flush_lsncounterstate, slot_name, job, ins, ip, instance, cls, sender_host, sender_portLast write-ahead log location already received and flushed to disk
pg_recv_flush_tlicounterstate, slot_name, job, ins, ip, instance, cls, sender_host, sender_portTimeline number of last write-ahead log location received and flushed to disk
pg_recv_init_lsncounterstate, slot_name, job, ins, ip, instance, cls, sender_host, sender_portFirst write-ahead log location used when WAL receiver is started
pg_recv_init_tlicounterstate, slot_name, job, ins, ip, instance, cls, sender_host, sender_portFirst timeline number used when WAL receiver is started
pg_recv_msg_recv_timegaugestate, slot_name, job, ins, ip, instance, cls, sender_host, sender_portReceipt time of last message received from origin WAL sender
pg_recv_msg_send_timegaugestate, slot_name, job, ins, ip, instance, cls, sender_host, sender_portSend time of last message received from origin WAL sender
pg_recv_pidgaugestate, slot_name, job, ins, ip, instance, cls, sender_host, sender_portProcess ID of the WAL receiver process
pg_recv_reported_lsncounterstate, slot_name, job, ins, ip, instance, cls, sender_host, sender_portLast write-ahead log location reported to origin WAL sender
pg_recv_reported_timegaugestate, slot_name, job, ins, ip, instance, cls, sender_host, sender_portTime of last write-ahead log location reported to origin WAL sender
pg_recv_timegaugestate, slot_name, job, ins, ip, instance, cls, sender_host, sender_portTime of current snapshot
pg_recv_write_lsncounterstate, slot_name, job, ins, ip, instance, cls, sender_host, sender_portLast write-ahead log location already received and written to disk, but not flushed.
pg_relkind_countgaugedatname, job, ins, ip, instance, cls, relkindNumber of relations of corresponding relkind
pg_repl_backend_xmincounterpid, usename, address, job, ins, appname, ip, instance, clsThis standby’s xmin horizon reported by hot_standby_feedback.
pg_repl_client_portgaugepid, usename, address, job, ins, appname, ip, instance, clsTCP port number that the client is using for communication with this WAL sender, or -1 if a Unix socket is used
pg_repl_flush_diffgaugepid, usename, address, job, ins, appname, ip, instance, clsLast log position flushed to disk by this standby server diff with current lsn
pg_repl_flush_laggaugepid, usename, address, job, ins, appname, ip, instance, clsTime elapsed between flushing recent WAL locally and receiving notification that this standby server has written and flushed it
pg_repl_flush_lsncounterpid, usename, address, job, ins, appname, ip, instance, clsLast write-ahead log location flushed to disk by this standby server
pg_repl_launch_timecounterpid, usename, address, job, ins, appname, ip, instance, clsTime when this process was started, i.e., when the client connected to this WAL sender
pg_repl_lsncounterpid, usename, address, job, ins, appname, ip, instance, clsCurrent log position on this server
pg_repl_replay_diffgaugepid, usename, address, job, ins, appname, ip, instance, clsLast log position replayed into the database on this standby server diff with current lsn
pg_repl_replay_laggaugepid, usename, address, job, ins, appname, ip, instance, clsTime elapsed between flushing recent WAL locally and receiving notification that this standby server has written, flushed and applied it
pg_repl_replay_lsncounterpid, usename, address, job, ins, appname, ip, instance, clsLast write-ahead log location replayed into the database on this standby server
pg_repl_reply_timegaugepid, usename, address, job, ins, appname, ip, instance, clsSend time of last reply message received from standby server
pg_repl_sent_diffgaugepid, usename, address, job, ins, appname, ip, instance, clsLast log position sent to this standby server diff with current lsn
pg_repl_sent_lsncounterpid, usename, address, job, ins, appname, ip, instance, clsLast write-ahead log location sent on this connection
pg_repl_stategaugepid, usename, address, job, ins, appname, ip, instance, clsCurrent WAL sender encoded state 0-4 for streaming startup catchup backup stopping
pg_repl_sync_prioritygaugepid, usename, address, job, ins, appname, ip, instance, clsPriority of this standby server for being chosen as the synchronous standby
pg_repl_sync_stategaugepid, usename, address, job, ins, appname, ip, instance, clsEncoded synchronous state of this standby server, 0-3 for async potential sync quorum
pg_repl_timecounterpid, usename, address, job, ins, appname, ip, instance, clsCurrent timestamp in unix epoch
pg_repl_write_diffgaugepid, usename, address, job, ins, appname, ip, instance, clsLast log position written to disk by this standby server diff with current lsn
pg_repl_write_laggaugepid, usename, address, job, ins, appname, ip, instance, clsTime elapsed between flushing recent WAL locally and receiving notification that this standby server has written it
pg_repl_write_lsncounterpid, usename, address, job, ins, appname, ip, instance, clsLast write-ahead log location written to disk by this standby server
pg_replay_lsncounterjob, ins, ip, instance, clsreplica only, location of wal applied
pg_seq_blks_hitcounterdatname, job, ins, ip, instance, cls, seqnameNumber of buffer hits in this sequence
pg_seq_blks_readcounterdatname, job, ins, ip, instance, cls, seqnameNumber of disk blocks read from this sequence
pg_seq_last_valuecounterdatname, job, ins, ip, instance, cls, seqnameThe last sequence value written to disk
pg_setting_block_sizegaugejob, ins, ip, instance, clspg page block size, 8192 by default
pg_setting_data_checksumsgaugejob, ins, ip, instance, clswhether data checksum is enabled, 1 enabled 0 disabled
pg_setting_max_connectionsgaugejob, ins, ip, instance, clsnumber of concurrent connections to the database server
pg_setting_max_locks_per_transactiongaugejob, ins, ip, instance, clsno more than this many distinct objects can be locked at any one time
pg_setting_max_prepared_transactionsgaugejob, ins, ip, instance, clsmaximum number of transactions that can be in the prepared state simultaneously
pg_setting_max_replication_slotsgaugejob, ins, ip, instance, clsmaximum number of replication slots
pg_setting_max_wal_sendersgaugejob, ins, ip, instance, clsmaximum number of concurrent connections from standby servers
pg_setting_max_worker_processesgaugejob, ins, ip, instance, clsmaximum number of background processes that the system can support
pg_setting_wal_log_hintsgaugejob, ins, ip, instance, clswhether wal_log_hints is enabled, 1 enabled 0 disabled
pg_size_bytesgaugedatname, job, ins, ip, instance, clsFile size in bytes
pg_slot_activegaugeslot_name, job, ins, ip, instance, clsTrue(1) if this slot is currently actively being used
pg_slot_catalog_xmincounterslot_name, job, ins, ip, instance, clsThe oldest transaction affecting the system catalogs that this slot needs the database to retain.
pg_slot_confirm_lsncounterslot_name, job, ins, ip, instance, clsThe address (LSN) up to which the logical slot’s consumer has confirmed receiving data.
pg_slot_reset_timecounterslot_name, job, ins, ip, instance, clsWhen statistics were last reset
pg_slot_restart_lsncounterslot_name, job, ins, ip, instance, clsThe address (LSN) of oldest WAL which still might be required by the consumer of this slot
pg_slot_retained_bytesgaugeslot_name, job, ins, ip, instance, clsSize of bytes that retained for this slot
pg_slot_safe_wal_sizegaugeslot_name, job, ins, ip, instance, clsbytes that can be written to WAL which will not make slot into lost
pg_slot_spill_bytescounterslot_name, job, ins, ip, instance, clsBytes that spilled to disk due to logical decode mem exceeding
pg_slot_spill_countcounterslot_name, job, ins, ip, instance, clsXacts that spilled to disk due to logical decode mem exceeding (a xact can be spilled multiple times)
pg_slot_spill_txnscounterslot_name, job, ins, ip, instance, clsXacts that spilled to disk due to logical decode mem exceeding (subtrans included)
pg_slot_stream_bytescounterslot_name, job, ins, ip, instance, clsBytes that streamed to decoding output plugin after mem exceed
pg_slot_stream_countcounterslot_name, job, ins, ip, instance, clsXacts that streamed to decoding output plugin after mem exceed (a xact can be streamed multiple times)
pg_slot_stream_txnscounterslot_name, job, ins, ip, instance, clsXacts that streamed to decoding output plugin after mem exceed
pg_slot_temporarygaugeslot_name, job, ins, ip, instance, clsTrue(1) if this is a temporary replication slot.
pg_slot_total_bytescounterslot_name, job, ins, ip, instance, clsNumber of decoded bytes sent to the decoding output plugin for this slot
pg_slot_total_txnscounterslot_name, job, ins, ip, instance, clsNumber of decoded xacts sent to the decoding output plugin for this slot
pg_slot_wal_statusgaugeslot_name, job, ins, ip, instance, clsWAL reserve status 0-3 means reserved,extended,unreserved,lost, -1 means other
pg_slot_xmincounterslot_name, job, ins, ip, instance, clsThe oldest transaction that this slot needs the database to retain.
pg_slru_blks_existscounterjob, ins, ip, instance, clsNumber of blocks checked for existence for this SLRU
pg_slru_blks_hitcounterjob, ins, ip, instance, clsNumber of times disk blocks were found already in the SLRU, so that a read was not necessary
pg_slru_blks_readcounterjob, ins, ip, instance, clsNumber of disk blocks read for this SLRU
pg_slru_blks_writtencounterjob, ins, ip, instance, clsNumber of disk blocks written for this SLRU
pg_slru_blks_zeroedcounterjob, ins, ip, instance, clsNumber of blocks zeroed during initializations
pg_slru_flushescounterjob, ins, ip, instance, clsNumber of flushes of dirty data for this SLRU
pg_slru_reset_timecounterjob, ins, ip, instance, clsTime at which these statistics were last reset
pg_slru_truncatescounterjob, ins, ip, instance, clsNumber of truncates for this SLRU
pg_ssl_disabledgaugejob, ins, ip, instance, clsNumber of client connection that does not use ssl
pg_ssl_enabledgaugejob, ins, ip, instance, clsNumber of client connection that use ssl
pg_sync_standby_enabledgaugejob, ins, ip, names, instance, clsSynchronous commit enabled, 1 if enabled, 0 if disabled
pg_table_agegaugedatname, relname, job, ins, ip, instance, clsAge of this table in vacuum cycles
pg_table_analyze_countcounterdatname, relname, job, ins, ip, instance, clsNumber of times this table has been manually analyzed
pg_table_autoanalyze_countcounterdatname, relname, job, ins, ip, instance, clsNumber of times this table has been analyzed by the autovacuum daemon
pg_table_autovacuum_countcounterdatname, relname, job, ins, ip, instance, clsNumber of times this table has been vacuumed by the autovacuum daemon
pg_table_frozenxidcounterdatname, relname, job, ins, ip, instance, clsAll txid before this have been frozen on this table
pg_table_heap_blks_hitcounterdatname, relname, job, ins, ip, instance, clsNumber of buffer hits in this table
pg_table_heap_blks_readcounterdatname, relname, job, ins, ip, instance, clsNumber of disk blocks read from this table
pg_table_idx_blks_hitcounterdatname, relname, job, ins, ip, instance, clsNumber of buffer hits in all indexes on this table
pg_table_idx_blks_readcounterdatname, relname, job, ins, ip, instance, clsNumber of disk blocks read from all indexes on this table
pg_table_idx_scancounterdatname, relname, job, ins, ip, instance, clsNumber of index scans initiated on this table
pg_table_idx_tup_fetchcounterdatname, relname, job, ins, ip, instance, clsNumber of live rows fetched by index scans
pg_table_kindgaugedatname, relname, job, ins, ip, instance, clsRelation kind r/table/114
pg_table_n_dead_tupgaugedatname, relname, job, ins, ip, instance, clsEstimated number of dead rows
pg_table_n_ins_since_vacuumgaugedatname, relname, job, ins, ip, instance, clsEstimated number of rows inserted since this table was last vacuumed
pg_table_n_live_tupgaugedatname, relname, job, ins, ip, instance, clsEstimated number of live rows
pg_table_n_mod_since_analyzegaugedatname, relname, job, ins, ip, instance, clsEstimated number of rows modified since this table was last analyzed
pg_table_n_tup_delcounterdatname, relname, job, ins, ip, instance, clsNumber of rows deleted
pg_table_n_tup_hot_updcounterdatname, relname, job, ins, ip, instance, clsNumber of rows HOT updated (i.e with no separate index update required)
pg_table_n_tup_inscounterdatname, relname, job, ins, ip, instance, clsNumber of rows inserted
pg_table_n_tup_modcounterdatname, relname, job, ins, ip, instance, clsNumber of rows modified (insert + update + delete)
pg_table_n_tup_newpage_updcounterdatname, relname, job, ins, ip, instance, clsNumber of rows updated where the successor version goes onto a new heap page
pg_table_n_tup_updcounterdatname, relname, job, ins, ip, instance, clsNumber of rows updated (includes HOT updated rows)
pg_table_ncolsgaugedatname, relname, job, ins, ip, instance, clsNumber of columns in the table
pg_table_pagesgaugedatname, relname, job, ins, ip, instance, clsSize of the on-disk representation of this table in pages
pg_table_relidgaugedatname, relname, job, ins, ip, instance, clsRelation oid of this table
pg_table_seq_scancounterdatname, relname, job, ins, ip, instance, clsNumber of sequential scans initiated on this table
pg_table_seq_tup_readcounterdatname, relname, job, ins, ip, instance, clsNumber of live rows fetched by sequential scans
pg_table_size_bytesgaugedatname, relname, job, ins, ip, instance, clsTotal bytes of this table (including toast, index, toast index)
pg_table_size_indexsizegaugedatname, relname, job, ins, ip, instance, clsBytes of all related indexes of this table
pg_table_size_relsizegaugedatname, relname, job, ins, ip, instance, clsBytes of this table itself (main, vm, fsm)
pg_table_size_toastsizegaugedatname, relname, job, ins, ip, instance, clsBytes of toast tables of this table
pg_table_tbl_scancounterdatname, relname, job, ins, ip, instance, clsNumber of scans initiated on this table
pg_table_tup_readcounterdatname, relname, job, ins, ip, instance, clsNumber of live rows fetched by scans
pg_table_tuplescounterdatname, relname, job, ins, ip, instance, clsAll txid before this have been frozen on this table
pg_table_vacuum_countcounterdatname, relname, job, ins, ip, instance, clsNumber of times this table has been manually vacuumed (not counting VACUUM FULL)
pg_timestampgaugejob, ins, ip, instance, clsdatabase current timestamp
pg_upgaugejob, ins, ip, instance, clslast scrape was able to connect to the server: 1 for yes, 0 for no
pg_uptimegaugejob, ins, ip, instance, clsseconds since postmaster start
pg_versiongaugejob, ins, ip, instance, clsserver version number
pg_wait_countgaugedatname, job, ins, event, ip, instance, clsCount of WaitEvent on target database
pg_wal_buffers_fullcounterjob, ins, ip, instance, clsNumber of times WAL data was written to disk because WAL buffers became full
pg_wal_bytescounterjob, ins, ip, instance, clsTotal amount of WAL generated in bytes
pg_wal_fpicounterjob, ins, ip, instance, clsTotal number of WAL full page images generated
pg_wal_recordscounterjob, ins, ip, instance, clsTotal number of WAL records generated
pg_wal_reset_timecounterjob, ins, ip, instance, clsWhen statistics were last reset
pg_wal_synccounterjob, ins, ip, instance, clsNumber of times WAL files were synced to disk via issue_xlog_fsync request
pg_wal_sync_timecounterjob, ins, ip, instance, clsTotal amount of time spent syncing WAL files to disk via issue_xlog_fsync request, in seconds
pg_wal_writecounterjob, ins, ip, instance, clsNumber of times WAL buffers were written out to disk via XLogWrite request.
pg_wal_write_timecounterjob, ins, ip, instance, clsTotal amount of time spent writing WAL buffers to disk via XLogWrite request in seconds
pg_write_lsncounterjob, ins, ip, instance, clsprimary only, location of current wal writing
pg_xact_xmaxcounterjob, ins, ip, instance, clsFirst as-yet-unassigned txid. txid >= this are invisible.
pg_xact_xmincounterjob, ins, ip, instance, clsEarliest txid that is still active
pg_xact_xnumgaugejob, ins, ip, instance, clsCurrent active transaction count
pgbouncer:cls:load1Unknownjob, clsN/A
pgbouncer:cls:load15Unknownjob, clsN/A
pgbouncer:cls:load5Unknownjob, clsN/A
pgbouncer:db:conn_usageUnknowndatname, job, ins, ip, instance, host, cls, real_datname, portN/A
pgbouncer:db:conn_usage_reserveUnknowndatname, job, ins, ip, instance, host, cls, real_datname, portN/A
pgbouncer:db:pool_current_connUnknowndatname, job, ins, ip, instance, host, cls, real_datname, portN/A
pgbouncer:db:pool_disabledUnknowndatname, job, ins, ip, instance, host, cls, real_datname, portN/A
pgbouncer:db:pool_max_connUnknowndatname, job, ins, ip, instance, host, cls, real_datname, portN/A
pgbouncer:db:pool_pausedUnknowndatname, job, ins, ip, instance, host, cls, real_datname, portN/A
pgbouncer:db:pool_reserve_sizeUnknowndatname, job, ins, ip, instance, host, cls, real_datname, portN/A
pgbouncer:db:pool_sizeUnknowndatname, job, ins, ip, instance, host, cls, real_datname, portN/A
pgbouncer:ins:free_clientsUnknownjob, ins, ip, instance, clsN/A
pgbouncer:ins:free_serversUnknownjob, ins, ip, instance, clsN/A
pgbouncer:ins:load1Unknownjob, ins, ip, instance, clsN/A
pgbouncer:ins:load15Unknownjob, ins, ip, instance, clsN/A
pgbouncer:ins:load5Unknownjob, ins, ip, instance, clsN/A
pgbouncer:ins:login_clientsUnknownjob, ins, ip, instance, clsN/A
pgbouncer:ins:pool_databasesUnknownjob, ins, ip, instance, clsN/A
pgbouncer:ins:pool_usersUnknownjob, ins, ip, instance, clsN/A
pgbouncer:ins:poolsUnknownjob, ins, ip, instance, clsN/A
pgbouncer:ins:used_clientsUnknownjob, ins, ip, instance, clsN/A
pgbouncer_database_current_connectionsgaugedatname, job, ins, ip, instance, host, cls, real_datname, portCurrent number of connections for this database
pgbouncer_database_disabledgaugedatname, job, ins, ip, instance, host, cls, real_datname, portTrue(1) if this database is currently disabled, else 0
pgbouncer_database_max_connectionsgaugedatname, job, ins, ip, instance, host, cls, real_datname, portMaximum number of allowed connections for this database
pgbouncer_database_min_pool_sizegaugedatname, job, ins, ip, instance, host, cls, real_datname, portMinimum number of server connections
pgbouncer_database_pausedgaugedatname, job, ins, ip, instance, host, cls, real_datname, portTrue(1) if this database is currently paused, else 0
pgbouncer_database_pool_sizegaugedatname, job, ins, ip, instance, host, cls, real_datname, portMaximum number of server connections
pgbouncer_database_reserve_poolgaugedatname, job, ins, ip, instance, host, cls, real_datname, portMaximum number of additional connections for this database
pgbouncer_exporter_agent_upUnknownjob, ins, ip, instance, clsN/A
pgbouncer_exporter_last_scrape_timegaugejob, ins, ip, instance, clsseconds exporter spending on scrapping
pgbouncer_exporter_query_cache_ttlgaugedatname, query, job, ins, ip, instance, clstimes to live of query cache
pgbouncer_exporter_query_scrape_durationgaugedatname, query, job, ins, ip, instance, clsseconds query spending on scrapping
pgbouncer_exporter_query_scrape_error_countgaugedatname, query, job, ins, ip, instance, clstimes the query failed
pgbouncer_exporter_query_scrape_hit_countgaugedatname, query, job, ins, ip, instance, clsnumbers been scrapped from this query
pgbouncer_exporter_query_scrape_metric_countgaugedatname, query, job, ins, ip, instance, clsnumbers of metrics been scrapped from this query
pgbouncer_exporter_query_scrape_total_countgaugedatname, query, job, ins, ip, instance, clstimes exporter server was scraped for metrics
pgbouncer_exporter_scrape_durationgaugejob, ins, ip, instance, clsseconds exporter spending on scrapping
pgbouncer_exporter_scrape_error_countcounterjob, ins, ip, instance, clstimes exporter was scraped for metrics and failed
pgbouncer_exporter_scrape_total_countcounterjob, ins, ip, instance, clstimes exporter was scraped for metrics
pgbouncer_exporter_server_scrape_durationgaugedatname, job, ins, ip, instance, clsseconds exporter server spending on scrapping
pgbouncer_exporter_server_scrape_total_countgaugedatname, job, ins, ip, instance, clstimes exporter server was scraped for metrics
pgbouncer_exporter_server_scrape_total_secondsgaugedatname, job, ins, ip, instance, clsseconds exporter server spending on scrapping
pgbouncer_exporter_upgaugejob, ins, ip, instance, clsalways be 1 if your could retrieve metrics
pgbouncer_exporter_uptimegaugejob, ins, ip, instance, clsseconds since exporter primary server inited
pgbouncer_in_recoverygaugejob, ins, ip, instance, clsserver is in recovery mode? 1 for yes 0 for no
pgbouncer_list_itemsgaugejob, ins, ip, instance, list, clsNumber of corresponding pgbouncer object
pgbouncer_pool_active_cancel_clientsgaugedatname, job, ins, ip, instance, user, cls, pool_modeClient connections that have forwarded query cancellations to the server and are waiting for the server response.
pgbouncer_pool_active_cancel_serversgaugedatname, job, ins, ip, instance, user, cls, pool_modeServer connections that are currently forwarding a cancel request
pgbouncer_pool_active_clientsgaugedatname, job, ins, ip, instance, user, cls, pool_modeClient connections that are linked to server connection and can process queries
pgbouncer_pool_active_serversgaugedatname, job, ins, ip, instance, user, cls, pool_modeServer connections that are linked to a client
pgbouncer_pool_cancel_clientsgaugedatname, job, ins, ip, instance, user, cls, pool_modeClient connections that have not forwarded query cancellations to the server yet.
pgbouncer_pool_cancel_serversgaugedatname, job, ins, ip, instance, user, cls, pool_modecancel requests have completed that were sent to cancel a query on this server
pgbouncer_pool_idle_serversgaugedatname, job, ins, ip, instance, user, cls, pool_modeServer connections that are unused and immediately usable for client queries
pgbouncer_pool_login_serversgaugedatname, job, ins, ip, instance, user, cls, pool_modeServer connections currently in the process of logging in
pgbouncer_pool_maxwaitgaugedatname, job, ins, ip, instance, user, cls, pool_modeHow long the first(oldest) client in the queue has waited, in seconds, key metric
pgbouncer_pool_maxwait_usgaugedatname, job, ins, ip, instance, user, cls, pool_modeMicrosecond part of the maximum waiting time.
pgbouncer_pool_tested_serversgaugedatname, job, ins, ip, instance, user, cls, pool_modeServer connections that are currently running reset or check query
pgbouncer_pool_used_serversgaugedatname, job, ins, ip, instance, user, cls, pool_modeServer connections that have been idle for more than server_check_delay (means have to run check query)
pgbouncer_pool_waiting_clientsgaugedatname, job, ins, ip, instance, user, cls, pool_modeClient connections that have sent queries but have not yet got a server connection
pgbouncer_stat_avg_query_countgaugedatname, job, ins, ip, instance, clsAverage queries per second in last stat period
pgbouncer_stat_avg_query_timegaugedatname, job, ins, ip, instance, clsAverage query duration, in seconds
pgbouncer_stat_avg_recvgaugedatname, job, ins, ip, instance, clsAverage received (from clients) bytes per second
pgbouncer_stat_avg_sentgaugedatname, job, ins, ip, instance, clsAverage sent (to clients) bytes per second
pgbouncer_stat_avg_wait_timegaugedatname, job, ins, ip, instance, clsTime spent by clients waiting for a server, in seconds (average per second).
pgbouncer_stat_avg_xact_countgaugedatname, job, ins, ip, instance, clsAverage transactions per second in last stat period
pgbouncer_stat_avg_xact_timegaugedatname, job, ins, ip, instance, clsAverage transaction duration, in seconds
pgbouncer_stat_total_query_countgaugedatname, job, ins, ip, instance, clsTotal number of SQL queries pooled by pgbouncer
pgbouncer_stat_total_query_timecounterdatname, job, ins, ip, instance, clsTotal number of seconds spent when executing queries
pgbouncer_stat_total_receivedcounterdatname, job, ins, ip, instance, clsTotal volume in bytes of network traffic received by pgbouncer
pgbouncer_stat_total_sentcounterdatname, job, ins, ip, instance, clsTotal volume in bytes of network traffic sent by pgbouncer
pgbouncer_stat_total_wait_timecounterdatname, job, ins, ip, instance, clsTime spent by clients waiting for a server, in seconds
pgbouncer_stat_total_xact_countgaugedatname, job, ins, ip, instance, clsTotal number of SQL transactions pooled by pgbouncer
pgbouncer_stat_total_xact_timecounterdatname, job, ins, ip, instance, clsTotal number of seconds spent when in a transaction
pgbouncer_upgaugejob, ins, ip, instance, clslast scrape was able to connect to the server: 1 for yes, 0 for no
pgbouncer_versiongaugejob, ins, ip, instance, clsserver version number
process_cpu_seconds_totalcounterjob, ins, ip, instance, clsTotal user and system CPU time spent in seconds.
process_max_fdsgaugejob, ins, ip, instance, clsMaximum number of open file descriptors.
process_open_fdsgaugejob, ins, ip, instance, clsNumber of open file descriptors.
process_resident_memory_bytesgaugejob, ins, ip, instance, clsResident memory size in bytes.
process_start_time_secondsgaugejob, ins, ip, instance, clsStart time of the process since unix epoch in seconds.
process_virtual_memory_bytesgaugejob, ins, ip, instance, clsVirtual memory size in bytes.
process_virtual_memory_max_bytesgaugejob, ins, ip, instance, clsMaximum amount of virtual memory available in bytes.
promhttp_metric_handler_requests_in_flightgaugejob, ins, ip, instance, clsCurrent number of scrapes being served.
promhttp_metric_handler_requests_totalcountercode, job, ins, ip, instance, clsTotal number of scrapes by HTTP status code.
scrape_duration_secondsUnknownjob, ins, ip, instance, clsN/A
scrape_samples_post_metric_relabelingUnknownjob, ins, ip, instance, clsN/A
scrape_samples_scrapedUnknownjob, ins, ip, instance, clsN/A
scrape_series_addedUnknownjob, ins, ip, instance, clsN/A
upUnknownjob, ins, ip, instance, clsN/A

14 - 参数列表

PGSQL 模块提供的 PostgreSQL 相关配置参数详解

PGSQL 模块需要在 Pigsty 管理的节点上安装(即节点已经配置了 NODE 模块),同时还要求您的部署中有一套可用的 ETCD 集群来存储集群元数据。

在单个节点上安装 PGSQL 模块将创建一个独立的 PGSQL 服务器/实例,即 主实例。 在额外节点上安装将创建 只读副本,可以作为备用实例,并用于承载分担只读请求。 您还可以创建用于 ETL/OLAP/交互式查询的 离线 实例, 使用 同步备库法定人数提交 来提高数据一致性, 甚至搭建 备份集群延迟集群 以快速应对人为失误与软件缺陷导致的数据损失。

您可以定义多个 PGSQL 集群并进一步组建一个水平分片集群: Pigsty 支持原生的 citus 集群组,可以将您的标准 PGSQL 集群原地升级为一个分布式的数据库集群。

Pigsty v4.0 默认使用 PostgreSQL 18,并新增了 pg_io_methodpgbackrest_exporter 等参数。


参数组功能说明
PG_IDPostgreSQL 集群与实例的身份标识参数
PG_BUSINESS业务用户、数据库、服务与访问控制规则定义
PG_INSTALLPostgreSQL 安装相关:版本、路径、软件包
PG_BOOTSTRAPPostgreSQL 集群初始化引导:Patroni 高可用
PG_PROVISIONPostgreSQL 集群模板置备:角色、权限、扩展
PG_BACKUPpgBackRest 备份与恢复配置
PG_ACCESS服务暴露、连接池、VIP、DNS 等客户端访问配置
PG_MONITORPostgreSQL 监控 Exporter 配置
PG_REMOVEPostgreSQL 实例清理与卸载配置

参数概览


PG_ID 参数组用于定义 PostgreSQL 集群与实例的身份标识,包括集群名称、实例序号、角色、分片等核心身份参数。

参数类型级别说明
pg_modeenumCpgsql 集群模式: pgsql,citus,mssql,mysql,polar,ivory,oracle,gpsql
pg_clusterstringCpgsql 集群名称, 必选身份参数
pg_seqintIpgsql 实例号, 必选身份参数
pg_roleenumIpgsql 实例角色, 必选身份参数, 可为 primary,replica,offline
pg_instancesdictI在一个节点上定义多个 pg 实例,使用 {port:ins_vars} 格式
pg_upstreamipI级联从库或备份集群或的复制上游节点IP地址
pg_shardstringCpgsql 分片名,对 citus 与 gpsql 等水平分片集群为必选身份参数
pg_groupintCpgsql 分片号,正整数,对 citus 与 gpsql 等水平分片集群为必选身份参数
gp_roleenumC这个集群的 greenplum 角色,可以是 master 或 segment
pg_exportersdictC在该节点上设置额外的 pg_exporters 用于监控远程 postgres 实例
pg_offline_queryboolI设置为 true 将此只读实例标记为特殊的离线从库,承载 Offline 服务,允许离线查询

PG_BUSINESS 参数组用于定义业务用户、数据库、服务与访问控制规则,以及默认的系统用户凭据。

参数类型级别说明
pg_usersuser[]Cpostgres 业务用户
pg_databasesdatabase[]Cpostgres 业务数据库
pg_servicesservice[]Cpostgres 业务服务
pg_hba_ruleshba[]Cpostgres 的业务 hba 规则
pgb_hba_ruleshba[]Cpgbouncer 的业务 hba 规则
pg_crontabstring[]Cpostgres dbsu 的定时任务
pg_replication_usernameusernameGpostgres 复制用户名,默认为 replicator
pg_replication_passwordpasswordGpostgres 复制密码,默认为 DBUser.Replicator
pg_admin_usernameusernameGpostgres 管理员用户名,默认为 dbuser_dba
pg_admin_passwordpasswordGpostgres 管理员明文密码,默认为 DBUser.DBA
pg_monitor_usernameusernameGpostgres 监控用户名,默认为 dbuser_monitor
pg_monitor_passwordpasswordGpostgres 监控密码,默认为 DBUser.Monitor
pg_dbsu_passwordpasswordG/Cdbsu 密码,默认为空字符串意味着不设置 dbsu 密码,最好不要设置。

PG_INSTALL 参数组用于配置 PostgreSQL 安装相关选项,包括版本、路径、软件包与扩展插件。

参数类型级别说明
pg_dbsuusernameC操作系统 dbsu 名称,默认为 postgres,最好不要更改
pg_dbsu_uidintC操作系统 dbsu uid 和 gid,对于默认的 postgres 用户和组为 26
pg_dbsu_sudoenumCdbsu sudo 权限, none,limit,all,nopass,默认为 limit
pg_dbsu_homepathCpostgresql 主目录,默认为 /var/lib/pgsql
pg_dbsu_ssh_exchangeboolC在 pgsql 集群之间交换 postgres dbsu ssh 密钥
pg_versionenumC要安装的 postgres 主版本,默认为 18
pg_bin_dirpathCpostgres 二进制目录,默认为 /usr/pgsql/bin
pg_log_dirpathCpostgres 日志目录,默认为 /pg/log/postgres
pg_packagesstring[]C要安装的 pg 包,${pg_version} 将被替换为实际主版本号
pg_extensionsstring[]C要安装的 pg 扩展,${pg_version} 将被替换为实际主版本号

PG_BOOTSTRAP 参数组用于配置 PostgreSQL 集群初始化引导,包括 Patroni 高可用、数据目录、存储、连接、编码等核心设置。

参数类型级别说明
pg_datapathCpostgres 数据目录,默认为 /pg/data
pg_fs_mainpathCpostgres 主数据的挂载点/路径,默认为 /data/postgres
pg_fs_backuppathCpg 备份数据的挂载点/路径,默认为 /data/backups
pg_storage_typeenumCpg 主数据的存储类型,SSD、HDD,默认为 SSD,影响自动优化的参数。
pg_dummy_filesizesizeC/pg/dummy 的大小,默认保留 64MB 磁盘空间用于紧急抢修
pg_listenip(s)C/Ipostgres/pgbouncer 的监听地址,用逗号分隔的IP列表,默认为 0.0.0.0
pg_portportCpostgres 监听端口,默认为 5432
pg_localhostpathCpostgres 的 Unix 套接字目录,用于本地连接
pg_namespacepathC在 etcd 中的顶级键命名空间,被 patroni & vip 用于高可用管理
patroni_enabledboolC如果禁用,初始化期间不会创建 postgres 集群
patroni_modeenumCpatroni 工作模式:default,pause,remove
patroni_portportCpatroni 监听端口,默认为 8008
patroni_log_dirpathCpatroni 日志目录,默认为 /pg/log/patroni
patroni_ssl_enabledboolG使用 SSL 保护 patroni RestAPI 通信?
patroni_watchdog_modeenumCpatroni 看门狗模式:automatic,required,off,默认为 off
patroni_usernameusernameCpatroni restapi 用户名,默认为 postgres
patroni_passwordpasswordCpatroni restapi 密码,默认为 Patroni.API
pg_primary_dbstringC指定集群中首要使用的数据库名,Citus等模式会用到,默认为 postgres
pg_parametersdictC覆盖 postgresql.auto.conf 中的 PostgreSQL 参数
pg_filespath[]C拷贝至PGDATA目录中的额外文件列表 (例如许可证文件)
pg_confenumC配置模板:oltp,olap,crit,tiny,默认为 oltp.yml
pg_max_connintCpostgres 最大连接数,auto 将使用推荐值
pg_shared_buffer_ratiofloatCpostgres 共享缓冲区内存比率,默认为 0.25,范围 0.1~0.4
pg_rtoenumCRTO 模式:fast,norm,safe,wide,默认 norm
pg_rto_plandictGRTO 预设配置,定义 Patroni HA 与 HAProxy 健康检查的超时参数
pg_rpointC恢复点目标(字节),默认为 1MiB
pg_libsstringC预加载的库,默认为 pg_stat_statements,auto_explain
pg_delayintervalI备份集群主库的WAL重放应用延迟,用于制备延迟从库
pg_checksumboolC为 postgres 集群启用数据校验和?
pg_pwd_encenumC密码加密算法:固定为 scram-sha-256
pg_encodingenumC数据库集群编码,默认为 UTF8
pg_localeenumC数据库集群本地化设置,默认为 C
pg_lc_collateenumC数据库集群排序,默认为 C
pg_lc_ctypeenumC数据库字符类型,默认为 C
pg_io_methodenumCPostgreSQL IO 方法:auto, sync, worker, io_uring
pg_etcd_passwordpasswordC此 PostgreSQL 集群在 etcd 中使用的密码,默认使用集群名
pgsodium_keystringCpgsodium 加密主密钥,64 位十六进制数字,默认使用 sha256(pg_cluster)
pgsodium_getkey_scriptpathCpgsodium 获取密钥脚本路径,默认使用模板中的 pgsodium_getkey

PG_PROVISION 参数组用于配置 PostgreSQL 集群模板置备,包括默认角色、权限、模式、扩展与 HBA 规则。

参数类型级别说明
pg_provisionboolC在引导后置备 postgres 集群内部的业务对象?
pg_initstringG/C为集群模板提供初始化脚本,默认为 pg-init
pg_default_rolesrole[]G/Cpostgres 集群中的默认预定义角色和系统用户
pg_default_privilegesstring[]G/C由管理员用户创建数据库内对象时的默认权限
pg_default_schemasstring[]G/C要创建的默认模式列表
pg_default_extensionsextension[]G/C要创建的默认扩展列表
pg_reloadboolA更改HBA后,是否立即重载 postgres 配置
pg_default_hba_ruleshba[]G/Cpostgres 基于主机的认证规则,全局PG默认HBA
pgb_default_hba_ruleshba[]G/Cpgbouncer 默认的基于主机的认证规则,全局PGB默认HBA

PG_BACKUP 参数组用于配置 pgBackRest 备份与恢复,包括仓库类型、路径、保留策略等。

参数类型级别说明
pgbackrest_enabledboolC在 pgsql 主机上启用 pgbackrest?
pgbackrest_cleanboolC在初始化时删除以前的 pg 备份数据?
pgbackrest_log_dirpathCpgbackrest 日志目录,默认为 /pg/log/pgbackrest
pgbackrest_methodenumCpgbackrest 使用的仓库:local,minio,等…
pgbackrest_init_backupboolCpgbackrest 初始化完成后是否立即执行全量备份?默认为 true
pgbackrest_repodictG/Cpgbackrest 仓库定义

PG_ACCESS 参数组用于配置服务暴露、连接池、VIP、DNS 等客户端访问相关选项。

参数类型级别说明
pgbouncer_enabledboolC如果禁用,则不会配置 pgbouncer 连接池
pgbouncer_portportCpgbouncer 监听端口,默认为 6432
pgbouncer_log_dirpathCpgbouncer 日志目录,默认为 /pg/log/pgbouncer
pgbouncer_auth_queryboolC使用 AuthQuery 来从 postgres 获取未列出的业务用户?
pgbouncer_poolmodeenumC池化模式:transaction,session,statement,默认为 transaction
pgbouncer_sslmodeenumCpgbouncer 客户端 SSL 模式,默认为禁用
pgbouncer_ignore_paramstring[]Cpgbouncer 忽略的启动参数列表
pg_weightintI在服务中的相对负载均衡权重,默认为 100,范围 0-255
pg_service_providerstringG/C专用的 haproxy 节点组名称,或默认空字符,使用本地节点上的 haproxy
pg_default_service_destenumG/C如果 svc.dest=‘default’,默认服务指向哪里?postgres 或 pgbouncer
pg_default_servicesservice[]G/Cpostgres 默认服务定义列表,全局共用。
pg_vip_enabledboolC是否为 pgsql 主节点启用 L2 VIP?默认不启用
pg_vip_addresscidr4Cvip 地址的格式为 <ipv4>/<mask>,启用 vip 时为必选参数
pg_vip_interfacestringC/I监听的 vip 网络接口,默认为 eth0
pg_dns_suffixstringCpgsql dns 后缀,默认为空
pg_dns_targetenumCPG DNS 解析到哪里?auto、primary、vip、none 或者特定的 IP 地址

PG_MONITOR 参数组用于配置 PostgreSQL 监控 Exporter,包括 pg_exporter、pgbouncer_exporter 和 pgbackrest_exporter。

参数类型级别说明
pg_exporter_enabledboolC在 pgsql 主机上启用 pg_exporter 吗?
pg_exporter_configstringCpg_exporter 配置文件/模板名称
pg_exporter_cache_ttlsstringCpg_exporter 收集器阶梯TTL配置,默认为 ‘1,10,60,300’
pg_exporter_portportCpg_exporter 监听端口,默认为 9630
pg_exporter_paramsstringCpg_exporter dsn 中传入的额外 URL 参数
pg_exporter_urlpgurlC如果指定,则覆盖自动生成的 postgres DSN 连接串
pg_exporter_auto_discoveryboolC监控是否启用自动数据库发现?默认启用
pg_exporter_exclude_databasestringC启用自动发现时,排除在外的数据库名称列表,用逗号分隔
pg_exporter_include_databasestringC启用自动发现时,只监控这个列表中的数据库,名称用逗号分隔
pg_exporter_connect_timeoutintCpg_exporter 连接超时,单位毫秒,默认为 200
pg_exporter_optionsargCpg_exporter 的额外命令行参数选项
pgbouncer_exporter_enabledboolC在 pgsql 主机上启用 pgbouncer_exporter 吗?
pgbouncer_exporter_portportCpgbouncer_exporter 监听端口,默认为 9631
pgbouncer_exporter_urlpgurlC如果指定,则覆盖自动生成的 pgbouncer dsn 连接串
pgbouncer_exporter_optionsargCpgbouncer_exporter 的额外命令行参数选项
pgbackrest_exporter_enabledboolC在 pgsql 主机上启用 pgbackrest_exporter 吗?
pgbackrest_exporter_portportCpgbackrest_exporter 监听端口,默认为 9854
pgbackrest_exporter_optionsargCpgbackrest_exporter 的额外命令行参数选项

PG_REMOVE 参数组用于配置 PostgreSQL 实例清理与卸载行为,包括数据目录、备份、软件包的删除控制。

参数类型级别说明
pg_rm_databoolG/C/A删除 pgsql 实例时是否清理 postgres 数据目录?
pg_rm_backupboolG/C/A删除主库时是否一并清理 pgbackrest 备份?
pg_rm_pkgboolG/C/A删除 pgsql 实例时是否卸载相关软件包?
pg_safeguardboolG/C/A防误删保险,阻止误执行 pgsql 清理操作?默认为 false

PG_ID

以下是一些常用的参数,用于标识 PGSQL 模块中的 实体:集群、实例、服务等…

# pg_cluster:           #CLUSTER  # pgsql 集群名称,必需的标识参数
# pg_seq: 0             #INSTANCE # pgsql 实例序列号,必需的标识参数
# pg_role: replica      #INSTANCE # pgsql 角色,必需的,可以是 primary,replica,offline
# pg_instances: {}      #INSTANCE # 在节点上定义多个 pg 实例,使用 `{port:ins_vars}` 格式
# pg_upstream:          #INSTANCE # 备用集群或级联副本的 repl 上游 ip 地址
# pg_shard:             #CLUSTER  # pgsql 分片名称,分片集群的可选标识
# pg_group: 0           #CLUSTER  # pgsql 分片索引号,分片集群的可选标识
# gp_role: master       #CLUSTER  # 此集群的 greenplum 角色,可以是 master 或 segment
pg_offline_query: false #INSTANCE # 设置为 true 以在此实例上启用离线查询

您必须显式指定这些身份参数,它们没有默认值:

名称类型级别扩展说明
pg_clusterstringCPG 数据库集群名称
pg_seqnumberIPG 数据库实例 ID
pg_roleenumIPG 数据库实例角色
pg_shardstringC数据库分片名称
pg_groupnumberC数据库分片序号
  • pg_cluster: 它标识集群的名称,该名称在集群级别配置。
  • pg_role: 在实例级别配置,标识 ins 的角色。只有 primary 角色会特别处理。如果不填写,默认为 replica 角色和特殊的 delayedoffline 角色。
  • pg_seq: 用于在集群内标识 ins,通常是从 0 或 1 递增的整数,一旦分配就不会更改。
  • {{ pg_cluster }}-{{ pg_seq }} 用于唯一标识 ins,即 pg_instance
  • {{ pg_cluster }}-{{ pg_role }} 用于标识集群内的服务,即 pg_service
  • pg_shardpg_group 用于水平分片集群,仅用于 citus、greenplum 和 matrixdb。

pg_clusterpg_rolepg_seq 是核心标识参数,对于任何 Postgres 集群都是必选的,并且必须显式指定。以下是一个示例:

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

所有其他参数都可以从全局配置或默认配置继承,但标识参数必须明确指定手动分配

pg_mode

参数名称: pg_mode, 类型: enum, 层次:C

PostgreSQL 集群模式,默认值为 pgsql,即标准的 PostgreSQL 集群。

可用的模式选项包括:

  • pgsql:标准的 PostgreSQL 集群
  • citus:Citus 分布式数据库集群
  • mssql:Babelfish MSSQL 线缆协议兼容内核
  • mysql:OpenHalo/HaloDB MySQL 线协议兼容内核
  • ivory:IvorySQL Oracle 兼容内核
  • polar:PolarDB for PostgreSQL 内核
  • oracle:PolarDB for Oracle 内核
  • gpsql:Greenplum 并行数据库集群(监控)

如果 pg_mode 设置为 citusgpsql,则需要两个额外的必选身份参数 pg_shardpg_group 来定义水平分片集群的身份。

在这两种情况下,每一个 PostgreSQL 集群都是一组更大的业务单元的一部分。

pg_cluster

参数名称: pg_cluster, 类型: string, 层次:C

PostgreSQL 集群名称,必选的身份标识参数,没有默认值

集群名将用作资源的命名空间。

集群命名需要遵循特定的命名模式:[a-z][a-z0-9-]*,即,只使用数字与小写字母,且不以数字开头,以符合标识上的不同约束的要求。

pg_seq

参数名称: pg_seq, 类型: int, 层次:I

PostgreSQL 实例序列号,必选的身份标识参数,无默认值。

此实例的序号,在其集群内是唯一分配的,通常使用自然数,从0或1开始分配,通常不会回收重用。

pg_role

参数名称: pg_role, 类型: enum, 层次:I

PostgreSQL 实例角色,必选的身份标识参数,无默认值。取值可以是:primary, replica, offline

PGSQL 实例的角色,可以是:primaryreplicastandbyoffline

  • primary: 主实例,在集群中有且仅有一个。
  • replica: 用于承载在线只读流量的副本,高负载下可能会有轻微复制延迟(10ms~100ms, 100KB)。
  • offline: 用于处理离线只读流量的离线副本,如统计分析/ETL/个人查询等。

pg_instances

参数名称: pg_instances, 类型: dict, 层次:I

使用 {port:ins_vars} 的形式在一台主机上定义多个 PostgreSQL 实例。

此参数是为在单个节点上的多实例部署保留的参数,Pigsty 尚未实现此功能,并强烈建议独占节点部署。

pg_upstream

参数名称: pg_upstream, 类型: ip, 层次:I

备份集群 或级联从库的上游实例 IP 地址。

在集群的 primary 实例上设置 pg_upstream ,表示此集群是一个 备份集群,该实例将作为 standby leader,从上游集群接收并应用更改。

对非 primary 实例设置 pg_upstream 参数将指定一个具体实例作为物理复制的上游,如果与主实例 ip 地址不同,此实例将成为 级联副本 。确保上游 IP 地址是同一集群中的另一个实例是用户的责任。

pg_shard

参数名称: pg_shard, 类型: string, 层次:C

PostgreSQL 水平分片名称,对于分片集群来说(例如 citus 集群),这是的必选标识参数。

当多个标准的 PostgreSQL 集群一起以水平分片方式为同一业务提供服务时,Pigsty 将此组集群标记为 水平分片集群

pg_shard 是分片组名称。它通常是 pg_cluster 的前缀。

例如,如果我们有一个分片组 pg-citus,并且其中有4个集群,它们的标识参数将是:

cls pg_shard: pg-citus
cls pg_group = 0:   pg-citus0
cls pg_group = 1:   pg-citus1
cls pg_group = 2:   pg-citus2
cls pg_group = 3:   pg-citus3

pg_group

参数名称: pg_group, 类型: int, 层次:C

PostgreSQL 水平分片集群的分片索引号,对于分片集群来说(例如 citus 集群),这是的必选标识参数。

此参数与 pg_shard 配对使用,通常可以使用非负整数作为索引号。

gp_role

参数名称: gp_role, 类型: enum, 层次:C

PostgreSQL 集群的 Greenplum/Matrixdb 角色,可以是 mastersegment

  • master: 标记 postgres 集群为 greenplum 主实例(协调节点),这是默认值。
  • segment 标记 postgres 集群为 greenplum 段集群(数据节点)。

此参数仅用于 Greenplum/MatrixDB 数据库 (pg_modegpsql),对于普通的 PostgreSQL 集群没有意义。

pg_exporters

参数名称: pg_exporters, 类型: dict, 层次:C

额外用于 监控 远程 PostgreSQL 实例的 Exporter 定义,默认值:{}

如果您希望监控远程 PostgreSQL 实例,请在监控系统所在节点(Infra节点)集群上的 pg_exporters 参数中定义它们,并使用 pgsql-monitor.yml 剧本来完成部署。

pg_exporters: # list all remote instances here, alloc a unique unused local port as k
    20001: { pg_cluster: pg-foo, pg_seq: 1, pg_host: 10.10.10.10 }
    20004: { pg_cluster: pg-foo, pg_seq: 2, pg_host: 10.10.10.11 }
    20002: { pg_cluster: pg-bar, pg_seq: 1, pg_host: 10.10.10.12 }
    20003: { pg_cluster: pg-bar, pg_seq: 1, pg_host: 10.10.10.13 }

pg_offline_query

参数名称: pg_offline_query, 类型: bool, 层次:I

设置为 true 以在此实例上启用离线查询,默认为 false

当某个 PostgreSQL 实例启用此参数时, 属于 dbrole_offline 分组的用户可以直接连接到该 PostgreSQL 实例上执行离线查询(慢查询,交互式查询,ETL/分析类查询)。

带有此标记的实例在效果上类似于为实例设置 pg_role = offline ,唯一的区别在于 offline 实例默认不会承载 replica 服务的请求,是作为专用的离线/分析从库实例而存在的。

如果您没有富余的实例可以专门用于此目的,则可以挑选一台普通的从库,在实例层次启用此参数,以便在需要时承载离线查询。


PG_BUSINESS

定制集群模板:用户,数据库,服务,权限规则。

用户需重点关注此部分参数,因为这里是业务声明自己所需数据库对象的地方。

默认 的数据库用户及其凭据,强烈建议在生产环境中修改这些用户的密码。

# postgres business object definition, overwrite in group vars
pg_users: []                      # postgres business users
pg_databases: []                  # postgres business databases
pg_services: []                   # postgres business services
pg_hba_rules: []                  # business hba rules for postgres
pgb_hba_rules: []                 # business hba rules for pgbouncer
pg_crontab: []                    # crontab entries for postgres dbsu
# global credentials, overwrite in global vars
pg_dbsu_password: ''              # dbsu password, empty string means no dbsu password by default
pg_replication_username: replicator
pg_replication_password: DBUser.Replicator
pg_admin_username: dbuser_dba
pg_admin_password: DBUser.DBA
pg_monitor_username: dbuser_monitor
pg_monitor_password: DBUser.Monitor

pg_users

参数名称: pg_users, 类型: user[], 层次:C

PostgreSQL 业务用户列表,需要在 PG 集群层面进行定义。默认值为:[] 空列表。

每一个数组元素都是一个 用户/角色 定义,例如:

- 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 不限制

pg_databases

参数名称: pg_databases, 类型: database[], 层次:C

PostgreSQL 业务数据库列表,需要在 PG 集群层面进行定义。默认值为:[] 空列表。

每一个数组元素都是一个 业务数据库 定义,例如:

- 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 是必选字段,其他的字段都是可选项。

pg_services

参数名称: pg_services, 类型: service[], 层次:C

PostgreSQL 服务列表,需要在 PG 集群层面进行定义。默认值为:[] ,空列表。

用于在数据库集群层面定义额外的服务,数组中的每一个对象定义了一个 服务,一个完整的服务定义样例如下:

- name: standby                   # 必选,服务名称,最终的 svc 名称会使用 `pg_cluster` 作为前缀,例如:pg-meta-standby
  port: 5435                      # 必选,暴露的服务端口(作为 kubernetes 服务节点端口模式)
  ip: "*"                         # 可选,服务绑定的 IP 地址,默认情况下为所有 IP 地址
  selector: "[]"                  # 必选,服务成员选择器,使用 JMESPath 来筛选配置清单
  backup: "[? pg_role == `primary`]"  # 可选,服务成员选择器(备份),也就是当默认选择器选中的实例都宕机后,服务才会由这里选中的实例成员来承载
  dest: default                   # 可选,目标端口,default|postgres|pgbouncer|<port_number>,默认为 'default',Default的意思就是使用 pg_default_service_dest 的取值来最终决定
  check: /sync                    # 可选,健康检查 URL 路径,默认为 /,这里使用 Patroni API:/sync ,只有同步备库和主库才会返回 200 健康状态码
  maxconn: 5000                   # 可选,允许的前端连接最大数,默认为5000
  balance: roundrobin             # 可选,haproxy 负载均衡算法(默认为 roundrobin,其他选项:leastconn)
  #options: 'inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100'
  # 注意:健康检查相关参数(inter, fastinter, downinter, rise, fall)现在由 pg_rto_plan 统一控制
  # 默认 norm 模式参数:inter 2s fastinter 1s downinter 2s rise 3 fall 3

请注意,本参数用于在集群层面添加额外的服务。如果您想在全局定义所有 PostgreSQL 数据库都要提供的服务,可以使用 pg_default_services 参数。

pg_hba_rules

参数名称: pg_hba_rules, 类型: hba[], 层次:C

数据库集群/实例的客户端IP黑白名单规则。默认为:[] 空列表。

对象数组,每一个对象都代表一条规则, hba 规则对象的定义形式如下:

- title: allow intranet password access
  role: common
  rules:
    - host   all  all  10.0.0.0/8      md5
    - host   all  all  172.16.0.0/12   md5
    - host   all  all  192.168.0.0/16  md5
  • title: 规则的标题名称,会被渲染为 HBA 文件中的注释。
  • rules:规则数组,每个元素是一条标准的 HBA 规则字符串。
  • role:规则的应用范围,哪些实例角色会启用这条规则?
    • common:对于所有实例生效
    • primary, replica,offline: 只针对特定的角色 pg_role 实例生效。
    • 特例:role: 'offline' 的规则除了会应用在 pg_role : offline 的实例上,对于带有 pg_offline_query 标记的实例也生效。

除了上面这种原生 HBA 规则定义形式,Pigsty 还提供了另外一种更为简便的别名形式:

- addr: 'intra'    # world|intra|infra|admin|local|localhost|cluster|<cidr>
  auth: 'pwd'      # trust|pwd|ssl|cert|deny|<official auth method>
  user: 'all'      # all|${dbsu}|${repl}|${admin}|${monitor}|<user>|<group>
  db: 'all'        # all|replication|....
  rules: []        # raw hba string precedence over above all
  title: allow intranet password access

pg_default_hba_rules 与本参数基本类似,但它是用于定义全局的 HBA 规则,而本参数通常用于定制某个集群/实例的 HBA 规则。

pgb_hba_rules

参数名称: pgb_hba_rules, 类型: hba[], 层次:C

Pgbouncer 业务HBA规则,默认值为: [], 空数组。

此参数与 pg_hba_rules 基本类似,都是 hba 规则对象的数组,区别在于本参数是为 Pgbouncer 准备的。

pgb_default_hba_rules 与本参数基本类似,但它是用于定义全局连接池 HBA 规则,而本参数通常用于定制某个连接池集群/实例的 HBA 规则。

pg_crontab

参数名称: pg_crontab, 类型: string[], 层次:C

PostgreSQL 数据库超级用户(dbsu,默认 postgres)的定时任务列表,默认值为:[] 空数组。

每个数组元素是一行 crontab 条目,使用标准的用户 crontab 格式:分 时 日 月 周 命令无需指定用户名)。

pg_crontab:
  - '00 01 * * * /pg/bin/pg-backup full'      # 每天凌晨 1 点全量备份
  - '00 13 * * * /pg/bin/pg-backup'           # 每天下午 1 点增量备份

此参数会将定时任务写入 postgres 用户的个人 crontab 文件:

  • EL 系统:/var/spool/cron/postgres
  • Debian 系统:/var/spool/cron/crontabs/postgres

注意:此参数用于取代在 node_crontab 中配置 postgres 用户任务的旧做法。 因为 node_crontab 在 NODE 初始化阶段写入 /etc/crontab,此时 postgres 用户可能尚未创建,会导致 cron 报错。

移除集群时,此 crontab 文件会被一并删除。

pg_replication_username

参数名称: pg_replication_username, 类型: username, 层次:G

PostgreSQL 物理复制用户名,默认使用 replicator,不建议修改此参数。

pg_replication_password

参数名称: pg_replication_password, 类型: password, 层次:G

PostgreSQL 物理复制用户密码,默认值为:DBUser.Replicator

警告:请在生产环境中修改此密码!

pg_admin_username

参数名称: pg_admin_username, 类型: username, 层次:G

PostgreSQL / Pgbouncer 管理员名称,默认为:dbuser_dba

这是全局使用的数据库管理员,具有数据库的 Superuser 权限与连接池的流量管理权限,请务必控制使用范围。

pg_admin_password

参数名称: pg_admin_password, 类型: password, 层次:G

PostgreSQL / Pgbouncer 管理员密码,默认为: DBUser.DBA

警告:请在生产环境中修改此密码!

pg_monitor_username

参数名称: pg_monitor_username, 类型: username, 层次:G

PostgreSQL/Pgbouncer 监控用户名,默认为:dbuser_monitor

这是一个用于监控的数据库/连接池用户,不建议修改此用户名。

但如果您的现有数据库使用了不同的监控用户,可以在指定监控目标时使用此参数传入使用的监控用户名。

pg_monitor_password

参数名称: pg_monitor_password, 类型: password, 层次:G

PostgreSQL/Pgbouncer 监控用户使用的密码,默认为:DBUser.Monitor

请尽可能不要在密码中使用 @:/ 这些容易与 URL 分隔符混淆的字符,减少不必要的麻烦。

警告:请在生产环境中修改此密码!

pg_dbsu_password

参数名称: pg_dbsu_password, 类型: password, 层次:G/C

PostgreSQL pg_dbsu 超级用户密码,默认是空字符串,即不为其设置密码。

我们不建议为 dbsu 配置密码登陆,这会增大攻击面。例外情况是:pg_mode = citus,这时候需要为每个分片集群的 dbsu 配置密码,以便在分片集群内部进行连接。


PG_INSTALL

本节负责安装 PostgreSQL 及其扩展。如果您希望安装不同大版本与扩展插件,修改 pg_versionpg_extensions 即可,不过请注意,并不是所有扩展都在所有大版本可用。

pg_dbsu: postgres                 # os 数据库超级用户名称,默认为 postgres,最好不要更改
pg_dbsu_uid: 26                   # os 数据库超级用户 uid 和 gid,默认为 26,适用于默认的 postgres 用户和组
pg_dbsu_sudo: limit               # 数据库超级用户 sudo 权限,可选 none,limit,all,nopass。默认为 limit
pg_dbsu_home: /var/lib/pgsql      # postgresql 主目录,默认为 `/var/lib/pgsql`
pg_dbsu_ssh_exchange: true        # 是否在相同的 pgsql 集群中交换 postgres 数据库超级用户的 ssh 密钥
pg_version: 18                    # 要安装的 postgres 主版本,默认为 18
pg_bin_dir: /usr/pgsql/bin        # postgres 二进制目录,默认为 `/usr/pgsql/bin`
pg_log_dir: /pg/log/postgres      # postgres 日志目录,默认为 `/pg/log/postgres`
pg_packages:                      # pg packages to be installed, alias can be used
  - pgsql-main pgsql-common
pg_extensions: []                 # pg extensions to be installed, alias can be used

pg_dbsu

参数名称: pg_dbsu, 类型: username, 层次:C

PostgreSQL 使用的操作系统 dbsu 用户名, 默认为 postgres,改这个用户名是不太明智的。

不过在特定情况下,您可能会使用到不同于 postgres 的用户名,例如在安装配置 Greenplum / MatrixDB 时,需要使用 gpadmin / mxadmin 作为相应的操作系统超级用户。

pg_dbsu_uid

参数名称: pg_dbsu_uid, 类型: int, 层次:C

操作系统数据库超级用户的 uid 和 gid,26 是 PGDG RPM 默认的 postgres 用户 UID/GID。

对于 Debian/Ubuntu 系统,没有默认值,且 26 号用户经常被占用。因此Pigsty 在检测到安装环境为 Debian 系,且 uid 为 26 时,会自动使用替换的 pg_dbsu_uid = 543

pg_dbsu_sudo

参数名称: pg_dbsu_sudo, 类型: enum, 层次:C

数据库超级用户的 sudo 权限,可以是 nonelimitallnopass。默认为 limit

  • none: 无 Sudo 权限

  • limit: 有限的 sudo 权限,用于执行与数据库相关的组件的 systemctl 命令(默认选项)。

  • all: 完全的 sudo 权限,需要密码。

  • nopass: 不需要密码的完全 sudo 权限(不推荐)。

  • 默认值为 limit,只允许执行 sudo systemctl <start|stop|reload> <postgres|patroni|pgbouncer|...>

pg_dbsu_home

参数名称: pg_dbsu_home, 类型: path, 层次:C

postgresql 主目录,默认为 /var/lib/pgsql,与官方的 pgdg RPM 保持一致。

pg_dbsu_ssh_exchange

参数名称: pg_dbsu_ssh_exchange, 类型: bool, 层次:C

是否在同一 PostgreSQL 集群中交换操作系统 dbsu 的 ssh 密钥?

默认值为 true,意味着同一集群中的数据库超级用户可以互相 ssh 访问。

pg_version

参数名称: pg_version, 类型: enum, 层次:C

要安装的 postgres 主版本,默认为 18

请注意,PostgreSQL 的物理流复制不能跨主要版本,因此最好不要在实例级别上配置此项。

您可以使用 pg_packagespg_extensions 中的参数来为特定的 PG 大版本安装不同的软件包与扩展。

pg_bin_dir

参数名称: pg_bin_dir, 类型: path, 层次:C

PostgreSQL 二进制程序目录,默认为 /usr/pgsql/bin

默认值是在安装过程中手动创建的软链接,指向安装的特定的 Postgres 版本目录。

例如 /usr/pgsql -> /usr/pgsql-15。在 Ubuntu/Debian 上则指向 /usr/lib/postgresql/15/bin

更多详细信息,请查看 PGSQL 文件结构

pg_log_dir

参数名称: pg_log_dir, 类型: path, 层次:C

PostgreSQL 日志目录,默认为:/pg/log/postgres,Vector 日志代理会使用此变量收集 PostgreSQL 日志。

请注意,如果日志目录 pg_log_dir 以数据库目录 pg_data 作为前缀,则不会显式创建(数据库目录初始化时自动创建)。

pg_packages

参数名称: pg_packages, 类型: string[], 层次:C

要安装的 PostgreSQL 软件包(RPM/DEB),这是一个包名数组,元素可以是空格或逗号分隔的包别名。

Pigsty v4 将默认值收敛为两个别名:

pg_packages:
  - pgsql-main pgsql-common
  • pgsql-main:映射到当前平台上的 PostgreSQL 内核、客户端、PL 语言以及 pg_repackwal2jsonpgvector 等核心扩展。
  • pgsql-common:映射到运行数据库必需的配套组件,例如 Patroni、Pgbouncer、pgBackRest、pg_exporter、vip-manager 等守护进程。

别名的具体定义可以在 roles/node_id/vars/ 中的 pg_package_map 查到,Pigsty 会先根据操作系统和架构解析别名,再将 $v/${pg_version} 替换为实际主版本 pg_version,最后安装真实的软件包。这样可以屏蔽不同发行版之间的包名差异。

如果需要额外的软件包(例如特定 FDW 或扩展),可以直接在 pg_packages 中追加别名或真实包名。但请记得保留 pgsql-main pgsql-common,否则会缺失核心组件。

pg_extensions

参数名称: pg_extensions, 类型: string[], 层次:G/C

要安装的 PostgreSQL 扩展包(RPM/DEB),这是一个由扩展包名或别名组成的数组。

从 v4 开始默认值为空列表 [],Pigsty 不再强制安装大体量扩展,用户可以按需选择,避免占用额外的磁盘与依赖。

如果需要安装扩展,请像下面这样填充:

pg_extensions:
  - postgis timescaledb pgvector
  - pgsql-fdw     # 使用别名一次性安装常用 FDW

pg_package_map 中提供了大量别名,方便在不同发行版之间屏蔽包名差异。以下是 EL9 平台可用的扩展组合供参考(按需挑选即可):

pg_extensions: # extensions to be installed on this cluster
  - timescaledb periods temporal_tables emaj table_version pg_cron pg_later pg_background pg_timetable
  - postgis pgrouting pointcloud pg_h3 q3c ogr_fdw geoip #pg_geohash #mobilitydb
  - pgvector pgvectorscale pg_vectorize pg_similarity pg_tiktoken pgml #smlar
  - pg_search pg_bigm zhparser hunspell
  - hydra pg_analytics pg_lakehouse pg_duckdb duckdb_fdw pg_fkpart pg_partman plproxy #pg_strom citus
  - pg_hint_plan age hll rum pg_graphql pg_jsonschema jsquery index_advisor hypopg imgsmlr pg_ivm pgmq pgq #rdkit
  - pg_tle plv8 pllua plprql pldebugger plpgsql_check plprofiler plsh #pljava plr pgtap faker dbt2
  - prefix semver pgunit md5hash asn1oid roaringbitmap pgfaceting pgsphere pg_country pg_currency pgmp numeral pg_rational pguint ip4r timestamp9 chkpass #pg_uri #pgemailaddr #acl #debversion #pg_rrule
  - topn pg_gzip pg_http pg_net pg_html5_email_address pgsql_tweaks pg_extra_time pg_timeit count_distinct extra_window_functions first_last_agg tdigest aggs_for_arrays pg_arraymath pg_idkit pg_uuidv7 permuteseq pg_hashids
  - sequential_uuids pg_math pg_random pg_base36 pg_base62 floatvec pg_financial pgjwt pg_hashlib shacrypt cryptint pg_ecdsa pgpcre icu_ext envvar url_encode #pg_zstd #aggs_for_vecs #quantile #lower_quantile #pgqr #pg_protobuf
  - pg_repack pg_squeeze pg_dirtyread pgfincore pgdd ddlx pg_prioritize pg_checksums pg_readonly safeupdate pg_permissions pgautofailover pg_catcheck preprepare pgcozy pg_orphaned pg_crash pg_cheat_funcs pg_savior table_log pg_fio #pgpool pgagent
  - pg_profile pg_show_plans pg_stat_kcache pg_stat_monitor pg_qualstats pg_store_plans pg_track_settings pg_wait_sampling system_stats pg_meta pgnodemx pg_sqlog bgw_replstatus pgmeminfo toastinfo pagevis powa pg_top #pg_statviz #pgexporter_ext #pg_mon
  - passwordcheck supautils pgsodium pg_vault anonymizer pg_tde pgsmcrypto pgaudit pgauditlogtofile pg_auth_mon credcheck pgcryptokey pg_jobmon logerrors login_hook set_user pg_snakeoil pgextwlist pg_auditor noset #sslutils
  - wrappers multicorn odbc_fdw mysql_fdw tds_fdw sqlite_fdw pgbouncer_fdw mongo_fdw redis_fdw pg_redis_pubsub kafka_fdw hdfs_fdw firebird_fdw aws_s3 log_fdw #oracle_fdw #db2_fdw #jdbc_fdw
  - orafce pgtt session_variable pg_statement_rollback pg_dbms_metadata pg_dbms_lock pgmemcache #pg_dbms_job #wiltondb
  - pglogical pgl_ddl_deploy pg_failover_slots wal2json wal2mongo decoderbufs decoder_raw mimeo pgcopydb pgloader pg_fact_loader pg_bulkload pg_comparator pgimportdoc pgexportdoc #repmgr #slony
  - gis-stack rag-stack fdw-stack fts-stack etl-stack feat-stack olap-stack supa-stack stat-stack json-stack

完整列表请参考:roles/node_id/vars


PG_BOOTSTRAP

使用 Patroni 引导拉起 PostgreSQL 集群,并设置 1:1 对应的 Pgbouncer 连接池。

它还会使用 PG_PROVISION 中定义的默认角色、用户、权限、模式、扩展来初始化数据库集群

pg_data: /pg/data                 # postgres data directory, `/pg/data` by default
pg_fs_main: /data/postgres        # postgres main data directory, `/data/postgres` by default
pg_fs_backup: /data/backups       # postgres backup data directory, `/data/backups` by default
pg_storage_type: SSD              # storage type for pg main data, SSD,HDD, SSD by default
pg_dummy_filesize: 64MiB          # size of `/pg/dummy`, hold 64MB disk space for emergency use
pg_listen: '0.0.0.0'              # postgres/pgbouncer listen addresses, comma separated list
pg_port: 5432                     # postgres listen port, 5432 by default
pg_localhost: /var/run/postgresql # postgres unix socket dir for localhost connection
patroni_enabled: true             # if disabled, no postgres cluster will be created during init
patroni_mode: default             # patroni working mode: default,pause,remove
pg_namespace: /pg                 # top level key namespace in etcd, used by patroni & vip
patroni_port: 8008                # patroni listen port, 8008 by default
patroni_log_dir: /pg/log/patroni  # patroni log dir, `/pg/log/patroni` by default
patroni_ssl_enabled: false        # secure patroni RestAPI communications with SSL?
patroni_watchdog_mode: off        # patroni watchdog mode: automatic,required,off. off by default
patroni_username: postgres        # patroni restapi username, `postgres` by default
patroni_password: Patroni.API     # patroni restapi password, `Patroni.API` by default
pg_etcd_password: ''              # etcd password for this pg cluster, '' to use pg_cluster
pg_primary_db: postgres           # primary database name, used by citus,etc... ,postgres by default
pg_parameters: {}                 # extra parameters in postgresql.auto.conf
pg_files: []                      # extra files to be copied to postgres data directory (e.g. license)
pg_conf: oltp.yml                 # config template: oltp,olap,crit,tiny. `oltp.yml` by default
pg_max_conn: auto                 # postgres max connections, `auto` will use recommended value
pg_shared_buffer_ratio: 0.25      # postgres shared buffers ratio, 0.25 by default, 0.1~0.4
pg_io_method: worker              # io method for postgres, auto,fsync,worker,io_uring, worker by default
pg_rto: norm                      # shared rto mode: fast,norm,safe,wide (or seconds for compatibility)
pg_rpo: 1048576                   # recovery point objective in bytes, `1MiB` at most by default
pg_libs: 'pg_stat_statements, auto_explain'  # preloaded libraries, `pg_stat_statements,auto_explain` by default
pg_delay: 0                       # replication apply delay for standby cluster leader
pg_checksum: true                 # enable data checksum for postgres cluster?
pg_pwd_enc: scram-sha-256         # passwords encryption algorithm: fixed to scram-sha-256
pg_encoding: UTF8                 # database cluster encoding, `UTF8` by default
pg_locale: C                      # database cluster local, `C` by default
pg_lc_collate: C                  # database cluster collate, `C` by default
pg_lc_ctype: C                    # database character type, `C` by default
#pgsodium_key: ""                 # pgsodium key, 64 hex digit, default to sha256(pg_cluster)
#pgsodium_getkey_script: ""       # pgsodium getkey script path, pgsodium_getkey by default

pg_data

参数名称: pg_data, 类型: path, 层次:C

Postgres 数据目录,默认为 /pg/data

这是一个指向底层实际数据目录的符号链接,在多处被使用,请不要修改它。参阅 PGSQL文件结构 获取详细信息。

pg_fs_main

参数名称: pg_fs_main, 类型: path, 层次:C

PostgreSQL 主数据盘的挂载点/文件系统路径,默认为/data/postgres

默认值:/data/postgres,它将直接用作 PostgreSQL 主数据目录的父目录。

建议使用 NVME SSD 作为 PostgreSQL 主数据存储,Pigsty默认为SSD存储进行了优化,但是也支持HDD。

您可以更改 pg_storage_typeHDD 以针对HDD存储进行优化。

pg_fs_backup

参数名称: pg_fs_backup, 类型: path, 层次:C

PostgreSQL 备份数据盘的挂载点/文件系统路径,默认为/data/backups

如果您使用的是默认的 pgbackrest_method = local,建议为备份存储使用一个单独的磁盘。

备份磁盘应足够大,以容纳所有的备份,至少足以容纳3个基础备份+2天的WAL归档。 通常容量不是什么大问题,因为您可以使用便宜且大的机械硬盘作为备份盘。

建议为备份存储使用一个单独的磁盘,否则 Pigsty 将回退到主数据磁盘,并占用主数据盘的容量与IO。

pg_storage_type

参数名称: pg_storage_type, 类型: enum, 层次:C

PostgreSQL 数据存储介质的类型:SSDHDD,默认为SSD

默认值:SSD,它会影响一些调优参数,如 random_page_costeffective_io_concurrency

pg_dummy_filesize

参数名称: pg_dummy_filesize, 类型: size, 层次:C

/pg/dummy的大小,默认值为64MiB,用于紧急使用的64MB磁盘空间。

当磁盘已满时,删除占位符文件可以为紧急使用释放一些空间,建议生产使用至少8GiB

pg_listen

参数名称: pg_listen, 类型: ip, 层次:C

PostgreSQL / Pgbouncer 的监听地址,默认为0.0.0.0(所有ipv4地址)。

您可以在此变量中使用占位符,例如:'${ip},${lo}''${ip},${vip},${lo}'

  • ${ip}:转换为 inventory_hostname,它是配置清单中定义的首要内网IP地址。
  • ${vip}:如果启用了 pg_vip_enabled,将使用 pg_vip_address 的主机部分。
  • ${lo}:将替换为127.0.0.1

对于高安全性要求的生产环境,建议限制监听的IP地址。

pg_port

参数名称: pg_port, 类型: port, 层次:C

PostgreSQL 服务器监听的端口,默认为 5432

pg_localhost

参数名称: pg_localhost, 类型: path, 层次:C

本地主机连接 PostgreSQL 使用的 Unix套接字目录,默认值为/var/run/postgresql

PostgreSQL 和 Pgbouncer 本地连接的Unix套接字目录,pg_exporter 和 patroni 都会优先使用 Unix 套接字访问 PostgreSQL。

pg_namespace

参数名称: pg_namespace, 类型: path, 层次:C

etcd 中使用的顶级命名空间,由 patroni 和 vip-manager 使用,默认值是:/pg,不建议更改。

patroni_enabled

参数名称: patroni_enabled, 类型: bool, 层次:C

是否启用 Patroni ?默认值为:true

如果禁用,则在初始化期间不会创建Postgres集群。Pigsty将跳过拉起 patroni的任务,当试图向现有的postgres实例添加一些组件时,可以使用此参数。

patroni_mode

参数名称: patroni_mode, 类型: enum, 层次:C

Patroni 工作模式:defaultpauseremove。默认值:default

  • default:正常使用 Patroni 引导 PostgreSQL 集群
  • pause:与default相似,但在引导后进入维护模式
  • remove:使用Patroni初始化集群,然后删除Patroni并使用原始 PostgreSQL。

patroni_port

参数名称: patroni_port, 类型: port, 层次:C

patroni监听端口,默认为8008,不建议更改。

Patroni API服务器在此端口上监听健康检查和API请求。

patroni_log_dir

参数名称: patroni_log_dir, 类型: path, 层次:C

patroni 日志目录,默认为 /pg/log/patroni,由 Vector 日志代理收集。

patroni_ssl_enabled

参数名称: patroni_ssl_enabled, 类型: bool, 层次:G

使用SSL保护patroni RestAPI通信吗?默认值为false

此参数是一个全局标志,只能在部署之前预先设置。因为如果为 patroni 启用了SSL,您将必须使用 HTTPS 而不是 HTTP 执行健康检查、获取指标,调用API。

patroni_watchdog_mode

参数名称: patroni_watchdog_mode, 类型: string, 层次:C

patroni看门狗模式:automaticrequiredoff,默认值为 off

在主库故障的情况下,Patroni 可以使用 看门狗 来强制关机旧主库节点以避免脑裂。

  • off:不使用看门狗。完全不进行 Fencing (默认行为)
  • automatic:如果内核启用了softdog模块并且看门狗属于dbsu,则启用 watchdog
  • required:强制启用 watchdog,如果softdog不可用则拒绝启动 Patroni/PostgreSQL。

默认值为off,您不应该在 Infra节点 启用看门狗,数据一致性优先于可用性的关键系统,特别是与钱有关的业务集群可以考虑打开此选项。

注意:当使用 pg_conf = crit 配置模板时,off 会被自动提升为 automatic,以确保关键业务系统的数据一致性。

请注意,如果您的所有访问流量都使用 HAproxy 健康检查 服务接入,正常是不存在脑裂风险的。

patroni_username

参数名称: patroni_username, 类型: username, 层次:C

Patroni REST API 用户名,默认为 postgres,与 patroni_password 配对使用。

Patroni的危险 REST API (比如重启集群)由额外的用户名/密码保护,查看 配置集群Patroni RESTAPI 以获取详细信息。

patroni_password

参数名称: patroni_password, 类型: password, 层次:C

Patroni REST API 密码,默认为Patroni.API

警告:务必生产环境中修改此参数!

pg_primary_db

参数名称: pg_primary_db, 类型: string, 层次:C

指定集群中的主数据库名称,用于 citus 等业务数据库,默认为 postgres

例如,在使用 Patroni 管理高可用的 Citus 集群时,您必须选择一个 “主数据库”。

此外,在这里指定的数据库名称,将在 PGSQL 模块安装完成后,显示在打印的连接串中。

pg_parameters

参数名称: pg_parameters, 类型: dict, 层次:G/C/I

可用于指定并管理 postgresql.auto.conf 中的配置参数。

当集群所有实例完成初始化后,pg_param 任务将会把本字典中的 key / value 键值对依次覆盖写入 /pg/data/postgresql.auto.conf 中。

注意:请不要手工修改该配置文件,或通过 ALTER SYSTEM 修改集群配置参数,修改会在下一次配置同步时被覆盖。

该变量的优先级大于 Patroni / DCS 中的集群配置(即优先级高于集群配置,由 Patroni edit-config 编辑的配置),因此通常可以在实例级别覆盖集群默认参数。

当您的集群成员有着不同的规格(不推荐的行为!)时,您可以通过本参数对每个实例的配置进行精细化管理。

pg-test:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary , pg_parameters: { shared_buffers: '5GB' } }
    10.10.10.12: { pg_seq: 2, pg_role: replica , pg_parameters: { shared_buffers: '4GB' } }
    10.10.10.13: { pg_seq: 3, pg_role: replica , pg_parameters: { shared_buffers: '3GB' } }

请注意,一些 重要的集群参数(对主从库参数值有要求)是 Patroni 直接通过命令行参数管理的,具有最高优先级,无法通过此方式覆盖,对于这些参数,您必须使用 Patroni edit-config 进行管理与配置。

在主从上必须保持一致的 PostgreSQL 参数(不一致会导致从库无法启动!):

  • wal_level
  • max_connections
  • max_locks_per_transaction
  • max_worker_processes
  • max_prepared_transactions
  • track_commit_timestamp

在主从上最好保持一致的参数(考虑到主从切换的可能性):

  • listen_addresses
  • port
  • cluster_name
  • hot_standby
  • wal_log_hints
  • max_wal_senders
  • max_replication_slots
  • wal_keep_segments
  • wal_keep_size

您可以设置不存在的参数(例如来自扩展的 GUC,从而配置 ALTER SYSTEM 无法修改的“尚未存在”的参数),但将现有配置修改为非法值可能会导致 PostgreSQL 无法启动,请谨慎配置!

pg_files

参数名称: pg_files, 类型: path[], 层次:C

用于指定需要拷贝至PGDATA目录的文件列表,默认为空数组:[]

在本参数中指定的文件将会被拷贝至 {{ pg_data }} 目录下,这主要用于下发特殊商业版本 PostgreSQL 内核要求的 License 文件。

目前仅有 PolarDB (Oracle兼容)内核需要许可证文件,例如,您可以将 license.lic 文件放置在 files/ 目录下,并在 pg_files 中指定:

pg_files: [ license.lic ]

pg_conf

参数名称: pg_conf, 类型: enum, 层次:C

配置模板:{oltp,olap,crit,tiny}.yml,默认为oltp.yml

  • tiny.yml:为小节点、虚拟机、小型演示优化(1-8核,1-16GB)
  • oltp.yml:为OLTP工作负载和延迟敏感应用优化(4C8GB+)(默认模板)
  • olap.yml:为OLAP工作负载和吞吐量优化(4C8G+)
  • crit.yml:为数据一致性和关键应用优化(4C8G+)

默认值:oltp.yml,但是 配置 程序将在当前节点为小节点时将此值设置为 tiny.yml

您可以拥有自己的模板,只需将其放在templates/<mode>.yml下,并将此值设置为模板名称即可使用。

pg_max_conn

参数名称: pg_max_conn, 类型: int, 层次:C

PostgreSQL 服务器最大连接数。你可以选择一个介于 50 到 5000 之间的值,或使用 auto 选择推荐值。

默认值为 auto,会根据 pg_confpg_default_service_dest 来设定最大连接数。

  • tiny: 100
  • olap: 200
  • oltp: 200 (pgbouncer) / 1000 (postgres)
    • pg_default_service_dest = pgbouncer : 200
    • pg_default_service_dest = postgres : 1000
  • crit: 200 (pgbouncer) / 1000 (postgres)
    • pg_default_service_dest = pgbouncer : 200
    • pg_default_service_dest = postgres : 1000

不建议将此值设定为超过 5000,否则你还需要手动增加 haproxy 服务的连接限制。

Pgbouncer 的事务池可以缓解过多的 OLTP 连接问题,因此默认情况下不建议设置很大的连接数。

对于 OLAP 场景, pg_default_service_dest 修改为 postgres 可以绕过连接池。

pg_shared_buffer_ratio

参数名称: pg_shared_buffer_ratio, 类型: float, 层次:C

Postgres 共享缓冲区内存比例,默认为 0.25,正常范围在 0.1~0.4 之间。

默认值:0.25,意味着节点内存的 25% 将被用作 PostgreSQL 的分片缓冲区。如果您想为 PostgreSQL 启用大页,那么此参数值应当适当小于 node_hugepage_ratio

将此值设定为大于 0.4(40%)通常不是好主意,但在极端情况下可能有用。

注意,共享缓冲区只是 PostgreSQL 中共享内存的一部分,要计算总共享内存,使用 show shared_memory_size_in_huge_pages;

pg_rto

参数名称: pg_rto, 类型: enum, 层次:C

恢复时间目标(RTO)模式,用于控制 Patroni 与 HAProxy 的超时参数,默认为 norm

Pigsty 提供四种预设的 RTO 模式,分别针对不同的网络条件与部署场景进行了优化:

模式适用场景网络条件平均 RTO最坏 RTO误切风险
fast同机柜/同交换机< 1ms,极稳定14s29s较高
norm同机房(默认)1-5ms,正常21s43s中等
safe同省跨机房10-50ms,跨机房43s91s较低
wide跨地域/跨洲100-200ms,公网92s207s极低

减小 RTO 可以加快故障恢复速度,但会增加误切风险(网络抖动被误判为故障)。您需要根据实际网络条件选择合适的模式。 更多详情请参阅 RTO 利弊权衡 文档。

为了向后兼容,也支持直接指定秒数,系统会自动映射到最接近的模式:< 30fast30-44norm45-89safe≥ 90wide

pg_rto: norm   # 默认模式,适合同机房部署
pg_rto: safe   # 跨机房部署推荐
pg_rto: 30     # 兼容旧版写法,等效于 norm

pg_rto_plan

参数名称: pg_rto_plan, 类型: dict, 层次:G

RTO 预设配置字典,定义了 Patroni 高可用与 HAProxy 健康检查的具体超时参数,默认值包含四种预设模式:

pg_rto_plan:  # [ttl, loop, retry, start, margin, inter, fastinter, downinter, rise, fall]
  fast: [ 20  ,5  ,5  ,15 ,5  ,'1s' ,'0.5s' ,'1s' ,3 ,3 ]  # rto < 30s
  norm: [ 30  ,5  ,10 ,25 ,5  ,'2s' ,'1s'   ,'2s' ,3 ,3 ]  # rto < 45s
  safe: [ 60  ,10 ,20 ,45 ,10 ,'3s' ,'1.5s' ,'3s' ,3 ,3 ]  # rto < 90s
  wide: [ 120 ,20 ,30 ,95 ,15 ,'4s' ,'2s'   ,'4s' ,3 ,3 ]  # rto < 150s

每个模式是一个包含 10 个参数的数组,用于同时控制 Patroni 和 HAProxy 的超时行为:

索引参数名组件说明
0ttlPatroni主库锁 TTL(秒)
1loop_waitPatroni主循环休眠间隔(秒)
2retry_timeoutPatroniDCS/PostgreSQL 重试超时
3primary_start_timeoutPatroni主库恢复等待时间
4safety_marginPatroniWatchdog 安全边界
5interHAProxy健康检查间隔
6fastinterHAProxy状态变化时的快速检查间隔
7downinterHAProxy服务器宕机时的检查间隔
8riseHAProxy标记为 UP 所需的连续成功检查次数
9fallHAProxy标记为 DOWN 所需的连续失败检查次数

此参数允许用户通过覆盖默认值来自定义 RTO 行为,或添加新的 RTO 模式。例如,如果您需要一个更激进的 RTO 配置:

pg_rto_plan:
  ultra: [ 10, 2, 3, 8, 2, '0.5s', '0.25s', '0.5s', 2, 2 ]  # 极速模式,仅限低延迟环境

注意:修改此参数需要谨慎,不恰当的超时配置可能导致集群不稳定或频繁误切换。

pg_rpo

参数名称: pg_rpo, 类型: int, 层次:C

以字节为单位的恢复点目标(RPO),默认值:1048576

默认为 1MiB,这意味着在故障转移期间最多可以容忍 1MiB 的数据丢失。

当主节点宕机并且所有副本都滞后时,你必须做出一个艰难的选择,在可用性和一致性之间进行权衡

  • 提升一个从库成为新的主库,并尽快将系统恢复服务,但要付出可接受的数据丢失代价(例如,少于 1MB)。
  • 等待主库重新上线(可能永远不会),或人工干预以避免任何数据丢失。

你可以使用 crit.yml conf 模板来确保在故障转移期间没有数据丢失,但这会牺牲一些性能。

pg_libs

参数名称: pg_libs, 类型: string, 层次:C

预加载的动态共享库,默认为 pg_stat_statements,auto_explain,这是两个 PostgreSQL 自带的扩展,强烈建议启用。

对于现有集群,您可以直接 配置集群shared_preload_libraries 参数并应用生效。

如果您想使用 TimescaleDB 或 Citus 扩展,您需要将 timescaledbcitus 添加到此列表中。timescaledbcitus 应当放在这个列表的最前面,例如:

citus,timescaledb,pg_stat_statements,auto_explain

其他需要动态加载的扩展也可以添加到这个列表中,例如 pg_cronpgml 等,通常 citustimescaledb 有着最高的优先级,应该添加到列表的最前面。

pg_delay

参数名称: pg_delay, 类型: interval, 层次:I

延迟备库复制延迟,默认值:0

如果此值被设置为一个正值,备用集群主库在应用 WAL 变更之前将被延迟这个时间。设置为 1h 意味着该集群中的数据将始终滞后原集群一个小时。

查看 延迟备用集群 以获取详细信息。

pg_checksum

参数名称: pg_checksum, 类型: bool, 层次:C

为 PostgreSQL 集群启用数据校验和吗?默认值是 true,启用。

这个参数只能在 PGSQL 部署之前设置(但你可以稍后手动启用它)。

数据校验和可以帮助检测磁盘损坏和硬件故障,从 Pigsty v3.5 开始默认启用此功能以确保数据完整性。

pg_pwd_enc

参数名称: pg_pwd_enc, 类型: enum, 层次:C

密码加密算法,Pigsty v4 以后固定为 scram-sha-256

所有新建用户都会使用 SCRAM 凭据。md5 已被淘汰,如需兼容旧客户端,请在业务连接池或客户端驱动中升级至 SCRAM。

pg_encoding

参数名称: pg_encoding, 类型: enum, 层次:C

数据库集群编码,默认为 UTF8

不建议使用其他非 UTF8 系编码。

pg_locale

参数名称: pg_locale, 类型: enum, 层次:C

数据库集群本地化规则集 (Locale),默认为 C

此参数控制数据库的默认 Locale 设置,影响排序规则、字符分类等行为。使用 CPOSIX 可以获得最佳的性能和可预测的排序行为。

如果您需要特定语言的本地化支持,可以设置为相应的 Locale,例如 en_US.UTF-8zh_CN.UTF-8。请注意,Locale 设置会影响索引的排序顺序,因此在集群初始化后无法更改。

pg_lc_collate

参数名称: pg_lc_collate, 类型: enum, 层次:C

数据库集群本地化排序规则,默认为 C

除非您知道自己在做什么,否则不建议修改集群级别的本地排序规则设置。

pg_lc_ctype

参数名称: pg_lc_ctype, 类型: enum, 层次:C

数据库字符集 CTYPE,默认为 C

从 Pigsty v3.5 开始,为了与 pg_lc_collate 保持一致,默认值改为 C

pg_io_method

参数名称: pg_io_method, 类型: enum, 层次:C

PostgreSQL 的 IO 方法,默认为 worker。可选值包括:

  • auto:根据操作系统自动选择,在 Debian 系列或 EL 10+ 上使用 io_uring,否则使用 worker
  • sync:使用传统的同步 IO 方式
  • worker:使用后台工作进程处理 IO(默认选项)
  • io_uring:使用 Linux 的 io_uring 异步 IO 接口

此参数仅适用于 PostgreSQL 17 及以上版本,控制 PostgreSQL 数据块层的 IO 策略。

  • 在 PostgreSQL 17 中,io_uring 可以提供更高的 IO 性能,但需要操作系统内核支持(Linux 5.1+)并安装 liburing 库。
  • 在 PostgreSQL 18 中,默认 IO 方法已从 sync 改为 worker,使用后台工作进程处理异步 IO,无需额外依赖。
  • 如果您使用 Debian 12/Ubuntu 22+ 或 EL 10+ 系统,并希望获得最佳 IO 性能,可以考虑设置为 io_uring

请注意,在不支持 io_uring 的系统上设置此值可能导致 PostgreSQL 启动失败,因此 autoworker 是更安全的选择。

pg_etcd_password

参数名称: pg_etcd_password, 类型: password, 层次:C

此 PostgreSQL 集群在 etcd 中使用的密码,默认为空字符串 ''

如果设置为空字符串,则会使用 pg_cluster 参数值作为密码(对于 Citus 集群则使用 pg_shard 参数值)。

此密码用于 Patroni 连接 etcd 以及 vip-manager 访问 etcd 时的认证。

pgsodium_key

参数名称: pgsodium_key, 类型: string, 层次:C

用于 pgsodium 扩展的加密主密钥,由 64 位十六进制数字组成。

默认不设置此参数,如果未指定,Pigsty 会使用 sha256(pg_cluster) 的值自动生成一个确定性的密钥。

pgsodium 是一个基于 libsodium 的 PostgreSQL 扩展,提供加密函数和透明列加密功能。 如果您需要使用 pgsodium 的加密功能,建议显式指定一个安全的随机密钥,并妥善保管。

生成随机密钥的命令示例:

openssl rand -hex 32   # 生成 64 位十六进制密钥

pgsodium_getkey_script

参数名称: pgsodium_getkey_script, 类型: path, 层次:C

pgsodium 获取密钥脚本的路径,默认使用 Pigsty 模板中的 pgsodium_getkey 脚本。

此脚本用于在 PostgreSQL 启动时获取 pgsodium 的主密钥。默认脚本会从环境变量或配置文件中读取密钥。

如果您有自定义的密钥管理需求(如使用 HashiCorp Vault、AWS KMS 等),可以提供自定义脚本路径。

PG_PROVISION

如果说 PG_BOOTSTRAP 是创建一个新的集群,那么 PG_PROVISION 就是在集群中创建默认的对象,包括:

pg_provision: true                # 在引导后提供postgres集群
pg_init: pg-init                  # 集群模板的初始化脚本,默认为`pg-init`
pg_default_roles:                 # postgres集群中的默认角色和用户
  - { name: dbrole_readonly  ,login: false ,comment: role for global read-only access     }
  - { name: dbrole_offline   ,login: false ,comment: role for restricted read-only access }
  - { name: dbrole_readwrite ,login: false ,roles: [dbrole_readonly] ,comment: role for global read-write access }
  - { name: dbrole_admin     ,login: false ,roles: [pg_monitor, dbrole_readwrite] ,comment: role for object creation }
  - { name: postgres     ,superuser: true  ,comment: system superuser }
  - { name: replicator ,replication: true  ,roles: [pg_monitor, dbrole_readonly] ,comment: system replicator }
  - { name: dbuser_dba   ,superuser: true  ,roles: [dbrole_admin]  ,pgbouncer: true ,pool_mode: session, pool_connlimit: 16 ,comment: pgsql admin user }
  - { name: dbuser_monitor ,roles: [pg_monitor, dbrole_readonly] ,pgbouncer: true ,parameters: {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment: pgsql monitor user }
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
pg_default_schemas: [ monitor ]   # 默认模式
pg_default_extensions:            # 默认扩展
  - { name: pg_stat_statements ,schema: monitor }
  - { name: pgstattuple        ,schema: monitor }
  - { name: pg_buffercache     ,schema: monitor }
  - { name: pageinspect        ,schema: monitor }
  - { name: pg_prewarm         ,schema: monitor }
  - { name: pg_visibility      ,schema: monitor }
  - { name: pg_freespacemap    ,schema: monitor }
  - { name: postgres_fdw       ,schema: public  }
  - { name: file_fdw           ,schema: public  }
  - { name: btree_gist         ,schema: public  }
  - { name: btree_gin          ,schema: public  }
  - { name: pg_trgm            ,schema: public  }
  - { name: intagg             ,schema: public  }
  - { name: intarray           ,schema: public  }
  - { name: pg_repack }
pg_reload: true                   # HBA变化后是否重载配置?
pg_default_hba_rules:             # postgres 默认 HBA 规则集,按 order 排序
  - {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}
pgb_default_hba_rules:            # pgbouncer 默认 HBA 规则集,按 order 排序
  - {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}

pg_provision

参数名称: pg_provision, 类型: bool, 层次:C

在集群拉起后,完整本节定义的 PostgreSQL 集群置备工作。默认值为true

如果禁用,不会置备 PostgreSQL 集群。对于一些特殊的 “PostgreSQL” 集群,比如 Greenplum,可以关闭此选项跳过置备阶段。

pg_init

参数名称: pg_init, 类型: string, 层次:G/C

用于初始化数据库模板的Shell脚本位置,默认为 pg-init,该脚本会被拷贝至/pg/bin/pg-init后执行。

该脚本位于 roles/pgsql/templates/pg-init

你可以在该脚本中添加自己的逻辑,或者提供一个新的脚本放置在 templates/ 目录下,并将 pg_init 设置为新的脚本名称。使用自定义脚本时请保留现有的初始化逻辑。

pg_default_roles

参数名称: pg_default_roles, 类型: role[], 层次:G/C

Postgres 集群中的默认角色和用户。

Pigsty有一个内置的角色系统,请查看 PGSQL访问控制:角色系统 了解详情。

pg_default_roles:                 # postgres集群中的默认角色和用户
  - { name: dbrole_readonly  ,login: false ,comment: role for global read-only access     }
  - { name: dbrole_offline   ,login: false ,comment: role for restricted read-only access }
  - { name: dbrole_readwrite ,login: false ,roles: [dbrole_readonly]               ,comment: role for global read-write access }
  - { name: dbrole_admin     ,login: false ,roles: [pg_monitor, dbrole_readwrite]  ,comment: role for object creation }
  - { name: postgres     ,superuser: true                                          ,comment: system superuser }
  - { name: replicator ,replication: true  ,roles: [pg_monitor, dbrole_readonly]   ,comment: system replicator }
  - { name: dbuser_dba   ,superuser: true  ,roles: [dbrole_admin]  ,pgbouncer: true ,pool_mode: session, pool_connlimit: 16 , comment: pgsql admin user }
  - { name: dbuser_monitor   ,roles: [pg_monitor, dbrole_readonly] ,pgbouncer: true ,parameters: {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment: pgsql monitor user }

pg_default_privileges

参数名称: pg_default_privileges, 类型: string[], 层次:G/C

每个数据库中的默认权限(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

Pigsty 基于默认角色系统提供了相应的默认权限设置,请查看 PGSQL访问控制:权限 了解详情。

pg_default_schemas

参数名称: pg_default_schemas, 类型: string[], 层次:G/C

要创建的默认模式,默认值为:[ monitor ],这将在所有数据库上创建一个monitor模式,用于放置各种监控扩展、表、视图、函数。

pg_default_extensions

参数名称: pg_default_extensions, 类型: extension[], 层次:G/C

要在所有数据库中默认创建启用的扩展列表,默认值:

pg_default_extensions: # default extensions to be created
  - { name: pg_stat_statements ,schema: monitor }
  - { name: pgstattuple        ,schema: monitor }
  - { name: pg_buffercache     ,schema: monitor }
  - { name: pageinspect        ,schema: monitor }
  - { name: pg_prewarm         ,schema: monitor }
  - { name: pg_visibility      ,schema: monitor }
  - { name: pg_freespacemap    ,schema: monitor }
  - { name: postgres_fdw       ,schema: public  }
  - { name: file_fdw           ,schema: public  }
  - { name: btree_gist         ,schema: public  }
  - { name: btree_gin          ,schema: public  }
  - { name: pg_trgm            ,schema: public  }
  - { name: intagg             ,schema: public  }
  - { name: intarray           ,schema: public  }
  - { name: pg_repack }

唯一的三方扩展是 pg_repack,这对于数据库维护很重要,所有其他扩展都是内置的 PostgreSQL Contrib 扩展插件。

监控相关的扩展默认安装在 monitor 模式中,该模式由 pg_default_schemas 创建。

pg_reload

参数名称: pg_reload, 类型: bool, 层次:A

在hba更改后重新加载 PostgreSQL,默认值为true

当您想在应用HBA更改之前进行检查时,将其设置为false以禁用自动重新加载配置。

pg_default_hba_rules

参数名称: pg_default_hba_rules, 类型: hba[], 层次:G/C

PostgreSQL 基于主机的认证规则,全局默认规则定义。默认值为:

pg_default_hba_rules:             # postgres default host-based authentication rules, order by `order`
  - {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}

默认值为常见场景提供了足够的安全级别,请查看 PGSQL身份验证 了解详情。

本参数为 HBA 规则对象组成的数组,在形式上与 pg_hba_rules 完全一致。 建议在全局配置统一的 pg_default_hba_rules,针对特定集群使用 pg_hba_rules 进行额外定制。两个参数中的规则都会依次应用,后者优先级更高。

pgb_default_hba_rules

参数名称: pgb_default_hba_rules, 类型: hba[], 层次:G/C

pgbouncer default host-based authentication rules, array or hba rule object.

default value provides a fair enough security level for common scenarios, check PGSQL Authentication for details.

pgb_default_hba_rules:            # pgbouncer default host-based authentication rules, order by `order`
  - {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}

默认的Pgbouncer HBA规则很简单:

  1. 允许从本地使用密码登陆
  2. 允许从内网网断使用密码登陆

用户可以按照自己的需求进行定制。

本参数在形式上与 pgb_hba_rules 完全一致,建议在全局配置统一的 pgb_default_hba_rules,针对特定集群使用 pgb_hba_rules 进行额外定制。两个参数中的规则都会依次应用,后者优先级更高。


PG_BACKUP

本节定义了用于 pgBackRest 的变量,它被用于 PGSQL 时间点恢复 PITR 。

查看 PGSQL 备份 & PITR 以获取详细信息。

pgbackrest_enabled: true          # 在 pgsql 主机上启用 pgBackRest 吗?
pgbackrest_clean: true            # 初始化时删除 pg 备份数据?
pgbackrest_log_dir: /pg/log/pgbackrest # pgbackrest 日志目录,默认为 `/pg/log/pgbackrest`
pgbackrest_method: local          # pgbackrest 仓库方法:local, minio, [用户定义...]
pgbackrest_init_backup: true      # pgbackrest 初始化完成后是否立即执行全量备份?
pgbackrest_repo:                  # pgbackrest 仓库:https://pgbackrest.org/configuration.html#section-repository
  local:                          # 默认使用本地 posix 文件系统的 pgbackrest 仓库
    path: /pg/backup              # 本地备份目录,默认为 `/pg/backup`
    retention_full_type: count    # 按计数保留完整备份
    retention_full: 2             # 使用本地文件系统仓库时,最多保留 3 个完整备份,至少保留 2 个
  minio:                          # pgbackrest 的可选 minio 仓库
    type: s3                      # minio 是与 s3 兼容的,所以使用 s3
    s3_endpoint: sss.pigsty       # minio 端点域名,默认为 `sss.pigsty`
    s3_region: us-east-1          # minio 区域,默认为 us-east-1,对 minio 无效
    s3_bucket: pgsql              # minio 桶名称,默认为 `pgsql`
    s3_key: pgbackrest            # pgbackrest 的 minio 用户访问密钥
    s3_key_secret: S3User.Backup  # pgbackrest 的 minio 用户秘密密钥
    s3_uri_style: path            # 对 minio 使用路径风格的 uri,而不是主机风格
    path: /pgbackrest             # minio 备份路径,默认为 `/pgbackrest`
    storage_port: 9000            # minio 端口,默认为 9000
    storage_ca_file: /etc/pki/ca.crt  # minio ca 文件路径,默认为 `/etc/pki/ca.crt`
    block: y                      # 启用块级增量备份(pgBackRest 2.46+)
    bundle: y                     # 将小文件打包成一个文件
    bundle_limit: 20MiB           # 对象存储文件打包阈值,默认 20MiB
    bundle_size: 128MiB           # 对象存储文件打包目标大小,默认 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码,默认为 'pgBackRest'
    retention_full_type: time     # 在 minio 仓库上按时间保留完整备份
    retention_full: 14            # 保留过去 14 天的完整备份

pgbackrest_enabled

参数名称: pgbackrest_enabled, 类型: bool, 层次:C

是否在 PGSQL 节点上启用 pgBackRest?默认值为: true

在使用本地文件系统备份仓库(local)时,只有集群主库才会真正启用 pgbackrest。其他实例只会初始化一个空仓库。

pgbackrest_clean

参数名称: pgbackrest_clean, 类型: bool, 层次:C

初始化时删除 PostgreSQL 备份数据吗?默认值为 true

pgbackrest_log_dir

参数名称: pgbackrest_log_dir, 类型: path, 层次:C

pgBackRest 日志目录,默认为 /pg/log/pgbackrest,Vector 日志代理会引用此参数收集日志。

pgbackrest_method

参数名称: pgbackrest_method, 类型: enum, 层次:C

pgBackRest 仓库方法:默认可选项为:localminio 或其他用户定义的方法,默认为 local

此参数用于确定用于 pgBackRest 的仓库,所有可用的仓库方法都在 pgbackrest_repo 中定义。

Pigsty 默认使用 local 备份仓库,这将在主实例的 /pg/backup 目录上创建一个备份仓库。底层存储路径由 pg_fs_backup 指定。

pgbackrest_init_backup

参数名称: pgbackrest_init_backup, 类型: bool, 层次:C

在 pgBackRest 初始化完成后是否立即执行一次全量备份?默认为 true

此操作仅在集群主库(primary)且非级联从库(无 pg_upstream 定义)时执行。启用此参数可以确保在集群初始化后立即拥有一个基础备份,以便在需要时进行恢复。

pgbackrest_repo

参数名称: pgbackrest_repo, 类型: dict, 层次:G/C

pgBackRest 仓库文档:https://pgbackrest.org/configuration.html#section-repository

默认值包括两种仓库方法:localminio,定义如下:

pgbackrest_repo:                  # pgbackrest 仓库:https://pgbackrest.org/configuration.html#section-repository
  local:                          # 默认使用本地 posix 文件系统的 pgbackrest 仓库
    path: /pg/backup              # 本地备份目录,默认为 `/pg/backup`
    retention_full_type: count    # 按计数保留完整备份
    retention_full: 2             # 使用本地文件系统仓库时,最多保留 3 个完整备份,至少保留 2 个
  minio:                          # pgbackrest 的可选 minio 仓库
    type: s3                      # minio 是与 s3 兼容的,所以使用 s3
    s3_endpoint: sss.pigsty       # minio 端点域名,默认为 `sss.pigsty`
    s3_region: us-east-1          # minio 区域,默认为 us-east-1,对 minio 无效
    s3_bucket: pgsql              # minio 桶名称,默认为 `pgsql`
    s3_key: pgbackrest            # pgbackrest 的 minio 用户访问密钥
    s3_key_secret: S3User.Backup  # pgbackrest 的 minio 用户秘密密钥
    s3_uri_style: path            # 对 minio 使用路径风格的 uri,而不是主机风格
    path: /pgbackrest             # minio 备份路径,默认为 `/pgbackrest`
    storage_port: 9000            # minio 端口,默认为 9000
    storage_ca_file: /etc/pki/ca.crt  # minio ca 文件路径,默认为 `/etc/pki/ca.crt`
    block: y                      # 启用块级增量备份(pgBackRest 2.46+)
    bundle: y                     # 将小文件打包成一个文件
    bundle_limit: 20MiB           # 对象存储文件打包阈值,默认 20MiB
    bundle_size: 128MiB           # 对象存储文件打包目标大小,默认 128MiB
    cipher_type: aes-256-cbc      # 为远程备份仓库启用 AES 加密
    cipher_pass: pgBackRest       # AES 加密密码,默认为 'pgBackRest'
    retention_full_type: time     # 在 minio 仓库上按时间保留完整备份
    retention_full: 14            # 保留过去 14 天的完整备份

您可以定义新的备份仓库,例如使用 AWS S3,GCP 或其他云供应商的 S3 兼容存储服务。

块级增量备份 (Block Incremental Backup):从 pgBackRest 2.46 版本开始支持 block: y 选项,可以实现块级增量备份。 这意味着在增量备份时,pgBackRest 只会备份发生变化的数据块,而不是整个变化的文件,从而大幅减少备份数据量和备份时间。 此功能对于大型数据库特别有用,建议在对象存储仓库上启用此选项。


PG_ACCESS

本节负责数据库访问路径,包括:

  • 在每个 PGSQL 节点上部署 Pgbouncer 连接池并设定默认行为
  • 通过本地或专用 haproxy 节点发布服务端口
  • 绑定可选的 L2 VIP、注册 DNS 记录
pgbouncer_enabled: true           # if disabled, pgbouncer will not be launched on pgsql host
pgbouncer_port: 6432              # pgbouncer listen port, 6432 by default
pgbouncer_log_dir: /pg/log/pgbouncer  # pgbouncer log dir, `/pg/log/pgbouncer` by default
pgbouncer_auth_query: false       # query postgres to retrieve unlisted business users?
pgbouncer_poolmode: transaction   # pooling mode: transaction,session,statement, transaction by default
pgbouncer_sslmode: disable        # pgbouncer client ssl mode, disable by default
pgbouncer_ignore_param: [ extra_float_digits, application_name, TimeZone, DateStyle, IntervalStyle, search_path ]
pg_weight: 100          #INSTANCE # relative load balance weight in service, 100 by default, 0-255
pg_service_provider: ''           # dedicate haproxy node group name, or empty string for local nodes by default
pg_default_service_dest: pgbouncer # default service destination if svc.dest='default'
pg_default_services:              # postgres default service definitions
  - { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }
  - { name: replica ,port: 5434 ,dest: default  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
  - { name: default ,port: 5436 ,dest: postgres ,check: /primary   ,selector: "[]" }
  - { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]"}
pg_vip_enabled: false             # enable a l2 vip for pgsql primary? false by default
pg_vip_address: 127.0.0.1/24      # vip address in `<ipv4>/<mask>` format, require if vip is enabled
pg_vip_interface: eth0            # vip network interface to listen, eth0 by default
pg_dns_suffix: ''                 # pgsql dns suffix, '' by default
pg_dns_target: auto               # auto, primary, vip, none, or ad hoc ip

pgbouncer_enabled

参数名称: pgbouncer_enabled, 类型: bool, 层次:C

默认值为 true,如果禁用,将不会在 PGSQL节点 上配置连接池 Pgbouncer。

pgbouncer_port

参数名称: pgbouncer_port, 类型: port, 层次:C

Pgbouncer 监听端口,默认为 6432

pgbouncer_log_dir

参数名称: pgbouncer_log_dir, 类型: path, 层次:C

Pgbouncer 日志目录,默认为 /pg/log/pgbouncer,Vector 日志代理会根据此参数收集 Pgbouncer 日志。

pgbouncer_auth_query

参数名称: pgbouncer_auth_query, 类型: bool, 层次:C

是否允许 Pgbouncer 查询 PostgreSQL,以允许未显式列出的用户通过连接池访问 PostgreSQL?默认值是 false

如果启用,pgbouncer 用户将使用 SELECT username, password FROM monitor.pgbouncer_auth($1) 对 postgres 数据库进行身份验证,否则,只有带有 pgbouncer: true 的业务用户才被允许连接到 Pgbouncer 连接池。

pgbouncer_poolmode

参数名称: pgbouncer_poolmode, 类型: enum, 层次:C

Pgbouncer 连接池池化模式:transaction,session,statement,默认为 transaction

  • session:会话级池化,具有最佳的功能兼容性。
  • transaction:事务级池化,具有更好的性能(许多小连接),可能会破坏某些会话级特性,如NOTIFY/LISTEN 等…
  • statements:语句级池化,用于简单的只读查询。

如果您的应用出现功能兼容性问题,可以考虑修改此参数为 session

pgbouncer_sslmode

参数名称: pgbouncer_sslmode, 类型: enum, 层次:C

Pgbouncer 客户端 ssl 模式,默认为 disable

注意,启用 SSL 可能会对你的 pgbouncer 产生巨大的性能影响。

  • disable:如果客户端请求 TLS 则忽略(默认)
  • allow:如果客户端请求 TLS 则使用。如果没有则使用纯TCP。不验证客户端证书。
  • prefer:与 allow 相同。
  • require:客户端必须使用 TLS。如果没有则拒绝客户端连接。不验证客户端证书。
  • verify-ca:客户端必须使用有效的客户端证书的TLS。
  • verify-full:与 verify-ca 相同。

pgbouncer_ignore_param

参数名称: pgbouncer_ignore_param, 类型: string[], 层次:C

PgBouncer 忽略的启动参数列表,默认值为:

[ extra_float_digits, application_name, TimeZone, DateStyle, IntervalStyle, search_path ]

这些参数会被配置到 PgBouncer 配置文件中的 ignore_startup_parameters 选项。当客户端连接时设置这些参数时,PgBouncer 不会因为连接池中的连接参数不匹配而创建新的连接。

这允许不同的客户端使用相同的连接池,即使它们设置了不同的这些参数值。此参数在 Pigsty v3.5 中新增。


pg_weight

参数名称: pg_weight, 类型: int, 层次:I

服务中的相对负载均衡权重,默认为100,范围0-255。

默认值: 100。您必须在实例变量中定义它,并 重载服务 以生效。

pg_service_provider

参数名称: pg_service_provider, 类型: string, 层次:G/C

专用的haproxy节点组名,或默认为本地节点的空字符串。

如果指定,PostgreSQL服务将注册到专用的haproxy节点组,而不是当下的 PGSQL 集群节点。

请记住为每个服务在专用的 haproxy 节点上分配唯一的端口!

例如,如果我们在3节点的 pg-test 集群上定义以下参数:

pg_service_provider: infra       # use load balancer on group `infra`
pg_default_services:             # alloc port 10001 and 10002 for pg-test primary/replica service  
  - { name: primary ,port: 10001 ,dest: postgres  ,check: /primary   ,selector: "[]" }
  - { name: replica ,port: 10002 ,dest: postgres  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }

pg_default_service_dest

参数名称: pg_default_service_dest, 类型: enum, 层次:G/C

当定义一个 服务 时,如果 svc.dest='default',此参数将用作默认值。

默认值: pgbouncer,意味着5433主服务和5434副本服务将默认将流量路由到 pgbouncer。

如果您不想使用pgbouncer,将其设置为postgres。流量将直接路由到 postgres。

pg_default_services

参数名称: pg_default_services, 类型: service[], 层次:G/C

postgres默认服务定义

默认值是四个默认服务定义,如 PGSQL Service 所述

pg_default_services:               # postgres default service definitions
  - { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }
  - { name: replica ,port: 5434 ,dest: default  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
  - { name: default ,port: 5436 ,dest: postgres ,check: /primary   ,selector: "[]" }
  - { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]"}

pg_vip_enabled

参数名称: pg_vip_enabled, 类型: bool, 层次:C

为 PGSQL 集群启用 L2 VIP吗?默认值是false,表示不创建 L2 VIP。

启用 L2 VIP 后,会有一个 VIP 绑定在集群主实例节点上,由 vip-manager 管理,根据 etcd 中的数据进行判断。

L2 VIP只能在相同的L2网络中使用,这可能会对您的网络拓扑产生额外的限制。

pg_vip_address

参数名称: pg_vip_address, 类型: cidr4, 层次:C

如果启用vip,则需要<ipv4>/<mask>格式的vip地址。

默认值: 127.0.0.1/24。这个值由两部分组成:ipv4mask,用/分隔。

pg_vip_interface

参数名称: pg_vip_interface, 类型: string, 层次:C/I

vip network interface to listen, eth0 by default.

L2 VIP 监听的网卡接口,默认为 eth0

它应该是您节点的首要网卡名,即您在配置清单中使用的IP地址。

如果您的节点有多块名称不同的网卡,您可以在实例变量上进行覆盖:

pg-test:
    hosts:
        10.10.10.11: {pg_seq: 1, pg_role: replica ,pg_vip_interface: eth0 }
        10.10.10.12: {pg_seq: 2, pg_role: primary ,pg_vip_interface: eth1 }
        10.10.10.13: {pg_seq: 3, pg_role: replica ,pg_vip_interface: eth2 }
    vars:
      pg_vip_enabled: true          # 为这个集群启用L2 VIP,默认绑定到主实例
      pg_vip_address: 10.10.10.3/24 # L2网络CIDR: 10.10.10.0/24, vip地址: 10.10.10.3
      # pg_vip_interface: eth1      # 如果您的节点有统一的接口,您可以在这里定义它

pg_dns_suffix

参数名称: pg_dns_suffix, 类型: string, 层次:C

PostgreSQL DNS 名称后缀,默认为空字符串。

在默认情况下,PostgreQL 集群名会作为 DNS 域名注册到 Infra 节点的 dnsmasq 中对外提供解析。

您可以通过本参数指定一个域名后缀,这样会使用 {{ pg_cluster }}{{ pg_dns_suffix }} 作为集群 DNS 名称。

例如,如果您将 pg_dns_suffix 设置为 .db.vip.company.tld,那么 pg-test 的集群 DNS 名称将是 pg-test.db.vip.company.tld

pg_dns_target

参数名称: pg_dns_target, 类型: enum, 层次:C

Could be: auto, primary, vip, none, or an ad hoc ip address, which will be the target IP address of cluster DNS record.

default values: auto , which will bind to pg_vip_address if pg_vip_enabled, or fallback to cluster primary instance ip address.

  • vip: bind to pg_vip_address
  • primary: resolve to cluster primary instance ip address
  • auto: resolve to pg_vip_address if pg_vip_enabled, or fallback to cluster primary instance ip address.
  • none: do not bind to any ip address
  • <ipv4>: bind to the given IP address

可以是:autoprimaryvipnone或一个特定的IP地址,它将是集群DNS记录的解析目标IP地址。

默认值: auto,如果pg_vip_enabled,将绑定到pg_vip_address,否则会回退到集群主实例的 IP 地址。

  • vip:绑定到pg_vip_address
  • primary:解析为集群主实例IP地址
  • auto:如果 pg_vip_enabled,解析为 pg_vip_address,或回退到集群主实例ip地址。
  • none:不绑定到任何ip地址
  • <ipv4>:绑定到指定的IP地址

PG_MONITOR

PG_MONITOR 组的参数用于监控 PostgreSQL 数据库、Pgbouncer 连接池与 pgBackRest 备份系统的状态。

此参数组定义了三个 Exporter 的配置:pg_exporter 用于监控 PostgreSQL,pgbouncer_exporter 用于监控连接池,pgbackrest_exporter 用于监控备份状态。

pg_exporter_enabled: true              # 在 pgsql 主机上启用 pg_exporter 吗?
pg_exporter_config: pg_exporter.yml    # pg_exporter 配置文件名
pg_exporter_cache_ttls: '1,10,60,300'  # pg_exporter 收集器 ttl 阶段(秒),默认为 '1,10,60,300'
pg_exporter_port: 9630                 # pg_exporter 监听端口,默认为 9630
pg_exporter_params: 'sslmode=disable'  # pg_exporter dsn 的额外 url 参数
pg_exporter_url: ''                    # 如果指定,将覆盖自动生成的 pg dsn
pg_exporter_auto_discovery: true       # 启用自动数据库发现?默认启用
pg_exporter_exclude_database: 'template0,template1,postgres' # 在自动发现过程中不会被监控的数据库的 csv 列表
pg_exporter_include_database: ''       # 在自动发现过程中将被监控的数据库的 csv 列表
pg_exporter_connect_timeout: 200       # pg_exporter 连接超时(毫秒),默认为 200
pg_exporter_options: ''                # 覆盖 pg_exporter 的额外选项
pgbouncer_exporter_enabled: true       # 在 pgsql 主机上启用 pgbouncer_exporter 吗?
pgbouncer_exporter_port: 9631          # pgbouncer_exporter 监听端口,默认为 9631
pgbouncer_exporter_url: ''             # 如果指定,将覆盖自动生成的 pgbouncer dsn
pgbouncer_exporter_options: ''         # 覆盖 pgbouncer_exporter 的额外选项
pgbackrest_exporter_enabled: true      # 在 pgsql 主机上启用 pgbackrest_exporter 吗?
pgbackrest_exporter_port: 9854         # pgbackrest_exporter 监听端口,默认为 9854
pgbackrest_exporter_options: ''        # 覆盖 pgbackrest_exporter 的额外选项

pg_exporter_enabled

参数名称: pg_exporter_enabled, 类型: bool, 层次:C

是否在 PGSQL 节点上启用 pg_exporter?默认值为:true

PG Exporter 用于监控 PostgreSQL 数据库实例,如果不想安装 pg_exporter 可以设置为 false

pg_exporter_config

参数名称: pg_exporter_config, 类型: string, 层次:C

pg_exporter 配置文件名,PG Exporter 和 PGBouncer Exporter 都会使用这个配置文件。默认值:pg_exporter.yml

如果你想使用自定义配置文件,你可以在这里定义它。你的自定义配置文件应当放置于 files/<name>.yml

例如,当您希望监控一个远程的 PolarDB 数据库实例时,可以使用样例配置:files/polar_exporter.yml

pg_exporter_cache_ttls

参数名称: pg_exporter_cache_ttls, 类型: string, 层次:C

pg_exporter 收集器 TTL 阶梯(秒),默认为 ‘1,10,60,300’

默认值:1,10,60,300,它将为不同的度量收集器使用不同的TTL值: 1s, 10s, 60s, 300s。

PG Exporter 内置了缓存机制,避免多个 Prometheus 重复抓取对数据库产生不当影响,所有指标收集器按 TTL 分为四类:

ttl_fast: "{{ pg_exporter_cache_ttls.split(',')[0]|int }}"         # critical queries
ttl_norm: "{{ pg_exporter_cache_ttls.split(',')[1]|int }}"         # common queries
ttl_slow: "{{ pg_exporter_cache_ttls.split(',')[2]|int }}"         # slow queries (e.g table size)
ttl_slowest: "{{ pg_exporter_cache_ttls.split(',')[3]|int }}"      # ver slow queries (e.g bloat)

例如,在默认配置下,存活类指标默认最多缓存 1s,大部分普通指标会缓存 10s(应当与监控抓取间隔 victoria_scrape_interval 相同)。 少量变化缓慢的查询会有 60s 的TTL,极个别大开销监控查询会有 300s 的TTL。

pg_exporter_port

参数名称: pg_exporter_port, 类型: port, 层次:C

pg_exporter 监听端口号,默认值为:9630

pg_exporter_params

参数名称: pg_exporter_params, 类型: string, 层次:C

pg_exporter 所使用 DSN 中额外的 URL PATH 参数。

默认值:sslmode=disable,它将禁用用于监控连接的 SSL(因为默认使用本地 unix 套接字)。

pg_exporter_url

参数名称: pg_exporter_url, 类型: pgurl, 层次:C

如果指定了本参数,将会覆盖自动生成的 PostgreSQL DSN,使用指定的 DSN 连接 PostgreSQL 。默认值为空字符串。

如果没有指定此参数,PG Exporter 默认会使用以下的连接串访问 PostgreSQL :

postgres://{{ pg_monitor_username }}:{{ pg_monitor_password }}@{{ pg_host }}:{{ pg_port }}/postgres{% if pg_exporter_params != '' %}?{{ pg_exporter_params }}{% endif %}

当您想监控一个远程的 PostgreSQL 实例时,或者需要使用不同的监控用户/密码,配置选项时,可以使用这个参数。

pg_exporter_auto_discovery

参数名称: pg_exporter_auto_discovery, 类型: bool, 层次:C

启用自动数据库发现吗? 默认启用:true

PG Exporter 默认会连接到 DSN 中指定的数据库 (默认为管理数据库 postgres) 收集全局指标,如果您希望收集所有业务数据库的指标,可以开启此选项。 PG Exporter 会自动发现目标 PostgreSQL 实例中的所有数据库,并在这些数据库中收集 库级监控指标

pg_exporter_exclude_database

参数名称: pg_exporter_exclude_database, 类型: string, 层次:C

如果启用了数据库自动发现(默认启用),在这个参数指定的列表中的数据库将不会被监控。 默认值为: template0,template1,postgres,即管理数据库 postgres 与模板数据库会被排除在自动监控的数据库之外。

作为例外,DSN 中指定的数据库不受此参数影响,例如,PG Exporter 如果连接的是 postgres 数据库,那么即使 postgres 在此列表中,也会被监控。

pg_exporter_include_database

参数名称: pg_exporter_include_database, 类型: string, 层次:C

如果启用了数据库自动发现(默认启用),在这个参数指定的列表中的数据库才会被监控。默认值为空字符串,即不启用此功能。

参数的形式是由逗号分隔的数据库名称列表,例如:db1,db2,db3

此参数相对于 [pg_exporter_exclude_database] 有更高的优先级,相当于白名单模式。如果您只希望监控特定的数据库,可以使用此参数。

pg_exporter_connect_timeout

参数名称: pg_exporter_connect_timeout, 类型: int, 层次:C

pg_exporter 连接超时(毫秒),默认为 200 (单位毫秒)

当 PG Exporter 尝试连接到 PostgreSQL 数据库时,最多会等待多长时间?超过这个时间,PG Exporter 将会放弃连接并报错。

默认值 200毫秒 对于绝大多数场景(例如:同可用区监控)都是足够的,但是如果您监控的远程 PostgreSQL 位于另一个大洲,您可能需要增加此值以避免连接超时。

pg_exporter_options

参数名称: pg_exporter_options, 类型: arg, 层次:C

传给 PG Exporter 的命令行参数,默认值为:"" 空字符串。

当使用空字符串时,会使用默认的命令参数:

{% if pg_exporter_port != '' %}
PG_EXPORTER_OPTS='--web.listen-address=:{{ pg_exporter_port }} {{ pg_exporter_options }}'
{% else %}
PG_EXPORTER_OPTS='--web.listen-address=:{{ pg_exporter_port }} --log.level=info'
{% endif %}

注意,请不要在本参数中覆盖 pg_exporter_port 的端口配置。

pgbouncer_exporter_enabled

参数名称: pgbouncer_exporter_enabled, 类型: bool, 层次:C

在 PGSQL 节点上,是否启用 pgbouncer_exporter ?默认值为:true

pgbouncer_exporter_port

参数名称: pgbouncer_exporter_port, 类型: port, 层次:C

pgbouncer_exporter 监听端口号,默认值为:9631

pgbouncer_exporter_url

参数名称: pgbouncer_exporter_url, 类型: pgurl, 层次:C

如果指定了本参数,将会覆盖自动生成的 pgbouncer DSN,使用指定的 DSN 连接 pgbouncer。默认值为空字符串。

如果没有指定此参数,Pgbouncer Exporter 默认会使用以下的连接串访问 Pgbouncer:

postgres://{{ pg_monitor_username }}:{{ pg_monitor_password }}@:{{ pgbouncer_port }}/pgbouncer?host={{ pg_localhost }}&sslmode=disable

当您想监控一个远程的 Pgbouncer 实例时,或者需要使用不同的监控用户/密码,配置选项时,可以使用这个参数。

pgbouncer_exporter_options

参数名称: pgbouncer_exporter_options, 类型: arg, 层次:C

传给 Pgbouncer Exporter 的命令行参数,默认值为:"" 空字符串。

当使用空字符串时,会使用默认的命令参数:

{% if pgbouncer_exporter_options != '' %}
PG_EXPORTER_OPTS='--web.listen-address=:{{ pgbouncer_exporter_port }} {{ pgbouncer_exporter_options }}'
{% else %}
PG_EXPORTER_OPTS='--web.listen-address=:{{ pgbouncer_exporter_port }} --log.level=info'
{% endif %}

注意,请不要在本参数中覆盖 pgbouncer_exporter_port 的端口配置。

pgbackrest_exporter_enabled

参数名称: pgbackrest_exporter_enabled, 类型: bool, 层次:C

是否在 PGSQL 节点上启用 pgbackrest_exporter?默认值为:true

pgbackrest_exporter 用于监控 pgBackRest 备份系统的状态,包括备份的大小、时间、类型、持续时长等关键指标。

pgbackrest_exporter_port

参数名称: pgbackrest_exporter_port, 类型: port, 层次:C

pgbackrest_exporter 监听端口号,默认值为:9854

此端口需要在 Prometheus 服务发现配置中引用,用于抓取备份相关的监控指标。

pgbackrest_exporter_options

参数名称: pgbackrest_exporter_options, 类型: arg, 层次:C

传给 pgbackrest_exporter 的命令行参数,默认值为:"" 空字符串。

当使用空字符串时,会使用默认的命令参数配置。您可以在此指定额外的参数选项来调整 exporter 的行为。


PG_REMOVE

pgsql-rm.yml 会调用 pg_remove 角色来安全地移除 PostgreSQL 实例。本节参数用于控制清理行为,避免误删。

pg_rm_data: true                  # remove postgres data during remove? true by default
pg_rm_backup: true                # remove pgbackrest backup during primary remove? true by default
pg_rm_pkg: true                   # uninstall postgres packages during remove? true by default
pg_safeguard: false               # stop pg_remove running if pg_safeguard is enabled, false by default

pg_rm_data

参数名称: pg_rm_data, 类型: bool, 层次:G/C/A

删除 PGSQL 实例时是否清理 pg_data 以及软链,默认值 true

该开关既影响 pgsql-rm.yml,也影响其他触发 pg_remove 的场景。设为 false 可以保留数据目录,便于手动检查或重新挂载。

pg_rm_backup

参数名称: pg_rm_backup, 类型: bool, 层次:G/C/A

删除主库时是否一并清理 pgBackRest 仓库与配置,默认值 true

该参数仅对 pg_role=primary 的主实例生效:pg_remove 会先停止 pgBackRest、删除当前集群的 stanza,并在 pgbackrest_method == 'local' 时移除 pg_fs_backup 中的数据。备用集群或上游备份不会受到影响。

pg_rm_pkg

参数名称: pg_rm_pkg, 类型: bool, 层次:G/C/A

在清理 PGSQL 实例时是否卸载 pg_packages 安装的所有软件包,默认值 true

如果只想暂时停机并保留二进制文件,可将其设为 false,否则 pg_remove 会调用系统包管理器彻底卸载 PostgreSQL 相关组件。

pg_safeguard

参数名称: pg_safeguard, 类型: bool, 层次:G/C/A

防误删保险,默认值为 false。当显式设置为 true 时,pg_remove 会立即终止并提示,必须使用 -e pg_safeguard=false 或在变量中关闭后才会继续。

建议在生产环境批量清理前先开启此开关,确认命令与目标节点无误后再解除,以避免误操作导致实例被删除。

15 - 预置剧本

如何使用 ansible 剧本来管理 PostgreSQL 集群

Pigsty提供了一系列剧本,用于集群上下线扩缩容,用户/数据库管理,监控、备份恢复或迁移已有实例。

剧本功能
pgsql.yml初始化 PostgreSQL 集群或添加新的从库
pgsql-rm.yml移除 PostgreSQL 集群,或移除某个实例
pgsql-user.yml在现有的 PostgreSQL 集群中添加新的业务用户
pgsql-db.yml在现有的 PostgreSQL 集群中添加新的业务数据库
pgsql-monitor.yml将远程 PostgreSQL 实例纳入监控中
pgsql-migration.yml为现有的 PostgreSQL 集群生成迁移手册和脚本
pgsql-pitr.yml执行 PostgreSQL 时间点恢复 (PITR)

保护机制

使用 PGSQL 剧本时需要特别注意,剧本 pgsql.ymlpgsql-rm.yml 使用不当会有误删数据库的风险!

  • 在执行时添加 -l 参数,限制命令执行的对象范围,并确保自己在正确的目标上执行正确的任务。
  • 限制范围通常以一个数据库集群为宜,使用不带参数的 pgsql.yml 在生产环境中是一个高危操作,务必三思而后行。

出于防止误删的目的,Pigsty 的 PGSQL 模块提供了防误删保险,由 pg_safeguard 参数控制。 当 pg_safeguard 设置为 true 时,pgsql-rm.yml 剧本会立即中止执行,防止误删数据库集群。

# 将会中止执行,保护数据安全
./pgsql-rm.yml -l pg-test

# 通过命令行参数强制覆盖保护开关
./pgsql-rm.yml -l pg-test -e pg_safeguard=false

除了 pg_safeguard 外,pgsql-rm.yml 还提供了更细粒度的控制参数:

参数默认值说明
pg_safeguardfalse防误删保险,设为 true 时剧本会中止执行
pg_rm_datatrue是否移除 PostgreSQL 数据目录
pg_rm_backuptrue是否移除 pgBackRest 备份数据(仅主库移除时生效)
pg_rm_pkgfalse是否卸载 PostgreSQL 软件包

这些参数允许你根据实际需求精确控制移除行为:

# 移除集群但保留数据目录(仅停止服务)
./pgsql-rm.yml -l pg-test -e pg_rm_data=false

# 移除集群但保留备份数据
./pgsql-rm.yml -l pg-test -e pg_rm_backup=false

# 移除集群并卸载软件包
./pgsql-rm.yml -l pg-test -e pg_rm_pkg=true

pgsql.yml

剧本 pgsql.yml 用于初始化 PostgreSQL 集群或添加新的从库。

下面是使用此剧本初始化沙箱环境中 PostgreSQL 集群的过程:

asciicast

基本用法

./pgsql.yml -l pg-meta            # 初始化集群 pg-meta
./pgsql.yml -l 10.10.10.13        # 初始化/添加实例 10.10.10.13
./pgsql.yml -l pg-test -t pg_service  # 刷新集群 pg-test 的服务
./pgsql.yml -l pg-test -t pg_hba,pgbouncer_hba,pgbouncer_reload -e pg_reload=true  # 重载HBA规则

包装脚本

Pigsty 提供了便捷的包装脚本简化常见操作:

bin/pgsql-add pg-meta             # 初始化 pgsql 集群 pg-meta
bin/pgsql-add 10.10.10.10         # 初始化 pgsql 实例 10.10.10.10
bin/pgsql-add pg-test 10.10.10.13 # 添加 10.10.10.13 到集群 pg-test(自动刷新服务)
bin/pgsql-svc pg-test             # 刷新 pg-test 的 haproxy 服务(成员变更时使用)
bin/pgsql-hba pg-test             # 重载 pg-test 的 pg/pgb HBA 规则

任务列表

本剧本包含以下子任务:

# pg_install              : 安装 postgres 软件包与扩展
#   - pg_dbsu             : 设置 postgres 超级用户
#     - pg_dbsu_create    : 创建 dbsu 用户
#     - pg_dbsu_sudo      : 配置 dbsu sudo 权限
#     - pg_ssh            : 交换 dbsu SSH 密钥
#   - pg_pkg              : 安装 postgres 软件包
#     - pg_pre            : 安装前置任务
#     - pg_ext            : 安装 postgres 扩展包
#     - pg_post           : 安装后置任务
#   - pg_link             : 将 pgsql 版本 bin 链接到 /usr/pgsql
#   - pg_path             : 将 pgsql bin 添加到系统路径
#   - pg_dir              : 创建 postgres 目录并设置 FHS
#   - pg_bin              : 同步 /pg/bin 脚本
#   - pg_alias            : 配置 pgsql/psql 别名
#   - pg_dummy            : 创建 dummy 占位文件
#
# pg_bootstrap            : 引导 postgres 集群
#   - pg_config           : 生成 postgres 配置
#     - pg_conf           : 生成 patroni 配置
#     - pg_key            : 生成 pgsodium 密钥
#   - pg_cert             : 为 postgres 签发证书
#     - pg_cert_private   : 检查 pg 私钥是否存在
#     - pg_cert_issue     : 签发 pg 服务端证书
#     - pg_cert_copy      : 复制密钥与证书到 pg 节点
#   - pg_launch           : 启动 patroni 主库与从库
#     - pg_watchdog       : 授予 postgres watchdog 权限
#     - pg_primary        : 启动 patroni/postgres 主库
#     - pg_init           : 使用角色/模板初始化 pg 集群
#     - pg_pass           : 将 .pgpass 文件写入 pg 主目录
#     - pg_replica        : 启动 patroni/postgres 从库
#     - pg_hba            : 生成 pg HBA 规则
#     - patroni_reload    : 重新加载 patroni 配置
#     - pg_patroni        : 必要时暂停或移除 patroni
#
# pg_provision            : 创建 postgres 业务用户与数据库
#   - pg_user             : 创建 postgres 业务用户
#     - pg_user_config    : 渲染创建用户的 sql
#     - pg_user_create    : 在 postgres 上创建用户
#   - pg_db               : 创建 postgres 业务数据库
#     - pg_db_drop        : 删除数据库(state=absent/recreate时)
#     - pg_db_config      : 渲染创建数据库的 sql
#     - pg_db_create      : 在 postgres 上创建数据库
#
# pg_backup               : 初始化 postgres PITR 备份
#   - pgbackrest          : 配置 pgbackrest 备份
#     - pgbackrest_config : 生成 pgbackrest 配置
#     - pgbackrest_init   : 初始化 pgbackrest 仓库
#     - pgbackrest_backup : 引导后进行初始备份
#
# pg_crontab              : 配置 postgres dbsu 定时任务
#
# pg_access               : 初始化 postgres 服务访问层
#   - pgbouncer           : 部署 pgbouncer 连接池
#     - pgbouncer_dir     : 创建 pgbouncer 目录
#     - pgbouncer_config  : 生成 pgbouncer 配置
#       - pgbouncer_hba   : 生成 pgbouncer hba 配置
#       - pgbouncer_user  : 生成 pgbouncer 用户列表
#     - pgbouncer_launch  : 启动 pgbouncer 服务
#     - pgbouncer_reload  : 重载 pgbouncer 配置
#   - pg_vip              : 使用 vip-manager 绑定 VIP 到主库
#     - pg_vip_config     : 生成 vip-manager 配置
#     - pg_vip_launch     : 启动 vip-manager 绑定 vip
#   - pg_dns              : 将 DNS 名称注册到基础设施 dnsmasq
#     - pg_dns_ins        : 注册 pg 实例名称
#     - pg_dns_cls        : 注册 pg 集群名称
#   - pg_service          : 使用 haproxy 暴露 pgsql 服务
#     - pg_service_config : 为 pg 服务生成本地 haproxy 配置
#     - pg_service_reload : 使用 haproxy 暴露 postgres 服务
#
# pg_monitor              : 设置 pgsql 监控并注册到基础设施
#   - pg_exporter         : 配置并启动 pg_exporter
#   - pgbouncer_exporter  : 配置并启动 pgbouncer_exporter
#   - pgbackrest_exporter : 配置并启动 pgbackrest_exporter
#   - pg_register         : 将 pgsql 注册到监控/日志/数据源
#     - add_metrics       : 将 pg 注册为 victoria 监控目标
#     - add_logs          : 将 pg 注册为 vector 日志来源
#     - add_ds            : 将 pg 数据库注册为 grafana 数据源

以下管理任务使用到了此剧本

注意事项

  • 单独针对某一集群从库执行此剧本时,用户应当确保 集群主库已经完成初始化!
  • 扩容完成后,您需要 重载服务重载HBA,包装脚本 bin/pgsql-add 会自动完成这些任务。

集群扩容时,如果 Patroni 拉起从库的时间过长,Ansible 剧本可能会因为超时而中止:

  • 典型错误信息为:wait for postgres/patroni replica 任务执行很长时间后中止
  • 但制作从库的进程会继续,例如制作从库需超过1天的场景,后续处理请参考 FAQ:制作从库失败。

pgsql-rm.yml

剧本 pgsql-rm.yml 用于移除 PostgreSQL 集群,或移除某个实例。

下面是使用此剧本移除沙箱环境中 PostgreSQL 集群的过程:

asciicast

基本用法

./pgsql-rm.yml -l pg-test          # 移除集群 pg-test
./pgsql-rm.yml -l 10.10.10.13      # 移除实例 10.10.10.13

命令行参数

本剧本可以使用以下命令行参数控制其行为:

./pgsql-rm.yml -l pg-test          # 移除集群 pg-test
    -e pg_safeguard=false          # 防误删保险,默认关闭,开启时需强制覆盖
    -e pg_rm_data=true             # 是否一并移除 PostgreSQL 数据目录,默认移除
    -e pg_rm_backup=true           # 是否一并移除 pgBackRest 备份(仅主库),默认移除
    -e pg_rm_pkg=false             # 是否卸载 PostgreSQL 软件包,默认不卸载

包装脚本

bin/pgsql-rm pg-meta               # 移除 pgsql 集群 pg-meta
bin/pgsql-rm pg-test 10.10.10.13   # 从集群 pg-test 移除实例 10.10.10.13

任务列表

本剧本包含以下子任务:

# pg_safeguard           : 如果 pg_safeguard 启用则中止执行
#
# pg_monitor             : 从监控系统移除注册
#   - pg_deregister      : 从基础设施移除 pg 监控目标
#     - rm_metrics       : 从 prometheus 移除监控目标
#     - rm_ds            : 从 grafana 移除数据源
#     - rm_logs          : 从 vector 移除日志目标
#   - pg_exporter        : 移除 pg_exporter
#   - pgbouncer_exporter : 移除 pgbouncer_exporter
#   - pgbackrest_exporter: 移除 pgbackrest_exporter
#
# pg_access              : 移除 pg 服务访问层
#   - dns                : 移除 pg DNS 记录
#   - vip                : 移除 vip-manager
#   - pg_service         : 从 haproxy 移除 pg 服务
#   - pgbouncer          : 移除 pgbouncer 连接中间件
#
# pg_crontab             : 移除 postgres dbsu 定时任务
#
# postgres               : 移除 postgres 实例
#   - pg_replica         : 移除所有从库
#   - pg_primary         : 移除主库
#   - pg_meta            : 从 etcd 移除元数据
#
# pg_backup              : 移除备份仓库(使用 pg_rm_backup=false 禁用)
# pg_data                : 移除 postgres 数据(使用 pg_rm_data=false 禁用)
# pg_pkg                 : 卸载 pg 软件包(使用 pg_rm_pkg=true 启用)
#   - pg_ext             : 单独卸载 postgres 扩展

以下管理任务使用到了此剧本

注意事项

  • 请不要直接对还有从库的集群主库单独执行此剧本,否则抹除主库后,其余从库会自动触发高可用自动故障切换。总是先下线所有从库后,再下线主库,当一次性下线整个集群时不需要操心此问题。
  • 实例下线后请刷新集群服务,当您从集群中下线掉某一个从库实例时,它仍然存留于在负载均衡器的配置文件中。因为健康检查无法通过,所以下线后的实例不会对集群产生影响。但您应当在恰当的时间点 重载服务,确保生产环境与配置清单的一致性。

pgsql-user.yml

剧本 pgsql-user.yml 用于在现有的 PostgreSQL 集群中添加新的业务用户。

基本用法

./pgsql-user.yml -l pg-meta -e username=dbuser_meta

包装脚本

bin/pgsql-user pg-meta dbuser_meta  # 在集群 pg-meta 上创建用户 dbuser_meta

工作流程

  1. 在配置清单中定义用户: all.children.<pg_cluster>.vars.pg_users[i]
  2. 执行剧本时指定集群和用户名: pgsql-user.yml -l <pg_cluster> -e username=<name>

剧本会:

  1. /pg/tmp/pg-user-{{ user.name }}.sql 生成用户创建 SQL
  2. 在集群主库上执行用户创建/更新 SQL
  3. 更新 /etc/pgbouncer/userlist.txtuseropts.txt
  4. 重载 pgbouncer 使配置生效

用户定义示例

pg_users:
  - name: dbuser_meta               # 必填,用户名是唯一必须的字段
    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                # 可选,是否绕过 RLS,默认 false
    pgbouncer: true                 # 可选,是否添加到 pgbouncer 用户列表,默认 false
    connlimit: -1                   # 可选,连接数限制,-1 表示无限制
    expire_in: 3650                 # 可选,N 天后过期(覆盖 expire_at)
    expire_at: '2030-12-31'         # 可选,指定过期日期
    comment: pigsty admin user      # 可选,用户注释
    roles: [dbrole_admin]           # 可选,所属角色
    parameters: {}                  # 可选,角色级参数
    pool_mode: transaction          # 可选,pgbouncer 用户级连接池模式
    pool_connlimit: -1              # 可选,用户级最大连接数

详情请参考:管理SOP:创建用户


pgsql-db.yml

剧本 pgsql-db.yml 用于在现有的 PostgreSQL 集群中添加新的业务数据库。

基本用法

./pgsql-db.yml -l pg-meta -e dbname=meta

包装脚本

bin/pgsql-db pg-meta meta  # 在集群 pg-meta 上创建数据库 meta

工作流程

  1. 在配置清单中定义数据库: all.children.<pg_cluster>.vars.pg_databases[i]
  2. 执行剧本时指定集群和数据库名: pgsql-db.yml -l <pg_cluster> -e dbname=<name>

剧本会:

  1. /pg/tmp/pg-db-{{ database.name }}.sql 生成数据库创建 SQL
  2. 在集群主库上执行数据库创建/更新 SQL
  3. 如果 db.register_datasource 为 true,将数据库注册为 grafana 数据源
  4. 更新 /etc/pgbouncer/database.txt 并重载 pgbouncer

数据库定义示例

pg_databases:
  - name: meta                      # 必填,数据库名是唯一必须的字段
    baseline: cmdb.sql              # 可选,数据库初始化 SQL 文件路径
    pgbouncer: true                 # 可选,是否添加到 pgbouncer,默认 true
    schemas: [pigsty]               # 可选,额外创建的 schema
    extensions:                     # 可选,要安装的扩展
      - { name: postgis, schema: public }
      - { name: timescaledb }
    comment: pigsty meta database   # 可选,数据库注释
    owner: postgres                 # 可选,数据库所有者
    template: template1             # 可选,模板数据库
    encoding: UTF8                  # 可选,字符编码
    locale: C                       # 可选,区域设置
    tablespace: pg_default          # 可选,默认表空间
    allowconn: true                 # 可选,是否允许连接
    revokeconn: false               # 可选,是否回收 public 连接权限
    register_datasource: true       # 可选,是否注册到 grafana 数据源
    connlimit: -1                   # 可选,连接数限制
    pool_mode: transaction          # 可选,pgbouncer 连接池模式
    pool_size: 64                   # 可选,pgbouncer 连接池大小
    pool_size_reserve: 32           # 可选,pgbouncer 保留连接池大小

详情请参考:管理SOP:创建数据库


pgsql-monitor.yml

剧本 pgsql-monitor.yml 用于将远程 PostgreSQL 实例纳入 Pigsty 监控体系。

基本用法

./pgsql-monitor.yml -e clsname=pg-foo  # 监控远程集群 pg-foo

包装脚本

bin/pgmon-add pg-foo              # 监控一个远程 pgsql 集群 pg-foo
bin/pgmon-add pg-foo pg-bar       # 同时监控多个集群

配置方式

首先需要在 infra 组变量中定义 pg_exporters

infra:
  hosts:
    10.10.10.10:
      pg_exporters:  # 列出所有远程实例,分配唯一的未使用本地端口
        20001: { pg_cluster: pg-foo, pg_seq: 1, pg_host: 10.10.10.10 }
        20002: { pg_cluster: pg-foo, pg_seq: 2, pg_host: 10.10.10.11 }

架构示意

     ------ infra ------
     |                 |
     |   prometheus    |            v---- pg-foo-1 ----v
     |       ^         |  metrics   |         ^        |
     |   pg_exporter <-|------------|----  postgres    |
     |   (port: 20001) |            | 10.10.10.10:5432 |
     |       ^         |            ^------------------^
     |       ^         |                      ^
     |       ^         |            v---- pg-foo-2 ----v
     |       ^         |  metrics   |         ^        |
     |   pg_exporter <-|------------|----  postgres    |
     |   (port: 20002) |            | 10.10.10.11:5433 |
     -------------------            ^------------------^

可配置参数

pg_exporter_config: pg_exporter.yml    # pg_exporter 配置文件名
pg_exporter_cache_ttls: '1,10,60,300'  # pg_exporter 采集器 TTL 阶段
pg_exporter_port: 9630                 # pg_exporter 监听端口
pg_exporter_params: 'sslmode=disable'  # DSN 额外 URL 参数
pg_exporter_url: ''                    # 直接覆盖自动生成的 DSN
pg_exporter_auto_discovery: true       # 是否启用自动数据库发现
pg_exporter_exclude_database: 'template0,template1,postgres'  # 排除的数据库
pg_exporter_include_database: ''       # 仅包含的数据库
pg_exporter_connect_timeout: 200       # 连接超时(毫秒)
pg_monitor_username: dbuser_monitor    # 监控用户名
pg_monitor_password: DBUser.Monitor    # 监控密码

远程数据库配置

远程 PostgreSQL 实例需要创建监控用户:

CREATE USER dbuser_monitor;
COMMENT ON ROLE dbuser_monitor IS 'system monitor user';
ALTER USER dbuser_monitor PASSWORD 'DBUser.Monitor';
GRANT pg_monitor TO dbuser_monitor;
CREATE EXTENSION IF NOT EXISTS "pg_stat_statements" WITH SCHEMA "monitor";

限制

  • 仅 postgres 指标可用
  • node、pgbouncer、patroni、haproxy 指标不可用

详情请参考:管理SOP:监控现有PG


pgsql-migration.yml

剧本 pgsql-migration.yml 用于为现有的 PostgreSQL 集群生成基于逻辑复制的零停机迁移手册和脚本。

基本用法

./pgsql-migration.yml -e@files/migration/pg-meta.yml

工作流程

  1. 定义迁移任务配置文件(如 files/migration/pg-meta.yml
  2. 执行剧本生成迁移手册与脚本
  3. 按照手册逐步执行脚本完成迁移

迁移任务定义示例

# files/migration/pg-meta.yml
context_dir: ~/migration           # 迁移手册与脚本输出目录
src_cls: pg-meta                   # 源集群名称(必填)
src_db: meta                       # 源数据库名称(必填)
src_ip: 10.10.10.10                # 源集群主库 IP(必填)
dst_cls: pg-test                   # 目标集群名称(必填)
dst_db: test                       # 目标数据库名称(必填)
dst_ip: 10.10.10.11                # 目标集群主库 IP(必填)

# 可选参数
pg_dbsu: postgres
pg_replication_username: replicator
pg_replication_password: DBUser.Replicator
pg_admin_username: dbuser_dba
pg_admin_password: DBUser.DBA
pg_monitor_username: dbuser_monitor
pg_monitor_password: DBUser.Monitor

详情请参考:管理SOP:迁移数据库集群


pgsql-pitr.yml

剧本 pgsql-pitr.yml 用于执行 PostgreSQL 时间点恢复 (Point-In-Time Recovery)。

基本用法

# 恢复到最新状态(WAL 归档流末端)
./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": {}}'

# 恢复到指定时间点
./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": {"time": "2025-07-13 10:00:00+00"}}'

# 恢复到指定 LSN
./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": {"lsn": "0/4001C80"}}'

# 恢复到指定事务 ID
./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": {"xid": "250000"}}'

# 恢复到命名还原点
./pgsql-pitr.yml -l pg-meta -e '{"pg_pitr": {"name": "some_restore_point"}}'

# 从其他集群备份恢复
./pgsql-pitr.yml -l pg-test -e '{"pg_pitr": {"cluster": "pg-meta"}}'

PITR 任务参数

pg_pitr:                           # 定义 PITR 任务
  cluster: "pg-meta"               # 源集群名称(恢复其他集群的备份时使用)
  type: latest                     # 恢复目标类型: time, xid, name, lsn, immediate, latest
  time: "2025-01-01 10:00:00+00"   # 恢复目标:时间点
  name: "some_restore_point"       # 恢复目标:命名还原点
  xid: "100000"                    # 恢复目标:事务 ID
  lsn: "0/3000000"                 # 恢复目标:日志序列号
  set: latest                      # 从哪个备份集恢复,默认 latest
  timeline: latest                 # 目标时间线,可以是整数,默认 latest
  exclusive: false                 # 是否排除目标点,默认 false
  action: pause                    # 恢复后动作: pause, promote, shutdown
  archive: false                   # 是否保留归档设置,默认 false
  backup: false                    # 恢复前是否备份现有数据到 /pg/data-backup?默认 false
  db_include: []                   # 仅包含这些数据库
  db_exclude: []                   # 排除这些数据库
  link_map: {}                     # 表空间链接映射
  process: 4                       # 并行恢复进程数
  repo: {}                         # 恢复源仓库配置
  data: /pg/data                   # 恢复数据目录
  port: 5432                       # 恢复实例监听端口

任务列表

本剧本包含以下子任务:

# down                 : 停止 HA 并关闭 patroni 和 postgres
#   - pause            : 暂停 patroni 自动故障转移
#   - stop             : 停止 patroni 和 postgres 服务
#     - stop_patroni   : 停止 patroni 服务
#     - stop_postgres  : 停止 postgres 服务
#
# pitr                 : 执行 PITR 恢复过程
#   - config           : 生成 pgbackrest 配置和恢复脚本
#   - backup           : 执行可选的原始数据备份
#   - restore          : 运行 pgbackrest restore 命令
#   - recovery         : 启动 postgres 并完成恢复
#   - verify           : 验证恢复的集群控制数据
#
# up                   : 启动 postgres/patroni 并恢复 HA
#   - etcd             : 启动前清理 etcd 元数据
#   - start            : 启动 patroni 和 postgres 服务
#     - start_postgres : 启动 postgres 服务
#     - start_patroni  : 启动 patroni 服务
#   - resume           : 恢复 patroni 自动故障转移

恢复目标类型说明

类型说明示例
latest恢复到 WAL 归档流末端(最新状态){"pg_pitr": {}}
time恢复到指定时间点{"pg_pitr": {"time": "2025-07-13 10:00:00"}}
xid恢复到指定事务 ID{"pg_pitr": {"xid": "250000"}}
name恢复到命名还原点{"pg_pitr": {"name": "before_ddl"}}
lsn恢复到指定 LSN{"pg_pitr": {"lsn": "0/4001C80"}}
immediate恢复到一致性状态后立即停止{"pg_pitr": {"type": "immediate"}}

详情请参考:备份恢复教程

16 - 扩展插件

利用 PostgreSQL 扩展的协同超能力

Pigsty 提供 444 扩展,覆盖时序、地理、向量、全文检索、分析、特性增强等 16 大类别,开箱即用。

在 Pigsty 中使用扩展涉及四个核心步骤:下载安装配置/加载启用

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_databases:
      - name: meta
        extensions: [ postgis, timescaledb, vector ]   # 启用:在数据库中创建扩展
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain' # 配置:预加载扩展库
    pg_extensions: [ postgis, timescaledb, pgvector ]  # 安装:安装扩展软件包

16.1 - 快速开始

使用扩展的四步流程速览

在 Pigsty 中使用扩展需要四个步骤:下载安装配置启用

  1. 下载:将扩展软件包下载到本地仓库(Pigsty 默认已下载主流扩展)
  2. 安装:在集群节点上安装扩展软件包
  3. 配置:部分扩展需要预加载或配置参数
  4. 启用:在数据库中执行 CREATE EXTENSION 创建扩展

声明式配置

在 Pigsty 配置清单中声明扩展,集群初始化时自动完成安装与启用:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_databases:
      - name: meta
        extensions: [ postgis, timescaledb, vector ]   # 在数据库中启用扩展
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain' # 预加载扩展库
    pg_extensions: [ postgis, timescaledb, pgvector ]  # 安装扩展软件包

执行 ./pgsql.yml 初始化集群后,postgistimescaledbvector 三个扩展即在 meta 数据库中可用。


命令式操作

对于已有集群,可以使用命令行方式添加扩展:

# 1. 安装扩展软件包
./pgsql.yml -l pg-meta -t pg_extension -e '{"pg_extensions":["pgvector"]}'

# 2. 预加载扩展(如需要,修改后需重启)
pg edit-config pg-meta --force -p shared_preload_libraries='timescaledb, pg_stat_statements, auto_explain'

# 3. 在数据库中启用扩展
psql -d meta -c 'CREATE EXTENSION vector;'

也可以使用 pig 包管理器直接安装:

pig install pgvector        # 安装扩展包
pig extension create vector  # 在数据库中启用

流程速查

步骤参数/命令说明
下载repo_extra_packages指定下载到本地仓库的扩展包
安装pg_extensions指定集群要安装的扩展包
配置pg_libs预加载扩展到 shared_preload_libraries
启用pg_databases.extensions在数据库中自动执行 CREATE EXTENSION

详细说明请参阅各子章节:下载安装配置启用

16.2 - 扩展简介

PostgreSQL 扩展的核心概念与 Pigsty 扩展生态

扩展是 PostgreSQL 的灵魂所在。Pigsty 收录了 444 个预编译、开箱即用的扩展插件,充分释放 PostgreSQL 的潜能。


扩展是什么

PostgreSQL 扩展(Extension)是一种模块化机制,允许在不修改核心代码的情况下增强数据库功能。 一个扩展通常包含三部分:

  • 控制文件.control):必需,包含扩展元数据
  • SQL 脚本.sql):可选,定义函数、类型、操作符等数据库对象
  • 动态库.so):可选,提供 C 语言实现的高性能功能

扩展可以为 PostgreSQL 添加:新数据类型、索引方法、函数与操作符、外部数据访问、过程语言、性能监控、安全审计等能力。


核心扩展

Pigsty 收录的扩展中,以下是最具代表性的:

扩展说明
PostGIS地理空间数据类型与索引,GIS 事实标准
TimescaleDB时序数据库,支持持续聚合、列存储、自动压缩
PGVector向量数据类型与 HNSW/IVFFlat 索引,AI 应用必备
Citus分布式数据库,水平分片扩展能力
pg_duckdb嵌入 DuckDB 分析引擎,OLAP 加速
ParadeDBElasticSearch 级别的全文搜索能力
Apache AGE图数据库,支持 OpenCypher 查询语言
pg_graphql原生 GraphQL 查询支持

绝大多数扩展可以并存甚至组合使用,产生 1+1 远大于 2 的协同效应。


扩展类别

Pigsty 将扩展划分为 16 个类别:

类别别名说明典型扩展
时序time时序数据处理timescaledb, pg_cron, periods
地理gis地理空间数据postgis, h3, pgrouting
向量rag向量检索与 AIpgvector, vchord, pg_vectorize
搜索fts全文检索pgroonga, zhparser, pg_bigm
分析olapOLAP 与分析pg_duckdb, pg_mooncake, citus
特性feat功能增强age, pg_graphql, hll, rum
语言lang过程语言plpython3u, pljava, plv8
类型type数据类型hstore, ltree, ip4r
工具util实用工具http, pg_net, pgjwt
函数func函数库pg_uuidv7, topn, tdigest
管理admin运维管理pg_repack, pg_squeeze, pgagent
统计stat监控统计pg_stat_statements, pg_qualstats, auto_explain
安全sec安全审计pgaudit, pgsodium, pg_tde
外联fdw外部数据访问postgres_fdw, mysql_fdw, oracle_fdw
兼容sim数据库兼容orafce, babelfish
同步etl数据同步pglogical, wal2json, decoderbufs

使用类别别名可以批量安装整个类别的扩展,例如 pg_extensions: [ pgsql-gis, pgsql-rag ]


预定义扩展集

Pigsty 提供了若干预定义的扩展集(Stack),方便按场景选用:

扩展集包含扩展
gis-stackpostgis, pgrouting, pointcloud, h3, q3c, ogr_fdw
rag-stackpgvector, vchord, pgvectorscale, pg_similarity, pg_tiktoken
fts-stackpgroonga, pg_bigm, zhparser, hunspell
olap-stackpg_duckdb, pg_mooncake, timescaledb, pg_partman, plproxy
feat-stackage, hll, rum, pg_graphql, pg_jsonschema, jsquery
stat-stackpg_show_plans, pg_stat_kcache, pg_qualstats, pg_wait_sampling
supa-stackpg_graphql, pg_jsonschema, wrappers, pgvector, pgsodium, vault

pg_extensions 中直接使用这些名称即可安装整套扩展。


扩展资源

16.3 - 软件包

扩展包别名与类别命名规则

Pigsty 使用包别名机制简化扩展的安装与管理。


包别名机制

管理扩展涉及多个层面的名称映射:

层面示例 pgvector示例 postgis
扩展名vectorpostgis, postgis_topology, …
包别名pgvectorpostgis
RPM 包名pgvector_18postgis36_18*
DEB 包名postgresql-18-pgvectorpostgresql-18-postgis-3*

Pigsty 提供包别名抽象层,让用户无需关心具体的 RPM/DEB 包名:

pg_extensions: [ pgvector, postgis, timescaledb ]  # 使用包别名

Pigsty 会根据操作系统和 PostgreSQL 版本自动翻译为正确的包名。

注意:CREATE EXTENSION 时使用的是扩展名(如 vector),而非包别名(pgvector)。


类别别名

所有扩展被划分为 16 个类别,可使用类别别名批量安装:

# 使用通用类别别名(自动适配当前 PG 版本)
pg_extensions: [ pgsql-gis, pgsql-rag, pgsql-fts ]

# 或使用版本特定的类别别名
pg_extensions: [ pg18-gis, pg18-rag, pg18-fts ]

olap 类别外,所有类别的扩展都可以同时安装。olap 类别中存在互斥:pg_duckdbpg_mooncake 冲突。


类别列表

类别说明典型扩展
time时序类timescaledb, pg_cron, periods
gis地理类postgis, h3, pgrouting
rag向量类pgvector, pgml, vchord
fts搜索类pg_trgm, zhparser, pgroonga
olap分析类citus, pg_duckdb, pg_analytics
feat特性类age, pg_graphql, rum
lang语言类plpython3u, pljava, plv8
type类型类hstore, ltree, citext
util工具类http, pg_net, pgjwt
func函数类pgcrypto, uuid-ossp, pg_uuidv7
admin管理类pg_repack, pgagent, pg_squeeze
stat统计类pg_stat_statements, pg_qualstats, auto_explain
sec安全类pgaudit, pgcrypto, pgsodium
fdw外部类postgres_fdw, mysql_fdw, oracle_fdw
sim兼容类orafce, babelfishpg_tds
etl数据类pglogical, wal2json, decoderbufs

查阅扩展目录

您可以在 Pigsty 扩展目录 网站上查阅所有可用扩展的详细信息,包括:

  • 扩展名称、描述、版本
  • 支持的 PostgreSQL 版本
  • 支持的操作系统发行版
  • 安装方式、预加载需求
  • 许可证、来源仓库

16.4 - 下载扩展

从软件仓库下载扩展包到本地

在安装扩展前,需要确保扩展软件包已下载到本地仓库或可从上游获取。


默认行为

Pigsty 在安装过程中会自动下载默认 PostgreSQL 版本可用的主流扩展到本地软件仓库。

使用本地仓库的优势:

  • 加速安装,避免重复下载
  • 减少网络流量消耗
  • 提高交付可靠性
  • 确保版本一致性

下载新扩展

要下载额外的扩展,将其添加到 repo_extra_packages 并重建仓库:

all:
  vars:
    repo_extra_packages: [ pgvector, postgis, timescaledb, pg_duckdb ]
# 重新下载软件包到本地仓库
./infra.yml -t repo_build

# 刷新所有节点的软件源缓存
./node.yml -t node_repo

使用上游仓库

也可以直接从互联网上游仓库安装,无需预先下载:

# 在节点上添加上游软件源
./node.yml -t node_repo -e node_repo_modules=node,pgsql

这种方式适合:

  • 快速测试最新版本
  • 安装冷门扩展
  • 网络条件良好的环境

但可能面临:

  • 网络不稳定影响安装
  • 版本不一致风险

扩展来源

扩展软件包来自两个主要源:

仓库说明
PGDGPostgreSQL 官方仓库,提供核心扩展
PigstyPigsty 补充仓库,提供额外扩展

Pigsty 仓库只收录 PGDG 仓库中不存在的扩展。一旦某扩展进入 PGDG 仓库,Pigsty 仓库会移除或与其保持一致。

仓库地址:

详细的仓库配置请参阅 扩展仓库

16.5 - 安装扩展

在集群节点上安装扩展软件包

Pigsty 使用操作系统的包管理器(yum/apt)安装扩展软件包。


相关参数

两个参数用于指定要安装的扩展:

参数用途默认行为
pg_packages全局通用软件包确保存在(不升级)
pg_extensions集群特定扩展安装最新版本

pg_packages 通常用于指定所有集群都需要的基础组件(PostgreSQL 内核、Patroni、pgBouncer 等)和必选扩展。

pg_extensions 用于指定特定集群需要的扩展。

pg_packages:                           # 全局基础包
  - pgsql-main pgsql-common
pg_extensions:                         # 集群扩展
  - postgis timescaledb pgvector

集群初始化时安装

在集群配置中声明扩展,初始化时自动安装:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_extensions: [ postgis, timescaledb, pgvector, pg_duckdb ]

执行 ./pgsql.yml 初始化集群时,扩展会自动安装。


已有集群安装扩展

对于已初始化的集群,有多种方式安装扩展:

使用 Pigsty 剧本

# 修改配置后使用剧本安装
./pgsql.yml -l pg-meta -t pg_extension

# 或直接在命令行指定扩展
./pgsql.yml -l pg-meta -t pg_extension -e '{"pg_extensions":["pg_duckdb"]}'

使用 pig 包管理器

# 使用 pig 安装扩展
pig install pg_duckdb

# 批量安装
ansible pg-meta -b -a 'pig install pg_duckdb pgvector'

直接使用包管理器

# EL 系统
sudo yum install -y pg_duckdb_18*

# Debian/Ubuntu 系统
sudo apt install -y postgresql-18-pg-duckdb

使用包别名

Pigsty 支持使用标准化的包别名,自动翻译为对应 PG 版本的包名:

pg_extensions:
  - pgvector           # 自动翻译为 pgvector_18* (EL) 或 postgresql-18-pgvector (Debian)
  - postgis            # 自动翻译为 postgis36_18* (EL) 或 postgresql-18-postgis-3* (Debian)
  - pgsql-gis          # 类别别名,安装整个 GIS 类别的扩展

也可以直接使用原始包名:

pg_extensions:
  - pgvector_18*                    # EL 系统的原始包名
  - postgresql-18-pgvector          # Debian 系统的原始包名

包别名定义参见:


验证安装

安装后可在数据库中验证:

-- 查看已安装的扩展
SELECT * FROM pg_available_extensions WHERE name = 'vector';

-- 查看扩展文件是否存在
\dx

16.6 - 配置扩展

预加载扩展库与配置扩展参数

部分扩展需要预加载动态库或配置参数后才能使用,本节介绍如何配置扩展。


预加载扩展

大多数扩展安装后可直接使用 CREATE EXTENSION 启用,但部分使用 PostgreSQL Hook 机制的扩展需要预加载

预加载通过 shared_preload_libraries 参数指定,修改后需重启数据库生效。

需要预加载的扩展

以下是常见的需要预加载的扩展:

扩展说明
timescaledb时序数据库扩展,必须放在最前面
citus分布式数据库扩展,必须放在最前面
pg_stat_statementsSQL 语句统计,Pigsty 默认启用
auto_explain自动记录慢查询执行计划,Pigsty 默认启用
pg_cron定时任务调度
pg_net异步 HTTP 请求
pg_tle可信语言扩展
pgaudit审计日志
pg_stat_kcache内核统计信息
pg_squeeze在线表空间回收
pgmlPostgresML 机器学习

完整列表请参阅 扩展目录(带 LOAD 标记)。

预加载顺序

shared_preload_libraries 中扩展的加载顺序很重要:

  • timescaledbcitus 必须放在最前面
  • 如果同时使用,citus 应在 timescaledb 之前
  • 统计类扩展应在 pg_stat_statements 之后,以使用相同的 query_id
pg_libs: 'citus, timescaledb, pg_stat_statements, auto_explain'

集群初始化时配置

在创建新集群时,使用 pg_libs 参数指定预加载的扩展:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain'
    pg_extensions: [ timescaledb, postgis, pgvector ]

pg_libs 的值将在集群初始化时写入 shared_preload_libraries

默认值

pg_libs 的默认值是 pg_stat_statements, auto_explain,这两个 Contrib 扩展提供基本的可观测性:

  • pg_stat_statements:跟踪所有 SQL 语句的执行统计
  • auto_explain:自动记录慢查询的执行计划

已有集群修改配置

对于已初始化的集群,使用 patronictl 修改 shared_preload_libraries

# 添加 timescaledb 到预加载库
pg edit-config pg-meta --force -p shared_preload_libraries='timescaledb, pg_stat_statements, auto_explain'

# 重启集群使配置生效
pg restart pg-meta

也可以直接修改 postgresql.conf 或使用 ALTER SYSTEM

ALTER SYSTEM SET shared_preload_libraries = 'timescaledb, pg_stat_statements, auto_explain';

修改后需重启 PostgreSQL 服务生效。


扩展参数配置

许多扩展有可配置的参数,可以在以下位置设置:

集群初始化时

使用 pg_parameters 参数指定:

pg-meta:
  vars:
    pg_cluster: pg-meta
    pg_libs: 'pg_cron, pg_stat_statements, auto_explain'
    pg_parameters:
      cron.database_name: postgres           # pg_cron 使用的数据库
      pg_stat_statements.track: all          # 跟踪所有语句
      auto_explain.log_min_duration: 1000    # 记录超过 1 秒的查询

运行时修改

使用 ALTER SYSTEMpatronictl

-- 修改参数
ALTER SYSTEM SET pg_stat_statements.track = 'all';

-- 重新加载配置
SELECT pg_reload_conf();
# 使用 patronictl 修改
pg edit-config pg-meta --force -p 'pg_stat_statements.track=all'

注意事项

  1. 预加载错误会阻止启动:如果 shared_preload_libraries 中的扩展不存在或加载失败,PostgreSQL 将无法启动。确保扩展已正确安装后再添加预加载。

  2. 修改需重启shared_preload_libraries 的修改需要重启 PostgreSQL 服务才能生效。

  3. 部分功能可用:某些扩展在不预加载的情况下可以部分使用,但完整功能需要预加载。

  4. 查看当前配置:使用以下命令查看当前的预加载库:

SHOW shared_preload_libraries;

16.7 - 启用扩展

在数据库中创建和启用扩展

安装扩展软件包后,需要在数据库中执行 CREATE EXTENSION 才能使用扩展功能。


查看可用扩展

安装扩展软件包后,可以查看可用的扩展:

-- 查看所有可用扩展
SELECT * FROM pg_available_extensions;

-- 查看特定扩展
SELECT * FROM pg_available_extensions WHERE name = 'vector';

-- 查看已启用的扩展
SELECT * FROM pg_extension;

创建扩展

使用 CREATE EXTENSION 在数据库中启用扩展:

-- 创建扩展
CREATE EXTENSION vector;

-- 创建扩展到指定 Schema
CREATE EXTENSION postgis SCHEMA public;

-- 自动安装依赖的扩展
CREATE EXTENSION postgis_topology CASCADE;

-- 如果不存在则创建
CREATE EXTENSION IF NOT EXISTS vector;

注意:CREATE EXTENSION 使用的是扩展名(如 vector),而非包别名(pgvector)。


集群初始化时启用

pg_databases 中声明扩展,集群初始化时自动创建:

pg-meta:
  vars:
    pg_cluster: pg-meta
    pg_databases:
      - name: meta
        extensions:
          - { name: vector }                         # 使用默认 Schema
          - { name: postgis, schema: public }        # 指定 Schema
          - { name: pg_stat_statements, schema: monitor }

Pigsty 会在数据库创建后自动执行 CREATE EXTENSION


需要预加载的扩展

部分扩展需要先添加到 shared_preload_libraries 并重启后才能创建:

pg-meta:
  vars:
    pg_cluster: pg-meta
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain'
    pg_databases:
      - name: meta
        extensions:
          - { name: timescaledb }  # 需要预加载

如果未预加载就尝试创建,会收到错误信息。

需要预加载的常见扩展:timescaledb, citus, pg_cron, pg_net, pgaudit 等。详见 配置扩展


扩展依赖

某些扩展依赖于其他扩展,需要按顺序创建:

-- postgis_topology 依赖 postgis
CREATE EXTENSION postgis;
CREATE EXTENSION postgis_topology;

-- 或使用 CASCADE 自动安装依赖
CREATE EXTENSION postgis_topology CASCADE;

不需要创建的扩展

少数扩展不通过 SQL 接口对外服务,无需执行 CREATE EXTENSION

扩展说明
wal2json逻辑解码插件,直接在复制槽中使用
decoderbufs逻辑解码插件
decoder_raw逻辑解码插件

这些扩展安装后即可使用,例如:

-- 使用 wal2json 创建逻辑复制槽
SELECT * FROM pg_create_logical_replication_slot('test_slot', 'wal2json');

查看扩展信息

-- 查看扩展详情
\dx+ vector

-- 查看扩展包含的对象
SELECT * FROM pg_extension_config_dump('vector');

-- 查看扩展版本
SELECT extversion FROM pg_extension WHERE extname = 'vector';

16.8 - 更新扩展

升级 PostgreSQL 扩展版本

扩展更新涉及两个层面:软件包更新(操作系统层面)和扩展对象更新(数据库层面)。


更新软件包

使用包管理器更新扩展的软件包:

# EL 系统
sudo yum update pgvector_18*

# Debian/Ubuntu 系统
sudo apt update && sudo apt upgrade postgresql-18-pgvector

使用 Pigsty 批量更新:

# 更新指定集群的扩展包
./pgsql.yml -l pg-meta -t pg_extension -e '{"pg_extensions":["pgvector"]}'

# 使用 pig 包管理器
pig update pgvector

更新扩展对象

软件包更新后,数据库中的扩展对象可能需要同步更新。

查看可更新的扩展

-- 查看已安装扩展及其版本
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE installed_version IS NOT NULL;

-- 查看可升级的扩展
SELECT name, installed_version, default_version
FROM pg_available_extensions
WHERE installed_version IS NOT NULL
  AND installed_version <> default_version;

执行扩展更新

-- 更新到最新版本
ALTER EXTENSION pgvector UPDATE;

-- 更新到指定版本
ALTER EXTENSION pgvector UPDATE TO '0.8.0';

查看更新路径

-- 查看扩展的可用升级路径
SELECT * FROM pg_extension_update_paths('pgvector');

注意事项

  1. 备份优先:更新扩展前建议先备份数据库,特别是涉及数据类型变更的扩展。

  2. 检查兼容性:某些扩展的大版本升级可能不兼容,需查阅扩展的升级文档。

  3. 预加载扩展:如果更新的是需要预加载的扩展(如 timescaledb),更新后可能需要重启数据库。

  4. 依赖关系:如果其他扩展依赖于被更新的扩展,需要按依赖顺序更新。

  5. 复制环境:在主从复制环境中,应先在从库测试更新,确认无误后再更新主库。


常见问题

更新失败

如果 ALTER EXTENSION UPDATE 失败,可能是因为:

  • 没有可用的升级路径
  • 扩展正在被使用
  • 权限不足
-- 查看扩展依赖
SELECT * FROM pg_depend WHERE refobjid = (SELECT oid FROM pg_extension WHERE extname = 'pgvector');

回滚更新

PostgreSQL 扩展通常不支持直接回滚。如需回滚:

  1. 从备份恢复
  2. 或者:卸载新版本扩展,安装旧版本软件包,重新创建扩展

16.9 - 移除扩展

卸载 PostgreSQL 扩展

移除扩展涉及两个层面:删除扩展对象(数据库层面)和卸载软件包(操作系统层面)。


删除扩展对象

使用 DROP EXTENSION 从数据库中删除扩展:

-- 删除扩展
DROP EXTENSION pgvector;

-- 如果有依赖对象,需要级联删除
DROP EXTENSION pgvector CASCADE;

警告CASCADE 会删除所有依赖于该扩展的对象(表、函数、视图等),请谨慎使用。

查看扩展依赖

删除前建议先检查依赖关系:

-- 查看依赖于某扩展的对象
SELECT
    classid::regclass,
    objid,
    deptype
FROM pg_depend
WHERE refobjid = (SELECT oid FROM pg_extension WHERE extname = 'pgvector');

-- 查看使用了扩展类型的表
SELECT
    c.relname AS table_name,
    a.attname AS column_name,
    t.typname AS type_name
FROM pg_attribute a
JOIN pg_class c ON a.attrelid = c.oid
JOIN pg_type t ON a.atttypid = t.oid
WHERE t.typname = 'vector';

移除预加载

如果扩展在 shared_preload_libraries 中,删除后需要从预加载列表移除:

# 修改 shared_preload_libraries,移除扩展
pg edit-config pg-meta --force -p shared_preload_libraries='pg_stat_statements, auto_explain'

# 重启使配置生效
pg restart pg-meta

卸载软件包

从数据库中删除扩展后,可以选择卸载软件包:

# EL 系统
sudo yum remove pgvector_18*

# Debian/Ubuntu 系统
sudo apt remove postgresql-18-pgvector

# 使用 pig 包管理器
pig remove pgvector

通常保留软件包不会有问题,仅在需要释放磁盘空间或解决冲突时才需要卸载。


注意事项

  1. 数据丢失风险:使用 CASCADE 会删除依赖对象,可能导致数据丢失。

  2. 应用兼容性:删除扩展前确保应用程序不再使用该扩展的功能。

  3. 预加载顺序:如果删除的是预加载扩展,务必同时从 shared_preload_libraries 中移除,否则数据库可能无法启动。

  4. 主从环境:在主从复制环境中,DROP EXTENSION 会自动复制到从库。


操作顺序

完整的扩展移除流程:

# 1. 检查依赖关系
psql -d mydb -c "SELECT * FROM pg_depend WHERE refobjid = (SELECT oid FROM pg_extension WHERE extname = 'pgvector');"

# 2. 删除数据库中的扩展
psql -d mydb -c "DROP EXTENSION pgvector;"

# 3. 如果是预加载扩展,从 shared_preload_libraries 移除
pg edit-config pg-meta --force -p shared_preload_libraries='pg_stat_statements, auto_explain'

# 4. 重启数据库(如果修改了预加载配置)
pg restart pg-meta

# 5. 可选:卸载软件包
sudo yum remove pgvector_18*

16.10 - 默认扩展

Pigsty 默认安装的 PostgreSQL 扩展

Pigsty 在初始化 PostgreSQL 集群时,会默认安装和启用一些核心扩展。


默认安装的扩展

通过 pg_packages 默认安装的扩展:

扩展说明
pg_repack在线处理表膨胀,重要的维护工具
wal2json逻辑解码输出 JSON 格式变更,CDC 场景常用

通过 pg_extensions 可选安装的扩展(默认注释):

扩展说明
postgis地理空间数据库扩展
timescaledb时序数据库扩展
pgvector向量数据类型与索引

默认启用的扩展

通过 pg_default_extensions 在所有数据库中默认启用的扩展:

扩展Schema说明
pg_stat_statementsmonitorSQL 语句执行统计
pgstattuplemonitor元组级统计信息
pg_buffercachemonitor缓冲区缓存检查
pageinspectmonitor页面级检查
pg_prewarmmonitor关系预热
pg_visibilitymonitor可见性映射检查
pg_freespacemapmonitor空闲空间映射检查
postgres_fdwpublicPostgreSQL 外部数据包装器
file_fdwpublic文件外部数据包装器
btree_gistpublicB-tree GiST 操作符类
btree_ginpublicB-tree GIN 操作符类
pg_trgmpublic三元组匹配
intaggpublic整数聚合器
intarraypublic整数数组函数
pg_repack-在线重组表

这些扩展提供基础的监控、运维和功能增强能力。


默认预加载的扩展

通过 pg_libs 默认预加载到 shared_preload_libraries 的扩展:

扩展说明
pg_stat_statements跟踪所有 SQL 语句的执行统计
auto_explain自动记录慢查询的执行计划

这两个扩展提供基本的可观测性,强烈建议保留。


自定义默认扩展

可以通过修改配置参数来自定义默认安装和启用的扩展:

all:
  vars:
    # 修改默认安装的扩展包
    pg_packages:
      - pgsql-main pgsql-common
      - pg_repack_$v* wal2json_$v*

    # 修改默认安装的扩展
    pg_extensions: [ postgis, timescaledb, pgvector ]

    # 修改默认预加载的扩展
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain'

    # 修改默认启用的扩展
    pg_default_extensions:
      - { name: pg_stat_statements, schema: monitor }
      - { name: pg_repack }
      # ... 添加更多

详细的扩展使用方法请参阅:

16.11 - 扩展仓库

Pigsty 扩展软件仓库配置

Pigsty 提供补充扩展仓库,在 PGDG 官方仓库基础上提供额外的扩展包。


YUM 仓库

适用于 EL 7/8/9/10 及其兼容系统(RHEL、Rocky、AlmaLinux、CentOS 等)。

添加仓库

# 添加 GPG 公钥
curl -fsSL https://repo.pigsty.io/key | sudo tee /etc/pki/rpm-gpg/RPM-GPG-KEY-pigsty >/dev/null

# 添加仓库配置
curl -fsSL https://repo.pigsty.io/yum/repo | sudo tee /etc/yum.repos.d/pigsty.repo >/dev/null

# 刷新缓存
sudo yum makecache

中国大陆镜像

curl -fsSL https://repo.pigsty.cc/key | sudo tee /etc/pki/rpm-gpg/RPM-GPG-KEY-pigsty >/dev/null
curl -fsSL https://repo.pigsty.cc/yum/repo | sudo tee /etc/yum.repos.d/pigsty.repo >/dev/null

仓库地址


APT 仓库

适用于 Debian 11/12/13 和 Ubuntu 22.04/24.04 及其兼容系统。

添加仓库

# 添加 GPG 公钥
curl -fsSL https://repo.pigsty.io/key | sudo gpg --dearmor -o /etc/apt/keyrings/pigsty.gpg

# 获取发行版代号并添加仓库
distro_codename=$(lsb_release -cs)
sudo tee /etc/apt/sources.list.d/pigsty.list > /dev/null <<EOF
deb [signed-by=/etc/apt/keyrings/pigsty.gpg] https://repo.pigsty.io/apt/infra generic main
deb [signed-by=/etc/apt/keyrings/pigsty.gpg] https://repo.pigsty.io/apt/pgsql ${distro_codename} main
EOF

# 刷新缓存
sudo apt update

中国大陆镜像

curl -fsSL https://repo.pigsty.cc/key | sudo gpg --dearmor -o /etc/apt/keyrings/pigsty.gpg

distro_codename=$(lsb_release -cs)
sudo tee /etc/apt/sources.list.d/pigsty.list > /dev/null <<EOF
deb [signed-by=/etc/apt/keyrings/pigsty.gpg] https://repo.pigsty.cc/apt/infra generic main
deb [signed-by=/etc/apt/keyrings/pigsty.gpg] https://repo.pigsty.cc/apt/pgsql/${distro_codename} ${distro_codename} main
EOF

仓库地址


GPG 签名

所有软件包均使用 GPG 签名:

  • 指纹: 9592A7BC7A682E7333376E09E7935D8DB9BD8B20
  • 短 ID: B9BD8B20

仓库策略

Pigsty 仓库遵循以下原则:

  1. 补充性:只收录 PGDG 仓库中不存在的扩展
  2. 一致性:扩展进入 PGDG 仓库后,Pigsty 仓库会移除或保持一致
  3. 兼容性:支持 PostgreSQL 13-18 多个大版本
  4. 多平台:支持 x86_64 和 aarch64 架构

相关资源

17 - 场景模板

使用 Pigsty 预置的四种场景化 Patroni 模版,或者基于这些模板自定义您的配置模板

Pigsty 提供四种预置的 Patroni/PostgreSQL 配置模板,针对不同的使用场景进行了参数优化:

模板CPU核心适用场景特点
oltp.yml4-128COLTP 事务处理高并发、低延迟、高吞吐
olap.yml4-128COLAP 分析处理大查询、高并行、长事务
crit.yml4-128C核心/金融业务数据安全、审计合规、零丢失
tiny.yml1-3C微型实例资源受限、低配环境

您可以通过 pg_conf 参数来选择使用哪个配置模板,默认为 oltp.yml

通常,数据库调优模板 pg_conf 应当与机器调优模板 node_tune 配套使用。


使用模板

要使用特定的配置模板,只需在集群定义中设置 pg_conf 参数。 建议同时设置 node_tune 参数,使操作系统级别的调优与数据库调优保持一致:

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
    pg_conf: oltp.yml    # PostgreSQL 配置模板(默认值)
    node_tune: oltp      # 操作系统调优模板(默认值)

对于核心金融业务场景,您可以使用 crit.yml 模板:

pg-finance:
  hosts:
    10.10.10.21: { pg_seq: 1, pg_role: primary }
    10.10.10.22: { pg_seq: 2, pg_role: replica }
    10.10.10.23: { pg_seq: 3, pg_role: replica }
  vars:
    pg_cluster: pg-finance
    pg_conf: crit.yml    # PostgreSQL 关键业务模板
    node_tune: crit      # 操作系统关键业务调优

对于低配虚拟机或开发环境,可以使用 tiny.yml 模板:

pg-dev:
  hosts:
    10.10.10.31: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-dev
    pg_conf: tiny.yml    # PostgreSQL 微型实例模板
    node_tune: tiny      # 操作系统微型实例调优

模板对比

四种模板在关键参数上有显著差异,以适应不同的业务场景。以下是主要差异对比:

连接与内存

参数OLTPOLAPCRITTINY
max_connections500/1000500500/1000250
work_mem 范围64MB-1GB64MB-8GB64MB-1GB16MB-256MB
maintenance_work_mem25% 共享缓冲区50% 共享缓冲区25% 共享缓冲区25% 共享缓冲区
max_locks_per_transaction1-2x maxconn2-4x maxconn1-2x maxconn1-2x maxconn

并行查询

参数OLTPOLAPCRITTINY
max_worker_processescpu+8cpu+12cpu+8cpu+4
max_parallel_workers50% cpu80% cpu50% cpu50% cpu
max_parallel_workers_per_gather20% cpu (max 8)50% cpu0(禁用)0(禁用)
parallel_setup_cost2000100020001000
parallel_tuple_cost0.20.10.20.1

同步复制

参数OLTPOLAPCRITTINY
synchronous_mode取决于 pg_rpo取决于 pg_rpo强制开启取决于 pg_rpo
data_checksums可选可选强制开启可选

Vacuum 配置

参数OLTPOLAPCRITTINY
vacuum_cost_delay20ms10ms20ms20ms
vacuum_cost_limit20001000020002000
autovacuum_max_workers3332

超时与安全

参数OLTPOLAPCRITTINY
idle_in_transaction_session_timeout10min禁用1min10min
log_min_duration_statement100ms1000ms100ms100ms
default_statistics_target4001000400200
track_activity_query_size8KB8KB32KB8KB
log_connections仅授权仅授权全部阶段默认

IO 配置(PG17+)

参数OLTPOLAPCRITTINY
io_workers25% cpu (4-16)50% cpu (4-32)25% cpu (4-8)3
temp_file_limit1/20 磁盘1/5 磁盘1/20 磁盘1/20 磁盘

选择建议

  • OLTP 模板:适用于大多数在线事务处理场景,是默认选择。适合电商、社交、游戏等高并发低延迟应用。

  • OLAP 模板:适用于数据仓库、BI 报表、ETL 等分析型负载。特点是允许大查询、高并行度、宽松的超时设置。

  • CRIT 模板:适用于金融交易、核心账务等对数据一致性和安全性有极高要求的场景。强制同步复制、数据校验和、完整审计日志。

  • TINY 模板:适用于开发测试环境、资源受限的虚拟机、树莓派等场景。最小化资源占用,禁用并行查询。


自定义模板

您可以基于现有模板创建自定义配置模板。模板文件位于 Pigsty 安装目录的 roles/pgsql/templates/ 下:

roles/pgsql/templates/
├── oltp.yml    # OLTP 事务处理模板(默认)
├── olap.yml    # OLAP 分析处理模板
├── crit.yml    # CRIT 关键业务模板
└── tiny.yml    # TINY 微型实例模板

创建自定义模板的步骤:

  1. 复制一个现有模板作为基础
  2. 根据需要修改参数
  3. 将模板放置在 roles/pgsql/templates/ 目录
  4. 在集群定义中通过 pg_conf 引用新模板

例如,创建一个名为 myapp.yml 的自定义模板:

cp roles/pgsql/templates/oltp.yml roles/pgsql/templates/myapp.yml
# 编辑 myapp.yml 进行自定义

然后在集群中使用:

pg-myapp:
  vars:
    pg_conf: myapp.yml

请注意,模板文件使用 Jinja2 模板语法,参数值会根据节点的实际资源(CPU、内存、磁盘)动态计算。


参数优化策略

了解更多关于模板参数优化的技术细节,请参阅 参数优化策略,其中详细介绍了:

  • 内存参数调整(共享缓冲区、工作内存、最大连接数)
  • CPU 参数调整(并行查询工作进程配置)
  • 存储空间参数(WAL 大小、临时文件限制)
  • 手工调整参数的方法

相关参数

  • pg_conf:指定使用的 PostgreSQL 配置模板
  • node_tune:指定使用的操作系统调优模板,应与 pg_conf 配套
  • pg_rto:恢复时间目标,影响故障切换超时
  • pg_rpo:恢复点目标,影响同步复制模式
  • pg_max_conn:覆盖模板的最大连接数
  • pg_shared_buffer_ratio:共享缓冲区占内存比例
  • pg_storage_type:存储类型,影响 IO 相关参数

17.1 - 默认配置模板的参数优化策略说明

了解在 Pigsty 中,预置的四种 Patroni 场景化模板所采用的不同参数优化策略

Pigsty 默认提供了四套场景化参数模板,可以通过 pg_conf 参数指定并使用。

  • tiny.yml:为小节点、虚拟机、小型演示优化(1-8核,1-16GB)
  • oltp.yml:为OLTP工作负载和延迟敏感应用优化(4C8GB+)(默认模板)
  • olap.yml:为OLAP工作负载和吞吐量优化(4C8G+)
  • crit.yml:为数据一致性和关键应用优化(4C8G+)

Pigsty 会针对这四种默认场景,采取不同的参数优化策略,如下所示:


内存参数调整

Pigsty 默认会检测系统的内存大小,并以此为依据设定最大连接数量与内存相关参数。

默认情况下,Pigsty 使用 25% 的内存作为 PostgreSQL 共享缓冲区,剩余的 75% 作为操作系统缓存。

默认情况下,如果用户没有设置一个 pg_max_conn 最大连接数,Pigsty 会根据以下规则使用默认值:

  • oltp: 500 (pgbouncer) / 1000 (postgres)
  • crit: 500 (pgbouncer) / 1000 (postgres)
  • tiny: 300
  • olap: 300

其中对于 OLTP 与 CRIT 模版来说,如果服务没有指向 pgbouncer 连接池,而是直接连接 postgres 数据库,最大连接会翻倍至 1000 条。

决定最大连接数后,work_mem 会根据共享内存数量 / 最大连接数计算得到,并限定在 64MB ~ 1GB 的范围内。

{% raw %}
{% if pg_max_conn != 'auto' and pg_max_conn|int >= 20 %}{% set pg_max_connections = pg_max_conn|int %}{% else %}{% if pg_default_service_dest|default('postgres') == 'pgbouncer' %}{% set pg_max_connections = 500 %}{% else %}{% set pg_max_connections = 1000 %}{% endif %}{% endif %}
{% set pg_max_prepared_transactions = pg_max_connections if 'citus' in pg_libs else 0 %}
{% set pg_max_locks_per_transaction = (2 * pg_max_connections)|int if 'citus' in pg_libs or 'timescaledb' in pg_libs else pg_max_connections %}
{% set pg_shared_buffers = (node_mem_mb|int * pg_shared_buffer_ratio|float) | round(0, 'ceil') | int %}
{% set pg_maintenance_mem = (pg_shared_buffers|int * 0.25)|round(0, 'ceil')|int %}
{% set pg_effective_cache_size = node_mem_mb|int - pg_shared_buffers|int  %}
{% set pg_workmem =  ([ ([ (pg_shared_buffers / pg_max_connections)|round(0,'floor')|int , 64 ])|max|int , 1024])|min|int %}
{% endraw %}

CPU参数调整

在 PostgreSQL 中,有 4 个与并行查询相关的重要参数,Pigsty 会自动根据当前系统的 CPU 核数进行参数优化。 在所有策略中,总并行进程数量(总预算)通常设置为 CPU 核数 + 8,且保底为 16 个,从而为逻辑复制与扩展预留足够的后台 worker 数量,OLAP 和 TINY 模板根据场景略有不同。

OLTP设置逻辑范围限制
max_worker_processesmax(100% CPU + 8, 16)核数 + 4,保底 1,
max_parallel_workersmax(ceil(50% CPU), 2)1/2 CPU 上取整,最少两个
max_parallel_maintenance_workersmax(ceil(33% CPU), 2)1/3 CPU 上取整,最少两个
max_parallel_workers_per_gathermin(max(ceil(20% CPU), 2),8)1/5 CPU 下取整,最少两个,最多 8 个
OLAP设置逻辑范围限制
max_worker_processesmax(100% CPU + 12, 20)核数 + 12,保底 20
max_parallel_workersmax(ceil(80% CPU, 2))4/5 CPU 上取整,最少两个
max_parallel_maintenance_workersmax(ceil(33% CPU), 2)1/3 CPU 上取整,最少两个
max_parallel_workers_per_gathermax(floor(50% CPU), 2)1/2 CPU 上取整,最少两个
CRIT设置逻辑范围限制
max_worker_processesmax(100% CPU + 8, 16)核数 + 8,保底 16
max_parallel_workersmax(ceil(50% CPU), 2)1/2 CPU 上取整,最少两个
max_parallel_maintenance_workersmax(ceil(33% CPU), 2)1/3 CPU 上取整,最少两个
max_parallel_workers_per_gather0, 按需启用
TINY设置逻辑范围限制
max_worker_processesmax(100% CPU + 4, 12)核数 + 4,保底 12
max_parallel_workersmax(ceil(50% CPU) 1)50% CPU 下取整,最少1个
max_parallel_maintenance_workersmax(ceil(33% CPU), 1)33% CPU 下取整,最少1个
max_parallel_workers_per_gather`0, 按需启用

请注意,CRIT 和 TINY 模板直接通过设置 max_parallel_workers_per_gather = 0 关闭了并行查询。 用户可以按需在需要时设置此参数以启用并行查询。

OLTP 和 CRIT 模板都额外设置了以下参数,将并行查询的 Cost x 2,以降低使用并行查询的倾向。

parallel_setup_cost: 2000           # double from 100 to increase parallel cost
parallel_tuple_cost: 0.2            # double from 0.1 to increase parallel cost
min_parallel_table_scan_size: 16MB  # double from 8MB to increase parallel cost
min_parallel_index_scan_size: 1024  # double from 512 to increase parallel cost

请注意 max_worker_processes 参数的调整必须在重启后才能生效。此外,当从库的本参数配置值高于主库时,从库将无法启动。 此参数必须通过 patroni 配置管理进行调整,该参数由 Patroni 管理,用于确保主从配置一致,避免在故障切换时新从库无法启动。


存储空间参数

Pigsty 默认检测 /data/postgres 主数据目录所在磁盘的总空间,并以此作为依据指定下列参数:

{% raw %}
min_wal_size: {{ ([pg_size_twentieth, 200])|min }}GB                  # 1/20 disk size, max 200GB
max_wal_size: {{ ([pg_size_twentieth * 4, 2000])|min }}GB             # 2/10 disk size, max 2000GB
max_slot_wal_keep_size: {{ ([pg_size_twentieth * 6, 3000])|min }}GB   # 3/10 disk size, max 3000GB
temp_file_limit: {{ ([pg_size_twentieth, 200])|min }}GB               # 1/20 of disk size, max 200GB
{% endraw %}
  • temp_file_limit 默认为磁盘空间的 5%,封顶不超过 200GB。
  • min_wal_size 默认为磁盘空间的 5%,封顶不超过 200GB。
  • max_wal_size 默认为磁盘空间的 20%,封顶不超过 2TB。
  • max_slot_wal_keep_size 默认为磁盘空间的 30%,封顶不超过 3TB。

作为特例, OLAP 模板允许 20% 的 temp_file_limit ,封顶不超过 2TB


手工调整参数

除了使用 Pigsty 自动配置的参数外,您还可以手工调整 PostgreSQL 参数。

使用 pg edit-config <cluster> 命令可以交互式编辑集群配置:

pg edit-config pg-meta

或者使用 -p 参数直接设置参数:

pg edit-config -p log_min_duration_statement=1000 pg-meta
pg edit-config --force -p shared_preload_libraries='timescaledb, pg_cron, pg_stat_statements, auto_explain' pg-meta

您也可以使用 Patroni REST API 来修改配置:

curl -u 'postgres:Patroni.API' \
    -d '{"postgresql":{"parameters": {"log_min_duration_statement":200}}}' \
    -s -X PATCH http://10.10.10.10:8008/config | jq .

17.2 - OLTP 模板

针对在线事务处理负载优化的 PostgreSQL 配置模板

oltp.yml 是 Pigsty 的默认配置模板,针对在线事务处理(OLTP)负载进行了优化。适用于 4-128 核 CPU 的服务器,特点是高并发连接、低延迟响应、高事务吞吐量。

建议同时使用 node_tune = oltp 进行操作系统级别的配套调优。


适用场景

OLTP 模板适用于以下场景:

  • 电商系统:订单处理、库存管理、用户交易
  • 社交应用:用户动态、消息推送、关注关系
  • 游戏后端:玩家数据、排行榜、游戏状态
  • SaaS 应用:多租户业务系统
  • Web 应用:常规的 CRUD 操作密集型应用

特征负载

  • 大量短事务(毫秒级)
  • 高并发连接(数百到数千)
  • 读写比例通常在 7:3 到 9:1
  • 对延迟敏感,要求快速响应
  • 数据一致性要求高

使用方法

oltp.yml 是默认模板,无需显式指定:

pg-oltp:
  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-oltp
    # pg_conf: oltp.yml  # PostgreSQL 配置模板(默认值)
    # node_tune: oltp    # 操作系统调优模板(默认值)

或显式指定:

pg-oltp:
  vars:
    pg_conf: oltp.yml    # PostgreSQL 配置模板
    node_tune: oltp      # 操作系统调优模板

参数详解

连接管理

max_connections: 500/1000   # 取决于是否使用 pgbouncer
superuser_reserved_connections: 10

内存配置

OLTP 模板的内存分配策略:

参数计算公式说明
shared_buffers内存 × pg_shared_buffer_ratio默认比例 0.25
maintenance_work_memshared_buffers × 25%用于 VACUUM、CREATE INDEX
work_mem64MB - 1GB根据 shared_buffers/max_connections 计算
effective_cache_size总内存 - shared_buffers可用于缓存的预估内存

work_mem 计算逻辑

work_mem = min(max(shared_buffers / max_connections, 64MB), 1GB)

这确保每个连接有足够的排序/哈希内存,但不会过度分配。

并行查询

OLTP 模板对并行查询做了适度限制,以避免并行查询抢占过多资源影响其他事务:

max_worker_processes: cpu + 8 (最小16)
max_parallel_workers: 50% × cpu (最小2)
max_parallel_workers_per_gather: 20% × cpu (2-8)
max_parallel_maintenance_workers: 33% × cpu (最小2)

同时提高了并行查询的成本估算,让优化器倾向于串行执行:

parallel_setup_cost: 2000      # 默认值 1000 的两倍
parallel_tuple_cost: 0.2       # 默认值 0.1 的两倍
min_parallel_table_scan_size: 16MB   # 默认值 8MB 的两倍
min_parallel_index_scan_size: 1024   # 默认值 512 的两倍

WAL 配置

min_wal_size: 磁盘/20 (最大200GB)
max_wal_size: 磁盘/5 (最大2000GB)
max_slot_wal_keep_size: 磁盘×3/10 (最大3000GB)
wal_buffers: 16MB
wal_writer_delay: 20ms
wal_writer_flush_after: 1MB
commit_delay: 20
commit_siblings: 10
checkpoint_timeout: 15min
checkpoint_completion_target: 0.80

这些设置平衡了数据安全性和写入性能。

Vacuum 配置

vacuum_cost_delay: 20ms         # 每轮 vacuum 后休眠
vacuum_cost_limit: 2000         # 每轮 vacuum 的代价上限
autovacuum_max_workers: 3
autovacuum_naptime: 1min
autovacuum_vacuum_scale_factor: 0.08    # 8% 表变化触发 vacuum
autovacuum_analyze_scale_factor: 0.04   # 4% 表变化触发 analyze
autovacuum_freeze_max_age: 1000000000

OLTP 模板使用保守的 vacuum 设置,避免 vacuum 操作影响在线事务性能。

查询优化

random_page_cost: 1.1           # SSD 优化
effective_io_concurrency: 200   # SSD 并发 IO
default_statistics_target: 400  # 统计信息精度

这些设置让优化器能够生成更好的查询计划。

日志与监控

log_min_duration_statement: 100         # 记录超过 100ms 的慢查询
log_statement: ddl                      # 记录 DDL 语句
log_checkpoints: on
log_lock_waits: on
log_temp_files: 1024                    # 记录超过 1MB 的临时文件
log_autovacuum_min_duration: 1s
track_io_timing: on
track_functions: all
track_activity_query_size: 8192

客户端超时

deadlock_timeout: 50ms
idle_in_transaction_session_timeout: 10min

10 分钟的空闲事务超时可以防止长时间持有锁的僵尸事务。

扩展配置

shared_preload_libraries: 'pg_stat_statements, auto_explain'

# auto_explain
auto_explain.log_min_duration: 1s
auto_explain.log_analyze: on
auto_explain.log_verbose: on
auto_explain.log_timing: on
auto_explain.log_nested_statements: true

# pg_stat_statements
pg_stat_statements.max: 10000
pg_stat_statements.track: all
pg_stat_statements.track_utility: off
pg_stat_statements.track_planning: off

与其他模板的对比

特性OLTPOLAPCRIT
max_connections500-1000500500-1000
work_mem64MB-1GB64MB-8GB64MB-1GB
并行查询适度限制激进启用禁用
vacuum 激进度保守激进保守
事务超时10min禁用1min
慢查询阈值100ms1000ms100ms

为什么选择 OLTP 而非 OLAP?

  • 您的查询大多数是简单的点查和范围查询
  • 事务响应时间要求在毫秒级
  • 有大量并发连接
  • 不需要执行复杂的分析查询

为什么选择 OLTP 而非 CRIT?

  • 可以接受极小概率的数据丢失(异步复制)
  • 不需要完整的审计日志
  • 希望获得更好的写入性能

性能调优建议

连接池

对于高并发场景,强烈建议使用 PgBouncer 连接池:

pg-oltp:
  vars:
    pg_default_service_dest: pgbouncer  # 默认值
    pgbouncer_poolmode: transaction     # 事务级池化

只读分离

使用只读从库分担读取负载:

pg-oltp:
  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 }

监控指标

关注以下监控指标:

  • 连接数:活跃连接数、等待连接数
  • 事务率:TPS、提交/回滚比例
  • 响应时间:查询延迟百分位(p50/p95/p99)
  • 锁等待:锁等待时间、死锁次数
  • 复制延迟:从库延迟时间和字节数

参考资料

17.3 - OLAP 模板

针对在线分析处理负载优化的 PostgreSQL 配置模板

olap.yml 是针对在线分析处理(OLAP)负载优化的配置模板。适用于 4-128 核 CPU 的服务器,特点是支持大查询、高并行度、宽松的超时设置和激进的 Vacuum 策略。

建议同时使用 node_tune = olap 进行操作系统级别的配套调优。


适用场景

OLAP 模板适用于以下场景:

  • 数据仓库:历史数据存储、多维分析
  • BI 报表:复杂报表查询、仪表盘数据源
  • ETL 处理:数据抽取、转换、加载
  • 数据分析:Ad-hoc 查询、数据探索
  • HTAP 混合负载:分析型从库

特征负载

  • 复杂查询(秒级到分钟级)
  • 低并发连接(数十到数百)
  • 读密集型,写入通常是批量操作
  • 对吞吐量敏感,可以容忍较高延迟
  • 需要扫描大量数据

使用方法

在集群定义中指定 pg_conf = olap.yml

pg-olap:
  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-olap
    pg_conf: olap.yml    # PostgreSQL 分析处理模板
    node_tune: olap      # 操作系统分析处理调优

也可以将 olap.yml 模板用于专用的离线从库:

pg-mixed:
  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, pg_conf: olap.yml }  # 离线分析从库
  vars:
    pg_cluster: pg-mixed
    pg_conf: oltp.yml    # 主库和在线从库使用 OLTP 模板
    node_tune: oltp      # 操作系统 OLTP 调优

参数详解

连接管理

max_connections: 500
superuser_reserved_connections: 10

OLAP 场景通常不需要大量连接,500 个连接足以应对大多数分析负载。

内存配置

OLAP 模板的内存分配策略更为激进:

参数计算公式说明
shared_buffers内存 × pg_shared_buffer_ratio默认比例 0.25
maintenance_work_memshared_buffers × 50%加速索引创建和 VACUUM
work_mem64MB - 8GB更大的排序/哈希内存
effective_cache_size总内存 - shared_buffers可用于缓存的预估内存

work_mem 计算逻辑(与 OLTP 不同):

work_mem = min(max(shared_buffers / max_connections, 64MB), 8GB)

更大的 work_mem 允许更大的排序和哈希操作在内存中完成,避免磁盘溢出。

锁与事务

max_locks_per_transaction: 2-4x maxconn   # OLTP 是 1-2x

OLAP 查询可能涉及更多表(分区表、大量 JOIN),因此需要更多的锁槽。

并行查询

OLAP 模板激进启用并行查询:

max_worker_processes: cpu + 12 (最小20)      # OLTP: cpu + 8
max_parallel_workers: 80% × cpu (最小2)      # OLTP: 50%
max_parallel_workers_per_gather: 50% × cpu   # OLTP: 20% (最大8)
max_parallel_maintenance_workers: 33% × cpu

并行查询成本保持默认值,让优化器更倾向于选择并行计划:

# parallel_setup_cost: 1000    # 默认值,不加倍
# parallel_tuple_cost: 0.1     # 默认值,不加倍

同时启用分区智能优化:

enable_partitionwise_join: on       # 分区表智能 JOIN
enable_partitionwise_aggregate: on  # 分区表智能聚合

IO 配置(PG17+)

io_workers: 50% × cpu (4-32)    # OLTP: 25% (4-16)

更多的 IO 工作线程支持并行扫描大表。

WAL 配置

min_wal_size: 磁盘/20 (最大200GB)
max_wal_size: 磁盘/5 (最大2000GB)
max_slot_wal_keep_size: 磁盘×3/10 (最大3000GB)
temp_file_limit: 磁盘/5 (最大2000GB)   # OLTP: 磁盘/20

更大的 temp_file_limit 允许更大的中间结果溢出到磁盘。

Vacuum 配置

OLAP 模板使用更激进的 vacuum 设置:

vacuum_cost_delay: 10ms         # OLTP: 20ms,更快的 vacuum
vacuum_cost_limit: 10000        # OLTP: 2000,每轮更多工作
autovacuum_max_workers: 3
autovacuum_naptime: 1min
autovacuum_vacuum_scale_factor: 0.08
autovacuum_analyze_scale_factor: 0.04

分析型数据库通常有大量批量写入,需要更激进的 vacuum 策略来回收空间。

查询优化

random_page_cost: 1.1
effective_io_concurrency: 200
default_statistics_target: 1000    # OLTP: 400,更精确的统计信息

更高的 default_statistics_target 提供更精确的查询计划,对复杂分析查询尤为重要。

日志与监控

log_min_duration_statement: 1000    # OLTP: 100ms,放宽慢查询阈值
log_statement: ddl
log_checkpoints: on
log_lock_waits: on
log_temp_files: 1024
log_autovacuum_min_duration: 1s
track_io_timing: on
track_cost_delay_timing: on         # PG18+,跟踪 vacuum 代价延迟
track_functions: all
track_activity_query_size: 8192

客户端超时

deadlock_timeout: 50ms
idle_in_transaction_session_timeout: 0   # OLTP: 10min,禁用

分析查询可能需要长时间持有事务,因此禁用空闲事务超时。


与 OLTP 模板的主要差异

参数OLAPOLTP差异原因
max_connections500500-1000分析负载连接数少
work_mem 上限8GB1GB支持更大的内存排序
maintenance_work_mem50% buffer25% buffer加速索引创建
max_locks_per_transaction2-4x1-2x更多表参与查询
max_parallel_workers80% cpu50% cpu激进并行
max_parallel_workers_per_gather50% cpu20% cpu激进并行
parallel_setup_cost10002000默认值,鼓励并行
parallel_tuple_cost0.10.2默认值,鼓励并行
enable_partitionwise_joinonoff分区表优化
enable_partitionwise_aggregateonoff分区表优化
vacuum_cost_delay10ms20ms激进 vacuum
vacuum_cost_limit100002000激进 vacuum
temp_file_limit1/5 磁盘1/20 磁盘允许更大临时文件
io_workers50% cpu25% cpu更多并行 IO
log_min_duration_statement1000ms100ms放宽慢查询阈值
default_statistics_target1000400更精确统计
idle_in_transaction_session_timeout禁用10min允许长事务

性能调优建议

结合 TimescaleDB

OLAP 模板与 TimescaleDB 配合使用效果极佳:

pg-timeseries:
  vars:
    pg_conf: olap.yml
    pg_libs: 'timescaledb, pg_stat_statements, auto_explain'
    pg_extensions:
      - timescaledb

结合 pg_duckdb

对于极致的分析性能,可以结合 pg_duckdb:

pg-analytics:
  vars:
    pg_conf: olap.yml
    pg_libs: 'pg_duckdb, pg_stat_statements, auto_explain'

列式存储

考虑使用 Citus 的列式存储或 pg_mooncake:

pg_extensions:
  - citus_columnar  # 或 pg_mooncake

资源隔离

对于混合负载,建议将分析查询隔离到专用从库:

pg-mixed:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }               # OLTP 写入
    10.10.10.12: { pg_seq: 2, pg_role: replica }               # OLTP 读取
    10.10.10.13: { pg_seq: 3, pg_role: offline }               # OLAP 分析
  vars:
    pg_cluster: pg-mixed

监控指标

关注以下监控指标:

  • 查询时间:长查询的执行时间分布
  • 并行度:并行工作进程的使用率
  • 临时文件:临时文件的大小和数量
  • 磁盘 IO:顺序扫描和索引扫描的 IO 量
  • 缓存命中率:shared_buffers 和 OS 缓存的命中率

参考资料

17.4 - CRIT 模板

针对核心金融业务优化的 PostgreSQL 配置模板,强调数据安全与审计合规

crit.yml 是针对核心金融业务优化的配置模板。适用于 4-128 核 CPU 的服务器,特点是强制同步复制、数据校验和、完整审计日志、严格的安全设置。这个模板牺牲一定的性能来换取最高级别的数据安全性。

建议同时使用 node_tune = crit 进行操作系统级别的配套调优,优化脏页数量。


适用场景

CRIT 模板适用于以下场景:

  • 金融交易:银行转账、支付清算、证券交易
  • 核心账务:总账系统、会计系统
  • 合规审计:需要完整操作记录的业务
  • 关键业务:任何不能容忍数据丢失的场景

特征需求

  • 零数据丢失(RPO = 0)
  • 数据完整性校验
  • 完整的审计日志
  • 严格的安全策略
  • 可以接受一定的性能损失

使用方法

在集群定义中指定 pg_conf = crit.yml

pg-finance:
  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-finance
    pg_conf: crit.yml    # PostgreSQL 关键业务模板
    node_tune: crit      # 操作系统关键业务调优

建议:关键业务集群至少配置 3 个节点,以确保在一个节点故障时仍能保持同步复制。


核心特性

强制同步复制

CRIT 模板强制启用同步复制,无论 pg_rpo 设置为何值:

synchronous_mode: true   # 强制开启,不受 pg_rpo 影响

这意味着每次事务提交都必须等待至少一个从库确认写入,确保 RPO = 0(零数据丢失)。

代价:写入延迟会增加(通常增加 1-5ms,取决于网络延迟)。

强制数据校验和

CRIT 模板强制启用数据校验和,无论 pg_checksum 设置为何值:

initdb:
  - data-checksums   # 强制启用,不检查 pg_checksum 参数

数据校验和可以检测到磁盘静默损坏(bit rot),这对金融数据尤为重要。

禁用并行查询

CRIT 模板禁用了并行查询的 gather 操作:

max_parallel_workers_per_gather: 0   # 禁用并行查询

同时提高了并行查询的成本估算:

parallel_setup_cost: 2000
parallel_tuple_cost: 0.2
min_parallel_table_scan_size: 16MB
min_parallel_index_scan_size: 1024

原因:并行查询可能导致查询延迟不稳定,对于延迟敏感的金融交易场景,稳定可预测的性能更为重要。


参数详解

连接管理

max_connections: 500/1000   # 取决于是否使用 pgbouncer
superuser_reserved_connections: 10

与 OLTP 模板相同。

内存配置

参数计算公式说明
shared_buffers内存 × pg_shared_buffer_ratio默认比例 0.25
maintenance_work_memshared_buffers × 25%用于 VACUUM、CREATE INDEX
work_mem64MB - 1GB与 OLTP 相同
effective_cache_size总内存 - shared_buffers可用于缓存的预估内存

WAL 配置(关键差异)

wal_writer_delay: 10ms              # OLTP: 20ms,更频繁刷新
wal_writer_flush_after: 0           # OLTP: 1MB,立即刷新,不缓冲
idle_replication_slot_timeout: 3d   # OLTP: 7d,更严格的槽位清理

wal_writer_flush_after: 0 确保每次 WAL 写入都立即刷到磁盘,最大程度减少数据丢失风险。

复制配置(PG15-)

vacuum_defer_cleanup_age: 500000    # 仅 PG15 及以下版本

这个参数保留最近 50 万个事务的变更不被 vacuum 清理,为从库提供更多的追赶缓冲。

审计日志(关键差异)

CRIT 模板启用完整的连接审计:

PostgreSQL 18+:

log_connections: 'receipt,authentication,authorization'

PostgreSQL 17 及以下:

log_connections: 'on'
log_disconnections: 'on'

这记录了每个连接的完整生命周期,包括:

  • 连接接收
  • 认证过程
  • 授权结果
  • 断开连接

查询日志

log_min_duration_statement: 100     # 记录超过 100ms 的查询
log_statement: ddl                  # 记录所有 DDL
track_activity_query_size: 32768    # OLTP: 8192,保存完整查询

32KB 的 track_activity_query_size 确保能捕获完整的长查询文本。

统计跟踪

track_io_timing: on
track_cost_delay_timing: on         # PG18+,跟踪 vacuum 代价延迟
track_functions: all
track_activity_query_size: 32768

客户端超时(关键差异)

idle_in_transaction_session_timeout: 1min   # OLTP: 10min,更严格

1 分钟的空闲事务超时可以快速释放持有锁的僵尸事务,避免阻塞其他交易。

扩展配置

shared_preload_libraries: '$libdir/passwordcheck, pg_stat_statements, auto_explain'

注意:CRIT 模板默认加载 passwordcheck 扩展,强制密码复杂度检查。


与 OLTP 模板的主要差异

参数CRITOLTP差异原因
synchronous_mode强制 true取决于 pg_rpo零数据丢失
data-checksums强制启用可选数据完整性
max_parallel_workers_per_gather020% cpu稳定延迟
wal_writer_delay10ms20ms更频繁刷新
wal_writer_flush_after01MB立即刷新
idle_replication_slot_timeout3d7d更严格清理
idle_in_transaction_session_timeout1min10min快速释放锁
track_activity_query_size32KB8KB完整查询记录
log_connections完整记录仅授权审计合规
log_disconnectionsonoff审计合规
passwordcheck启用未启用密码安全
vacuum_defer_cleanup_age5000000从库追赶缓冲

性能影响

使用 CRIT 模板会带来以下性能影响:

写入延迟增加

同步复制会增加 1-5ms 的写入延迟(取决于网络):

异步复制: 提交 -> 本地刷盘 -> 返回客户端
同步复制: 提交 -> 本地刷盘 -> 等待从库确认 -> 返回客户端

写入吞吐量下降

由于需要等待从库确认,写入 TPS 可能下降 10-30%。

查询延迟更稳定

禁用并行查询后,查询延迟更加可预测,没有并行查询启动的开销波动。

资源开销略有增加

更频繁的 WAL 刷新和完整的审计日志会带来额外的 IO 开销。


高可用配置

最小推荐配置

pg-critical:
  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-critical
    pg_conf: crit.yml    # PostgreSQL 关键业务模板
    node_tune: crit      # 操作系统关键业务调优

3 节点配置确保在一个节点故障时仍能保持同步复制。

跨机房部署

对于金融级别的容灾要求:

pg-critical:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary, pg_weight: 100 }  # 机房 A
    10.10.10.12: { pg_seq: 2, pg_role: replica, pg_weight: 100 }  # 机房 A
    10.20.10.13: { pg_seq: 3, pg_role: replica, pg_weight: 0 }    # 机房 B(备用)
  vars:
    pg_cluster: pg-critical
    pg_conf: crit.yml    # PostgreSQL 关键业务模板
    node_tune: crit      # 操作系统关键业务调优

法定人数提交

对于更高的一致性要求,可以配置多个同步从库:

$ pg edit-config pg-critical
synchronous_mode: true
synchronous_node_count: 2    # 需要 2 个从库确认

安全加固建议

密码策略

CRIT 模板已启用 passwordcheck,建议进一步配置:

-- 设置密码最小长度
ALTER SYSTEM SET password_encryption = 'scram-sha-256';

审计扩展

考虑启用 pgaudit 扩展进行更详细的审计:

pg_libs: 'pg_stat_statements, auto_explain, pgaudit'
pg_parameters:
  pgaudit.log: 'ddl, role, write'

网络隔离

确保数据库网络与业务网络隔离,使用 HBA 规则 限制访问。


监控指标

对于关键业务集群,重点关注:

  • 复制延迟:同步复制延迟应接近 0
  • 事务提交时间:p99 延迟
  • 锁等待:长时间锁等待可能影响业务
  • 检查点:检查点持续时间和频率
  • WAL 生成速率:预测磁盘空间需求

参考资料

17.5 - TINY 模板

针对微型实例和资源受限环境优化的 PostgreSQL 配置模板

tiny.yml 是针对微型实例和资源受限环境优化的配置模板。适用于 1-3 核 CPU 的服务器,特点是最小化资源占用、保守的内存分配、禁用并行查询。

建议同时使用 node_tune = tiny 进行操作系统级别的配套调优。


适用场景

TINY 模板适用于以下场景:

  • 开发测试:本地开发环境、CI/CD 测试
  • 低配虚拟机:1-2 核 CPU、1-4GB 内存的云主机
  • 边缘计算:树莓派、嵌入式设备
  • Demo 演示:快速体验 Pigsty 功能
  • 个人项目:资源有限的个人博客、小型应用

资源限制

  • 1-3 核 CPU
  • 1-8 GB 内存
  • 有限的磁盘空间
  • 可能与其他服务共享资源

使用方法

在集群定义中指定 pg_conf = tiny.yml

pg-dev:
  hosts:
    10.10.10.11: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-dev
    pg_conf: tiny.yml    # PostgreSQL 微型实例模板
    node_tune: tiny      # 操作系统微型实例调优

单节点开发环境:

pg-local:
  hosts:
    127.0.0.1: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-local
    pg_conf: tiny.yml    # PostgreSQL 微型实例模板
    node_tune: tiny      # 操作系统微型实例调优

参数详解

连接管理

max_connections: 250   # OLTP: 500-1000,减少连接开销
superuser_reserved_connections: 10

微型实例不需要处理大量并发连接,250 个连接足以应对开发测试场景。

内存配置

TINY 模板使用保守的内存分配策略:

参数计算公式说明
shared_buffers内存 × pg_shared_buffer_ratio默认比例 0.25
maintenance_work_memshared_buffers × 25%用于 VACUUM、CREATE INDEX
work_mem16MB - 256MB更小的排序/哈希内存
effective_cache_size总内存 - shared_buffers可用于缓存的预估内存

work_mem 计算逻辑(与 OLTP 不同):

work_mem = min(max(shared_buffers / max_connections, 16MB), 256MB)

更小的 work_mem 上限(256MB vs OLTP 的 1GB)避免内存溢出。

并行查询(完全禁用)

TINY 模板完全禁用了并行查询:

max_worker_processes: cpu + 4 (最小12)      # OLTP: cpu + 8
max_parallel_workers: 50% × cpu (最小1)      # OLTP: 50% (最小2)
max_parallel_workers_per_gather: 0           # 禁用并行查询
max_parallel_maintenance_workers: 33% × cpu (最小1)

max_parallel_workers_per_gather: 0 确保查询不会启动并行工作进程,避免在低核心环境下争抢资源。

IO 配置(PG17+)

io_workers: 3   # 固定值,OLTP: 25% cpu (4-16)

固定的低 IO 工作线程数量,适合资源受限环境。

Vacuum 配置

vacuum_cost_delay: 20ms
vacuum_cost_limit: 2000
autovacuum_max_workers: 2          # OLTP: 3,减少一个工作进程
autovacuum_naptime: 1min
# autovacuum_vacuum_scale_factor 使用默认值
# autovacuum_analyze_scale_factor 使用默认值

减少 autovacuum 工作进程数量,降低后台资源占用。

查询优化

random_page_cost: 1.1
effective_io_concurrency: 200
default_statistics_target: 200     # OLTP: 400,降低统计精度以节省空间

较低的 default_statistics_target 减少 pg_statistic 表的大小。

日志配置

log_min_duration_statement: 100    # 与 OLTP 相同
log_statement: ddl
log_checkpoints: on
log_lock_waits: on
log_temp_files: 1024
# log_connections 使用默认设置(不额外记录)

TINY 模板不启用额外的连接日志,以减少日志量。

客户端超时

deadlock_timeout: 50ms
idle_in_transaction_session_timeout: 10min   # 与 OLTP 相同

扩展配置

shared_preload_libraries: 'pg_stat_statements, auto_explain'

pg_stat_statements.max: 2500      # OLTP: 10000,减少内存占用
pg_stat_statements.track: all
pg_stat_statements.track_utility: off
pg_stat_statements.track_planning: off

pg_stat_statements.max 从 10000 降到 2500,减少约 75% 的内存占用。


与 OLTP 模板的主要差异

参数TINYOLTP差异原因
max_connections250500-1000减少连接开销
work_mem 上限256MB1GB避免内存溢出
max_worker_processescpu+4cpu+8减少后台进程
max_parallel_workers_per_gather020% cpu禁用并行查询
autovacuum_max_workers23减少后台负载
default_statistics_target200400节省空间
pg_stat_statements.max250010000减少内存占用
io_workers325% cpu固定低值

资源估算

以下是 TINY 模板在不同配置下的资源使用估算:

1 核 1GB 内存

shared_buffers: ~256MB
work_mem: ~16MB
maintenance_work_mem: ~64MB
max_connections: 250
max_worker_processes: ~12

PostgreSQL 进程内存占用:约 400-600MB

2 核 4GB 内存

shared_buffers: ~1GB
work_mem: ~32MB
maintenance_work_mem: ~256MB
max_connections: 250
max_worker_processes: ~12

PostgreSQL 进程内存占用:约 1.5-2GB

4 核 8GB 内存

此配置建议使用 OLTP 模板而非 TINY 模板:

pg-small:
  vars:
    pg_conf: oltp.yml   # 4核8GB可以使用OLTP模板

性能调优建议

进一步减少资源

如果资源极度受限,可以考虑:

pg_parameters:
  max_connections: 100           # 进一步减少
  shared_buffers: 128MB          # 进一步减少
  maintenance_work_mem: 32MB
  work_mem: 8MB

禁用不需要的扩展

pg_libs: 'pg_stat_statements'    # 只保留必要扩展

关闭不需要的功能

pg_parameters:
  track_io_timing: off           # 禁用 IO 时间跟踪
  track_functions: none          # 禁用函数跟踪

使用外部连接池

即使在微型实例上,使用 PgBouncer 也能显著提高并发能力:

pg-tiny:
  vars:
    pg_conf: tiny.yml
    pg_default_service_dest: pgbouncer
    pgbouncer_poolmode: transaction

云平台推荐规格

AWS

  • t3.micro:1 vCPU, 1GB RAM - 适合 TINY
  • t3.small:2 vCPU, 2GB RAM - 适合 TINY
  • t3.medium:2 vCPU, 4GB RAM - 可考虑 OLTP

阿里云

  • ecs.t6-c1m1.small:1 vCPU, 1GB RAM - 适合 TINY
  • ecs.t6-c1m2.small:1 vCPU, 2GB RAM - 适合 TINY
  • ecs.t6-c1m4.small:1 vCPU, 4GB RAM - 适合 TINY

腾讯云

  • SA2.SMALL1:1 vCPU, 1GB RAM - 适合 TINY
  • SA2.SMALL2:1 vCPU, 2GB RAM - 适合 TINY
  • SA2.SMALL4:1 vCPU, 4GB RAM - 适合 TINY

边缘设备部署

树莓派 4

pg-pi:
  hosts:
    192.168.1.100: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-pi
    pg_conf: tiny.yml       # PostgreSQL 微型实例模板
    node_tune: tiny         # 操作系统微型实例调优
    pg_storage_type: SSD    # 建议使用 SSD 存储

Docker 容器

pg-docker:
  hosts:
    172.17.0.2: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-docker
    pg_conf: tiny.yml       # PostgreSQL 微型实例模板
    node_tune: tiny         # 操作系统微型实例调优

升级到 OLTP

当您的应用增长,需要更多资源时,可以轻松升级到 OLTP 模板

  1. 升级虚拟机规格(4核 8GB 以上)
  2. 修改集群配置:
pg-growing:
  vars:
    pg_conf: oltp.yml    # 从 tiny.yml 改为 oltp.yml
    node_tune: oltp      # 从 tiny 改为 oltp
  1. 重新配置集群 或重新部署

参考资料

18 - 内核分支

如何在 Pigsty 中使用其他 PostgreSQL 内核分支?例如 Citus,Babelfish,IvorySQL,PolarDB 等

在 Pigsty 中,您可以使用不同 “风味” 的 PostgreSQL 分支替换 “原生PG内核”,实现特殊的功能与效果。

Pigsty 支持各种 PostgreSQL 内核和兼容分支,使您能够模拟不同的数据库系统,同时利用 PostgreSQL 的生态系统。每个内核都能提供独特的功能和兼容性层。

内核关键特性描述
PostgreSQL444扩展原版 PostgreSQL,配备 444 扩展
Citus水平扩展通过原生扩展实现分布式 PostgreSQL
WiltonDBSQL Server 兼容SQL Server 线协议兼容
IvorySQLOracle 兼容Oracle 语法和 PL/SQL 兼容
OpenHaloMySQL 兼容MySQL 线协议兼容
Percona透明数据加密带有 pg_tde 的 Percona 发行版
FerretDBMongoDB 迁移MongoDB 线协议兼容
OrioleDBOLTP 优化Zheap,无膨胀,S3 存储
PolarDBAurora 风格 RACRAC,中国国产合规
Supabase后端即服务基于 PostgreSQL 的 BaaS,Firebase 替代方案
CloudberryMPP数仓与数据分析大规模并行处理数据仓库

18.1 - PostgreSQL

带有 444 扩展的原版 PostgreSQL 内核

PostgreSQL 是世界上最先进和最受欢迎的开源数据库。

Pigsty 支持 PostgreSQL 13 ~ 18,并提供 444 个 PG 扩展。


快速开始

使用 pgsql 配置模板 安装 Pigsty。

./configure -c pgsql     # 使用 postgres 内核
./deploy.yml             # 使用 pigsty 设置一切

大多数 配置模板 默认使用 PostgreSQL 内核,例如:

  • meta : 默认,带有核心扩展(vector、postgis、timescale)的 postgres
  • rich : 安装了所有扩展的 postgres
  • slim : 仅 postgres,无监控基础设施
  • full : 用于 HA 演示的 4 节点沙盒
  • pgsql : 最小的 postgres 内核配置示例

配置

原版 PostgreSQL 内核不需要特殊调整:

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  }
    pg_databases:
      - { name: meta, baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [ vector ]}
    pg_hba_rules:
      - { user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes' }
    node_crontab: [ '00 01 * * * postgres /pg/bin/pg-backup full' ] # 每天凌晨 1 点进行全量备份
    pg_packages: [ pgsql-main, pgsql-common ]   # pg 内核和通用工具
    #pg_extensions: [ pg18-time ,pg18-gis ,pg18-rag ,pg18-fts ,pg18-olap ,pg18-feat ,pg18-lang ,pg18-type ,pg18-util ,pg18-func ,pg18-admin ,pg18-stat ,pg18-sec ,pg18-fdw ,pg18-sim ,pg18-etl]

版本选择

要使用不同的 PostgreSQL 主版本,您可以使用 -v 参数进行配置:

./configure -c pgsql            # 默认就是 postgresql 18,无需显式指定
./configure -c pgsql -v 17      # 使用 postgresql 17
./configure -c pgsql -v 16      # 使用 postgresql 16
./configure -c pgsql -v 15      # 使用 postgresql 15
./configure -c pgsql -v 14      # 使用 postgresql 14
./configure -c pgsql -v 13      # 使用 postgresql 13

如果 PostgreSQL 集群已经安装,您需要在安装新版本之前卸载它:

./pgsql-rm.yml # -l pg-meta

扩展生态

Pigsty 为 PostgreSQL 提供了丰富的扩展生态,包括:

  • 时序类:timescaledb, pg_cron, periods
  • 地理类:postgis, h3, pgrouting
  • 向量类:pgvector, pgml, vchord
  • 搜索类:pg_trgm, zhparser, pgroonga
  • 分析类:citus, pg_duckdb, pg_analytics
  • 特性类:age, pg_graphql, rum
  • 语言类:plpython3u, pljava, plv8
  • 类型类:hstore, ltree, citext
  • 工具类:http, pg_net, pgjwt
  • 函数类:pgcrypto, uuid-ossp, pg_uuidv7
  • 管理类:pg_repack, pgagent, pg_squeeze
  • 统计类:pg_stat_statements, pg_qualstats, auto_explain
  • 安全类:pgaudit, pgcrypto, pgsodium
  • 外部类:postgres_fdw, mysql_fdw, oracle_fdw
  • 兼容类:orafce, babelfishpg_tds
  • 数据类:pglogical, wal2json, decoderbufs

详情请参考 扩展目录

18.2 - Supabase

如何使用Pigsty自建Supabase,一键拉起开源Firebase替代,后端全栈全家桶。

Supabase —— Build in a weekend, Scale to millions

Supabase 是一个开源的 Firebase 替代,对 PostgreSQL 进行了封装,并提供了认证,开箱即用的 API,边缘函数,实时订阅,对象存储,向量嵌入能力。 这是一个低代码的一站式后端平台,能让你几乎告别大部分后端开发的工作,只需要懂数据库设计与前端即可快速出活!

Supabase 的口号是:“花个周末写写,随便扩容至百万”。诚然,在小微规模(4c8g)内的 Supabase 极有性价比,堪称赛博菩萨。 —— 但当你真的增长到百万用户时 —— 确实应该认真考虑托管自建 Supabase 了 —— 无论是出于功能,性能,还是成本上的考虑。

Pigsty 为您提供完整的 Supabase 一键自建方案。自建的 Supabase 可以享受完整的 PostgreSQL 监控,IaC,PITR 与高可用, 而且相比 Supabase 云服务,提供了多达 444 个开箱即用的 PostgreSQL 扩展,并能够更充分地利用现代硬件的性能与成本优势。

完整自建教程,请参考:《Supabase自建手册


快速上手

Pigsty 默认提供的 supa.yml 配置模板定义了一套单节点 Supabase。

首先,使用 Pigsty 标准安装流程 安装 Supabase 所需的 MinIO 与 PostgreSQL 实例:

 curl -fsSL https://repo.pigsty.io/get | bash
./bootstrap          # 环境检查,安装依赖
./configure -c supa  # 重要:请在配置文件中修改密码等关键信息!
./deploy.yml         # 安装 Pigsty,拉起 PGSQL 与 MINIO!

请在部署 Supabase 前,根据您的实际情况,修改 pigsty.yml 配置文件中 关于 Supabase 的参数(主要是密码!)

然后,运行 supabase.yml 完成剩余的工作,拉起 Supabase 容器

./docker.yml       # 安装 Docker 模块
./app.yml          # 拉起 Supabase 无状态部分!

中国区域用户注意,请您配置合适的 Docker 镜像站点或代理服务器绕过 GFW 以拉取 DockerHub 镜像。 对于 专业订阅 ,我们提供在没有互联网访问的情况下,离线安装 Pigsty 与 Supabase 的能力。

Pigsty 默认通过管理节点/INFRA节点上的 Nginx 对外暴露 Web 服务,您可以在本地添加 supa.pigsty 的 DNS 解析指向该节点, 然后通过浏览器访问 https://supa.pigsty 即可进入 Supabase Studio 管理界面。

默认用户名与密码:supabase / pigsty

18.3 - Citus

使用 Pigsty 部署原生高可用的 Citus 水平分片集群,将 PostgreSQL 无缝伸缩到多套分片并加速 OLTP/OLAP 查询。

Pigsty 原生支持 Citus。这是一个基于原生 PostgreSQL 内核的分布式水平扩展插件。


安装

Citus 是一个 PostgreSQL 扩展插件,可以按照标准插件安装的流程,在原生 PostgreSQL 集群上加装启用。

./pgsql.yml -t pg_extension -e '{"pg_extensions":["citus"]}'

配置

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

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

您可以将每个 Citus 集群分别定义为独立的分组,像标准的 PostgreSQL 集群一样,如 conf/dbms/citus.yml 所示:

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'  }

您也可以在一个分组内指定所有 Citus 集群成员的身份参数,如 prod.yml 所示:

#==========================================================#
# pg-citus: 10 node citus cluster (5 x primary-replica pair)
#==========================================================#
pg-citus: # citus group
  hosts:
    10.10.10.50: { pg_group: 0, pg_cluster: pg-citus0 ,pg_vip_address: 10.10.10.60/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.51: { pg_group: 0, pg_cluster: pg-citus0 ,pg_vip_address: 10.10.10.60/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.52: { pg_group: 1, pg_cluster: pg-citus1 ,pg_vip_address: 10.10.10.61/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.53: { pg_group: 1, pg_cluster: pg-citus1 ,pg_vip_address: 10.10.10.61/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.54: { pg_group: 2, pg_cluster: pg-citus2 ,pg_vip_address: 10.10.10.62/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.55: { pg_group: 2, pg_cluster: pg-citus2 ,pg_vip_address: 10.10.10.62/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.56: { pg_group: 3, pg_cluster: pg-citus3 ,pg_vip_address: 10.10.10.63/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.57: { pg_group: 3, pg_cluster: pg-citus3 ,pg_vip_address: 10.10.10.63/24 ,pg_seq: 1, pg_role: replica }
    10.10.10.58: { pg_group: 4, pg_cluster: pg-citus4 ,pg_vip_address: 10.10.10.64/24 ,pg_seq: 0, pg_role: primary }
    10.10.10.59: { pg_group: 4, pg_cluster: pg-citus4 ,pg_vip_address: 10.10.10.64/24 ,pg_seq: 1, pg_role: replica }
  vars:
    pg_mode: citus                    # pgsql cluster mode: citus
    pg_shard: pg-citus                # citus shard name: pg-citus
    pg_primary_db: test               # primary database used by citus
    pg_dbsu_password: DBUser.Postgres # all dbsu password access for citus cluster
    pg_vip_enabled: true
    pg_vip_interface: eth1
    pg_extensions: [ 'citus postgis timescaledb pgvector' ]
    pg_libs: 'citus, timescaledb, pg_stat_statements, auto_explain' # citus will be added by patroni automatically
    pg_users: [ { name: test ,password: test ,pgbouncer: true ,roles: [ dbrole_admin ] } ]
    pg_databases: [ { name: test ,owner: test ,extensions: [ { name: citus }, { name: postgis } ] } ]
    pg_hba_rules:
      - { user: 'all' ,db: all  ,addr: 10.10.10.0/24 ,auth: trust ,title: 'trust citus cluster members'        }
      - { 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'  }

使用

您可以像访问普通集群一样,访问任意节点:

pgbench -i postgres://test:test@pg-citus0/test
pgbench -nv -P1 -T1000 -c 2 postgres://test:test@pg-citus0/test

默认情况下,您对某一个 Shard 进行的变更,都只发生在这套集群上,而不会同步到其他 Shard。

如果你希望将写入分布到所有 Shard,可以使用 Citus 提供的 API 函数,将表标记为:

  • 水平分片表(自动分区,需要指定分区键)
  • 引用表(全量复制:不需要指定分区键):

从 Citus 11.2 开始,任何 Citus 数据库节点都可以扮演协调者的角色,即,任意一个主节点都可以写入:

psql -h pg-citus0 -d test -c "SELECT create_distributed_table('pgbench_accounts', 'aid'); SELECT truncate_local_data_after_distributing_table('public.pgbench_accounts');"
psql -h pg-citus0 -d test -c "SELECT create_reference_table('pgbench_branches')         ; SELECT truncate_local_data_after_distributing_table('public.pgbench_branches');"
psql -h pg-citus0 -d test -c "SELECT create_reference_table('pgbench_history')          ; SELECT truncate_local_data_after_distributing_table('public.pgbench_history');"
psql -h pg-citus0 -d test -c "SELECT create_reference_table('pgbench_tellers')          ; SELECT truncate_local_data_after_distributing_table('public.pgbench_tellers');"

将表分布出去后,你可以在其他节点上也访问到:

psql -h pg-citus1 -d test -c '\dt+'

例如,全表扫描可以发现执行计划已经变为分布式计划

vagrant@meta-1:~$ psql -h pg-citus3 -d test -c 'explain select * from pgbench_accounts'
                                               QUERY PLAN
---------------------------------------------------------------------------------------------------------
 Custom Scan (Citus Adaptive)  (cost=0.00..0.00 rows=100000 width=352)
   Task Count: 32
   Tasks Shown: One of 32
   ->  Task
         Node: host=10.10.10.52 port=5432 dbname=test
         ->  Seq Scan on pgbench_accounts_102008 pgbench_accounts  (cost=0.00..81.66 rows=3066 width=97)
(6 rows)

你可以从几个不同的主节点发起写入:

pgbench -nv -P1 -T1000 -c 2 postgres://test:test@pg-citus1/test
pgbench -nv -P1 -T1000 -c 2 postgres://test:test@pg-citus2/test
pgbench -nv -P1 -T1000 -c 2 postgres://test:test@pg-citus3/test
pgbench -nv -P1 -T1000 -c 2 postgres://test:test@pg-citus4/test

当某个节点出现故障时,Patroni 提供的原生高可用支持会将备用节点提升并自动顶上。

test=# select * from  pg_dist_node;
 nodeid | groupid |  nodename   | nodeport | noderack | hasmetadata | isactive | noderole | nodecluster | metadatasynced | shouldhaveshards
--------+---------+-------------+----------+----------+-------------+----------+----------+-------------+----------------+------------------
      1 |       0 | 10.10.10.51 |     5432 | default  | t           | t        | primary  | default     | t              | f
      2 |       2 | 10.10.10.54 |     5432 | default  | t           | t        | primary  | default     | t              | t
      5 |       1 | 10.10.10.52 |     5432 | default  | t           | t        | primary  | default     | t              | t
      3 |       4 | 10.10.10.58 |     5432 | default  | t           | t        | primary  | default     | t              | t
      4 |       3 | 10.10.10.56 |     5432 | default  | t           | t        | primary  | default     | t              | t

18.4 - Babelfish

使用 WiltonDB 与 Babelfish 创建兼容 Microsoft SQL Server 的 PostgreSQL 数据库集群!(线缆协议级仿真)

Babelfish 是一个基于 PostgreSQL 的 MSSQL(微软 SQL Server)兼容性方案,由 AWS 开源。


概览

Pigsty 允许用户使用 Babelfish 与 WiltonDB 创建 Microsoft SQL Server 兼容的 PostgreSQL 集群!

  • Babelfish :一个由 AWS 开源的 MSSQL(微软 SQL Server) 兼容性扩展插件
  • WiltonDB: 一个专注于整合 Babelfish 的 PostgreSQL 内核发行版

Babelfish 是一个 PostgreSQL 扩展插件,但只能在一个轻微修改过的 PostgreSQL 内核 Fork 上工作,WiltonDB 在 EL/Ubuntu 系统下提供了编译后的Fork内核二进制与扩展二进制软件包。

Pigsty 可以使用 WiltonDB 替代原生的 PostgreSQL 内核,提供开箱即用的 MSSQL 兼容集群。MSSQL集群使用与管理与一套标准的 PostgreSQL 15 集群并无差异,您可以使用 Pigsty 提供的所有功能,如高可用,备份,监控等。

WiltonDB 带有包括 Babelfish 在内的若干扩展插件,但不能使用 PostgreSQL 原生的扩展插件。

MSSQL 兼容集群在启动后,除了监听 PostgreSQL 默认的端口外,还会监听 MSSQL 默认的 1433 端口,并在此端口上通过 TDS WireProtocol 提供 MSSQL 服务。 您可以用任何 MSSQL 客户端连接至 Pigsty 提供的 MSSQL 服务,如 SQL Server Management Studio,或者使用 sqlcmd 命令行工具。


安装

WiltonDB 与原生 PostgreSQL 内核冲突,在一个节点上只能选择一个内核进行安装,使用以下命令在线安装 WiltonDB 内核。

./node.yml -t node_install -e '{"node_repo_modules":"local,mssql","node_packages":["wiltondb"]}'

请注意 WiltonDB 仅在 EL 与 Ubuntu 系统中可用,目前尚未提供 Debian 支持。

Pigsty 专业版提供了 WiltonDB 离线安装包,可以从本地软件源安装 WiltonDB。


配置

在安装部署 MSSQL 模块时需要特别注意以下事项:

  • WiltonDB 在 EL (7/8/9) 和 Ubuntu (20.04/22.04) 中可用,在Debian系统中不可用
  • WiltonDB 目前基于 PostgreSQL 15 编译,因此需要指定 pg_version: 15
  • 在 EL 系统上,wiltondb 的二进制默认会安装至 /usr/bin/ 目录下,而在 Ubuntu 系统上则会安装至 /usr/lib/postgresql/15/bin/ 目录下,与 PostgreSQL 官方二进制文件放置位置不同。
  • WiltonDB 兼容模式下,HBA 密码认证规则需要使用 md5,而非 scram-sha-256,因此需要覆盖 Pigsty 默认的 HBA 规则集,将 SQL Server 需要的 md5 认证规则,插入到 dbrole_readonly 通配认证规则之前
  • WiltonDB 只能针对一个首要数据库启用,同时应当指定一个用户作为 Babelfish 的超级用户,以便 Babelfish 可以创建数据库和用户,默认为 mssqldbuser_myssql,如果修改,请一并修改 files/mssql.sql 中的用户。
  • WiltonDB TDS 线缆协议兼容插件 babelfishpg_tds 需要在 shared_preload_libraries 中启用
  • WiltonDB 扩展在启用后,默认监听 MSSQL 1433 端口,您可以覆盖 Pigsty 默认的服务定义,将 primaryreplica 服务的端口指向 1433 ,而不是 5432 / 6432 端口。

以下参数需要针对 MSSQL 数据库集群进行配置:

#----------------------------------#
# PGSQL & MSSQL (Babelfish & Wilton)
#----------------------------------#
# PG Installation
node_repo_modules: local,node,mssql # add mssql and os upstream repos
pg_mode: mssql                      # Microsoft SQL Server Compatible Mode
pg_libs: 'babelfishpg_tds, pg_stat_statements, auto_explain' # add timescaledb to shared_preload_libraries
pg_version: 15                      # The current WiltonDB major version is 15
pg_packages:
  - wiltondb                        # install forked version of postgresql with babelfishpg support
  - patroni pgbouncer pgbackrest pg_exporter pgbadger vip-manager
pg_extensions: []                   # do not install any vanilla postgresql extensions

# PG Provision
pg_default_hba_rules:               # overwrite default HBA rules for babelfish cluster
- {user: '${dbsu}'    ,db: all         ,addr: local     ,auth: ident ,title: 'dbsu access via local os user ident'  }
- {user: '${dbsu}'    ,db: replication ,addr: local     ,auth: ident ,title: 'dbsu replication from local os ident' }
- {user: '${repl}'    ,db: replication ,addr: localhost ,auth: pwd   ,title: 'replicator replication from localhost'}
- {user: '${repl}'    ,db: replication ,addr: intra     ,auth: pwd   ,title: 'replicator replication from intranet' }
- {user: '${repl}'    ,db: postgres    ,addr: intra     ,auth: pwd   ,title: 'replicator postgres db from intranet' }
- {user: '${monitor}' ,db: all         ,addr: localhost ,auth: pwd   ,title: 'monitor from localhost with password' }
- {user: '${monitor}' ,db: all         ,addr: infra     ,auth: pwd   ,title: 'monitor from infra host with password'}
- {user: '${admin}'   ,db: all         ,addr: infra     ,auth: ssl   ,title: 'admin @ infra nodes with pwd & ssl'   }
- {user: '${admin}'   ,db: all         ,addr: world     ,auth: ssl   ,title: 'admin @ everywhere with ssl & pwd'    }
- {user: dbuser_mssql ,db: mssql       ,addr: intra     ,auth: md5   ,title: 'allow mssql dbsu intranet access'     } # <--- use md5 auth method for mssql user
- {user: '+dbrole_readonly',db: all    ,addr: localhost ,auth: pwd   ,title: 'pgbouncer read/write via local socket'}
- {user: '+dbrole_readonly',db: all    ,addr: intra     ,auth: pwd   ,title: 'read/write biz user via password'     }
- {user: '+dbrole_offline' ,db: all    ,addr: intra     ,auth: pwd   ,title: 'allow etl offline tasks from intranet'}
pg_default_services:                # route primary & replica service to mssql port 1433
- { name: primary ,port: 5433 ,dest: 1433  ,check: /primary   ,selector: "[]" }
- { name: replica ,port: 5434 ,dest: 1433  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
- { name: default ,port: 5436 ,dest: postgres ,check: /primary   ,selector: "[]" }
- { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]"}

您可以定义 MSSQL 业务数据库与业务用户:

#----------------------------------#
# pgsql (singleton on current node)
#----------------------------------#
# this is an example single-node postgres cluster with postgis & timescaledb installed, with one biz database & two biz users
pg-meta:
  hosts:
    10.10.10.10: { pg_seq: 1, pg_role: primary } # <---- primary instance with read-write capability
  vars:
    pg_cluster: pg-test
    pg_users:                           # create MSSQL superuser
      - {name: dbuser_mssql ,password: DBUser.MSSQL ,superuser: true, pgbouncer: true ,roles: [dbrole_admin], comment: superuser & owner for babelfish  }
    pg_primary_db: mssql                # use `mssql` as the primary sql server database
    pg_databases:
      - name: mssql
        baseline: mssql.sql             # init babelfish database & user
        extensions:
          - { name: uuid-ossp          }
          - { name: babelfishpg_common }
          - { name: babelfishpg_tsql   }
          - { name: babelfishpg_tds    }
          - { name: babelfishpg_money  }
          - { name: pg_hint_plan       }
          - { name: system_stats       }
          - { name: tds_fdw            }
        owner: dbuser_mssql
        parameters: { 'babelfishpg_tsql.migration_mode' : 'multi-db' }
        comment: babelfish cluster, a MSSQL compatible pg cluster

访问

您可以使用任何 SQL Server 兼容的客户端工具来访问这个数据库集群。

Microsoft 提供了 sqlcmd 作为官方的命令行工具。

除此之外,他们还提供了一个 Go 语言版本的命令行工具 go-sqlcmd

安装 go-sqlcmd:

curl -LO https://github.com/microsoft/go-sqlcmd/releases/download/v1.4.0/sqlcmd-v1.4.0-linux-amd64.tar.bz2
tar xjvf sqlcmd-v1.4.0-linux-amd64.tar.bz2
sudo mv sqlcmd* /usr/bin/

快速上手 go-sqlcmd

$ sqlcmd -S 10.10.10.10,1433 -U dbuser_mssql -P DBUser.MSSQL
1> select @@version
2> go
version                                                                                                                                                                                                                                                         
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Babelfish for PostgreSQL with SQL Server Compatibility - 12.0.2000.8
Oct 22 2023 17:48:32
Copyright (c) Amazon Web Services
PostgreSQL 15.4 (EL 1:15.4.wiltondb3.3_2-2.el8) on x86_64-redhat-linux-gnu (Babelfish 3.3.0)                                        

(1 row affected)

使用 Pigsty 提供的服务机制,可以使用 5433 / 5434 端口始终连接到主库/从库上的 1433 端口。

# 访问任意集群成员上的 5433 端口,指向主库上的 1433 MSSQL 端口 
sqlcmd -S 10.10.10.11,5433 -U dbuser_mssql -P DBUser.MSSQL

# 访问任意集群成员上的 5434 端口,指向任意可读库上的 1433 MSSQL 端口
sqlcmd -S 10.10.10.11,5434 -U dbuser_mssql -P DBUser.MSSQL

扩展

绝大多数 PGSQL 模块的 扩展插件(非纯 SQL 类)都无法直接在 MSSQL 模块的 WiltonDB 内核上使用,需要重新编译。

目前 WiltonDB 自带了以下扩展插件,除了 PostgreSQL Contrib 扩展,四个 BabelfishPG 核心扩展之外,还提供了 pg_hint_pantds_fdw,以及 system_stats 三个第三方扩展。

扩展名版本说明
dblink1.2connect to other PostgreSQL databases from within a database
adminpack2.1administrative functions for PostgreSQL
dict_int1.0text search dictionary template for integers
intagg1.1integer aggregator and enumerator (obsolete)
dict_xsyn1.0text search dictionary template for extended synonym processing
amcheck1.3functions for verifying relation integrity
autoinc1.0functions for autoincrementing fields
bloom1.0bloom access method - signature file based index
fuzzystrmatch1.1determine similarities and distance between strings
intarray1.5functions, operators, and index support for 1-D arrays of integers
btree_gin1.3support for indexing common datatypes in GIN
btree_gist1.7support for indexing common datatypes in GiST
hstore1.8data type for storing sets of (key, value) pairs
hstore_plperl1.0transform between hstore and plperl
isn1.2data types for international product numbering standards
hstore_plperlu1.0transform between hstore and plperlu
jsonb_plperl1.0transform between jsonb and plperl
citext1.6data type for case-insensitive character strings
jsonb_plperlu1.0transform between jsonb and plperlu
jsonb_plpython3u1.0transform between jsonb and plpython3u
cube1.5data type for multidimensional cubes
hstore_plpython3u1.0transform between hstore and plpython3u
earthdistance1.1calculate great-circle distances on the surface of the Earth
lo1.1Large Object maintenance
file_fdw1.0foreign-data wrapper for flat file access
insert_username1.0functions for tracking who changed a table
ltree1.2data type for hierarchical tree-like structures
ltree_plpython3u1.0transform between ltree and plpython3u
pg_walinspect1.0functions to inspect contents of PostgreSQL Write-Ahead Log
moddatetime1.0functions for tracking last modification time
old_snapshot1.0utilities in support of old_snapshot_threshold
pgcrypto1.3cryptographic functions
pgrowlocks1.2show row-level locking information
pageinspect1.11inspect the contents of database pages at a low level
pg_surgery1.0extension to perform surgery on a damaged relation
seg1.4data type for representing line segments or floating-point intervals
pgstattuple1.5show tuple-level statistics
pg_buffercache1.3examine the shared buffer cache
pg_freespacemap1.2examine the free space map (FSM)
postgres_fdw1.1foreign-data wrapper for remote PostgreSQL servers
pg_prewarm1.2prewarm relation data
tcn1.0Triggered change notifications
pg_trgm1.6text similarity measurement and index searching based on trigrams
xml21.1XPath querying and XSLT
refint1.0functions for implementing referential integrity (obsolete)
pg_visibility1.2examine the visibility map (VM) and page-level visibility info
pg_stat_statements1.10track planning and execution statistics of all SQL statements executed
sslinfo1.2information about SSL certificates
tablefunc1.0functions that manipulate whole tables, including crosstab
tsm_system_rows1.0TABLESAMPLE method which accepts number of rows as a limit
tsm_system_time1.0TABLESAMPLE method which accepts time in milliseconds as a limit
unaccent1.1text search dictionary that removes accents
uuid-ossp1.1generate universally unique identifiers (UUIDs)
plpgsql1.0PL/pgSQL procedural language
babelfishpg_money1.1.0babelfishpg_money
system_stats2.0EnterpriseDB system statistics for PostgreSQL
tds_fdw2.0.3Foreign data wrapper for querying a TDS database (Sybase or Microsoft SQL Server)
babelfishpg_common3.3.3Transact SQL Datatype Support
babelfishpg_tds1.0.0TDS protocol extension
pg_hint_plan1.5.1
babelfishpg_tsql3.3.1Transact SQL compatibility
  • Pigsty 专业版提供离线安装 MSSQL 兼容模块的能力
  • Pigsty 专业版 提供可选的 MSSQL 兼容内核扩展移植定制服务,可以将 PGSQL 模块中可用的 扩展 移植到 MSSQL 集群中。

18.5 - IvorySQL

使用瀚高开源的 IvorySQL 内核,基于 PostgreSQL 集群实现 Oracle 语法/PLSQL 兼容性。

IvorySQL 是一个开源的,旨在基于 PG 提供 “Oracle兼容性” 的 PostgreSQL 内核分支。


概览

IvorySQL 内核支持在 Pigsty 开源版本中提供,您的服务器需要互联网访问,直接从 IvorySQL 的官方仓库下载相关软件包。

请注意,直接将 IvorySQL 加入 Pigsty 默认软件仓库中会影响原生 PostgreSQL 内核的安装。Pigsty 专业版提供包括 IvorySQL 内核在内的离线安装解决方案。

当前 IvorySQL 的最新版本为 5.0,对应的 PostgreSQL 版本为 18。请注意,IvorySQL 当前仅在 EL8/EL9 上可用。

最后一个支持 EL7 的 IvorySQL 版本为 3.3,对应 PostgreSQL 16.3;最后一个基于 PostgreSQL 17 的版本为 IvorySQL 4.4


安装

如果您的环境有互联网访问,您可以使用以下方式,直接将 IvorySQL 仓库加入到节点上,然后执行 PGSQL 剧本进行安装

./node.yml -t node_repo -e '{"node_repo_modules":"local,node,pgsql,ivory"}'

配置

以下参数需要针对 IvorySQL 数据库集群进行配置:

#----------------------------------#
# Ivory SQL Configuration
#----------------------------------#
node_repo_modules: local,node,pgsql,ivory  # add ivorysql upstream repo
pg_mode: ivory                    # IvorySQL Oracle Compatible Mode
pg_packages: [ 'ivorysql patroni pgbouncer pgbackrest pg_exporter pgbadger vip-manager' ]
pg_libs: 'liboracle_parser, pg_stat_statements, auto_explain'
pg_extensions: [ ]                # do not install any vanilla postgresql extensions

使用 Oracle 兼容性模式时,需要动态加载 liboracle_parser 扩展插件。


客户端访问

IvorySQL 等效于 PostgreSQL 16,任何兼容 PostgreSQL 线缆协议的客户端工具都可以访问 IvorySQL 集群。


扩展列表

绝大多数 PGSQL 模块的 扩展插件 (非纯 SQL 类)都无法直接在 IvorySQL 内核上使用,如果需要使用,请针对新内核从源码重新编译安装。

目前 IvorySQL 内核自带了以下 101 个扩展插件。

nameversioncomment
hstore_plperl1.0transform between hstore and plperl
plisql1.0PL/iSQL procedural language
hstore_plperlu1.0transform between hstore and plperlu
adminpack2.1administrative functions for PostgreSQL
insert_username1.0functions for tracking who changed a table
dblink1.2connect to other PostgreSQL databases from within a database
dict_int1.0text search dictionary template for integers
amcheck1.3functions for verifying relation integrity
intagg1.1integer aggregator and enumerator (obsolete)
autoinc1.0functions for autoincrementing fields
bloom1.0bloom access method - signature file based index
dict_xsyn1.0text search dictionary template for extended synonym processing
btree_gin1.3support for indexing common datatypes in GIN
earthdistance1.1calculate great-circle distances on the surface of the Earth
file_fdw1.0foreign-data wrapper for flat file access
fuzzystrmatch1.2determine similarities and distance between strings
btree_gist1.7support for indexing common datatypes in GiST
intarray1.5functions, operators, and index support for 1-D arrays of integers
citext1.6data type for case-insensitive character strings
isn1.2data types for international product numbering standards
ivorysql_ora1.0Oracle Compatible extenison on Postgres Database
jsonb_plperl1.0transform between jsonb and plperl
cube1.5data type for multidimensional cubes
dummy_index_am1.0dummy_index_am - index access method template
dummy_seclabel1.0Test code for SECURITY LABEL feature
hstore1.8data type for storing sets of (key, value) pairs
jsonb_plperlu1.0transform between jsonb and plperlu
lo1.1Large Object maintenance
ltree1.2data type for hierarchical tree-like structures
moddatetime1.0functions for tracking last modification time
old_snapshot1.0utilities in support of old_snapshot_threshold
ora_btree_gin1.0support for indexing oracle datatypes in GIN
pg_trgm1.6text similarity measurement and index searching based on trigrams
ora_btree_gist1.0support for oracle indexing common datatypes in GiST
pg_visibility1.2examine the visibility map (VM) and page-level visibility info
pg_walinspect1.1functions to inspect contents of PostgreSQL Write-Ahead Log
pgcrypto1.3cryptographic functions
pgstattuple1.5show tuple-level statistics
pageinspect1.12inspect the contents of database pages at a low level
pgrowlocks1.2show row-level locking information
pg_buffercache1.4examine the shared buffer cache
pg_stat_statements1.10track planning and execution statistics of all SQL statements executed
pg_freespacemap1.2examine the free space map (FSM)
plsample1.0PL/Sample
pg_prewarm1.2prewarm relation data
pg_surgery1.0extension to perform surgery on a damaged relation
seg1.4data type for representing line segments or floating-point intervals
postgres_fdw1.1foreign-data wrapper for remote PostgreSQL servers
refint1.0functions for implementing referential integrity (obsolete)
test_ext_req_schema11.0Required extension to be referenced
spgist_name_ops1.0Test opclass for SP-GiST
test_ext_req_schema21.0Test schema referencing of required extensions
test_shm_mq1.0Test code for shared memory message queues
sslinfo1.2information about SSL certificates
test_slru1.0Test code for SLRU
tablefunc1.0functions that manipulate whole tables, including crosstab
bool_plperl1.0transform between bool and plperl
tcn1.0Triggered change notifications
test_ext_req_schema31.0Test schema referencing of 2 required extensions
test_bloomfilter1.0Test code for Bloom filter library
test_copy_callbacks1.0Test code for COPY callbacks
test_ginpostinglist1.0Test code for ginpostinglist.c
test_custom_rmgrs1.0Test code for custom WAL resource managers
test_integerset1.0Test code for integerset
test_ddl_deparse1.0Test code for DDL deparse feature
tsm_system_rows1.0TABLESAMPLE method which accepts number of rows as a limit
test_ext11.0Test extension 1
tsm_system_time1.0TABLESAMPLE method which accepts time in milliseconds as a limit
test_ext21.0Test extension 2
unaccent1.1text search dictionary that removes accents
test_ext31.0Test extension 3
test_ext41.0Test extension 4
uuid-ossp1.1generate universally unique identifiers (UUIDs)
test_ext51.0Test extension 5
worker_spi1.0Sample background worker
test_ext61.0test_ext6
test_lfind1.0Test code for optimized linear search functions
xml21.1XPath querying and XSLT
test_ext71.0Test extension 7
plpgsql1.0PL/pgSQL procedural language
test_ext81.0Test extension 8
test_parser1.0example of a custom parser for full-text search
test_pg_dump1.0Test pg_dump with an extension
test_ext_cine1.0Test extension using CREATE IF NOT EXISTS
test_predtest1.0Test code for optimizer/util/predtest.c
test_ext_cor1.0Test extension using CREATE OR REPLACE
test_rbtree1.0Test code for red-black tree library
test_ext_cyclic11.0Test extension cyclic 1
test_ext_cyclic21.0Test extension cyclic 2
test_ext_extschema1.0test @extschema@
test_regex1.0Test code for backend/regex/
test_ext_evttrig1.0Test extension - event trigger
bool_plperlu1.0transform between bool and plperlu
plperl1.0PL/Perl procedural language
plperlu1.0PL/PerlU untrusted procedural language
hstore_plpython3u1.0transform between hstore and plpython3u
jsonb_plpython3u1.0transform between jsonb and plpython3u
ltree_plpython3u1.0transform between ltree and plpython3u
plpython3u1.0PL/Python3U untrusted procedural language
pltcl1.0PL/Tcl procedural language
pltclu1.0PL/TclU untrusted procedural language

请注意,Pigsty 不对使用 IvorySQL 内核承担任何质保责任,使用此内核遇到的任何问题与需求请联系原厂解决。

18.6 - PolarDB PG

使用阿里云开源的 PolarDB for PostgreSQL 内核提供国产信创资质支持,与类似 Oracle RAC 的使用体验。

概览

Pigsty 允许使用 PolarDB 创建带有 “国产化信创资质” 的 PostgreSQL 集群!

PolarDB for PostgreSQL 基本等效于 PostgreSQL 15,任何兼容 PostgreSQL 线缆协议的客户端工具都可以访问 PolarDB 集群。

Pigsty 的 PGSQL 仓库中提供了 EL7 / EL8 的 PolarDB PG 开源版安装包,但不会在 Pigsty 安装时下载到本地软件仓库。

如果您需要 PolarDB PG 的离线安装支持,请考虑我们的 专业订阅服务


安装

如果您的环境有互联网访问,您可以使用以下方式,直接将 Pigsty PGSQL 及依赖仓库加入到节点上,

node_repo_modules: local,node,pgsql

然后在 pg_packages 中,使用 polardb 替换原生的 postgresql 软件包。


配置

以下参数需要针对 PolarDB 数据库集群进行特殊配置:

#----------------------------------#
# PGSQL & PolarDB
#----------------------------------#
pg_version: 15
pg_packages: [ 'polardb patroni pgbouncer pgbackrest pg_exporter pgbadger vip-manager' ]
pg_extensions: [ ]                # do not install any vanilla postgresql extensions
pg_mode: polar                    # PolarDB Compatible Mode
pg_default_roles:                 # default roles and users in postgres cluster
  - { name: dbrole_readonly  ,login: false ,comment: role for global read-only access     }
  - { name: dbrole_offline   ,login: false ,comment: role for restricted read-only access }
  - { name: dbrole_readwrite ,login: false ,roles: [dbrole_readonly] ,comment: role for global read-write access }
  - { name: dbrole_admin     ,login: false ,roles: [pg_monitor, dbrole_readwrite] ,comment: role for object creation }
  - { name: postgres     ,superuser: true  ,comment: system superuser }
  - { name: replicator   ,superuser: true  ,replication: true ,roles: [pg_monitor, dbrole_readonly] ,comment: system replicator } # <- superuser is required for replication
  - { name: dbuser_dba   ,superuser: true  ,roles: [dbrole_admin]  ,pgbouncer: true ,pool_mode: session, pool_connlimit: 16 ,comment: pgsql admin user }
  - { name: dbuser_monitor ,roles: [pg_monitor] ,pgbouncer: true ,parameters: {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment: pgsql monitor user }

这里特别注意,PolarDB PG 要求 replicator 复制用户为 Superuser,与原生 PG 不同。


扩展列表

绝大多数 PGSQL 模块的 扩展插件 (非纯 SQL 类)都无法直接在 PolarDB 内核上使用,如果需要使用,请针对新内核从源码重新编译安装。

目前 PolarDB 内核自带了以下 61 个扩展插件,除去 Contrib 扩展外,提供的额外扩展包括:

  • polar_csn 1.0 : polar_csn
  • polar_monitor 1.2 : examine the polardb information
  • polar_monitor_preload 1.1 : examine the polardb information
  • polar_parameter_check 1.0 : kernel extension for parameter validation
  • polar_px 1.0 : Parallel Execution extension
  • polar_stat_env 1.0 : env stat functions for PolarDB
  • polar_stat_sql 1.3 : Kernel statistics gathering, and sql plan nodes information gathering
  • polar_tde_utils 1.0 : Internal extension for TDE
  • polar_vfs 1.0 : polar_vfs
  • polar_worker 1.0 : polar_worker
  • timetravel 1.0 : functions for implementing time travel
  • vector 0.5.1 : vector data type and ivfflat and hnsw access methods
  • smlar 1.0 : compute similary of any one-dimensional arrays

PolarDB 可用的完整插件列表:

nameversioncomment
hstore_plpython2u1.0transform between hstore and plpython2u
dict_int1.0text search dictionary template for integers
adminpack2.0administrative functions for PostgreSQL
hstore_plpython3u1.0transform between hstore and plpython3u
amcheck1.1functions for verifying relation integrity
hstore_plpythonu1.0transform between hstore and plpythonu
autoinc1.0functions for autoincrementing fields
insert_username1.0functions for tracking who changed a table
bloom1.0bloom access method - signature file based index
file_fdw1.0foreign-data wrapper for flat file access
dblink1.2connect to other PostgreSQL databases from within a database
btree_gin1.3support for indexing common datatypes in GIN
fuzzystrmatch1.1determine similarities and distance between strings
lo1.1Large Object maintenance
intagg1.1integer aggregator and enumerator (obsolete)
btree_gist1.5support for indexing common datatypes in GiST
hstore1.5data type for storing sets of (key, value) pairs
intarray1.2functions, operators, and index support for 1-D arrays of integers
citext1.5data type for case-insensitive character strings
cube1.4data type for multidimensional cubes
hstore_plperl1.0transform between hstore and plperl
isn1.2data types for international product numbering standards
jsonb_plperl1.0transform between jsonb and plperl
dict_xsyn1.0text search dictionary template for extended synonym processing
hstore_plperlu1.0transform between hstore and plperlu
earthdistance1.1calculate great-circle distances on the surface of the Earth
pg_prewarm1.2prewarm relation data
jsonb_plperlu1.0transform between jsonb and plperlu
pg_stat_statements1.6track execution statistics of all SQL statements executed
jsonb_plpython2u1.0transform between jsonb and plpython2u
jsonb_plpython3u1.0transform between jsonb and plpython3u
jsonb_plpythonu1.0transform between jsonb and plpythonu
pg_trgm1.4text similarity measurement and index searching based on trigrams
pgstattuple1.5show tuple-level statistics
ltree1.1data type for hierarchical tree-like structures
ltree_plpython2u1.0transform between ltree and plpython2u
pg_visibility1.2examine the visibility map (VM) and page-level visibility info
ltree_plpython3u1.0transform between ltree and plpython3u
ltree_plpythonu1.0transform between ltree and plpythonu
seg1.3data type for representing line segments or floating-point intervals
moddatetime1.0functions for tracking last modification time
pgcrypto1.3cryptographic functions
pgrowlocks1.2show row-level locking information
pageinspect1.7inspect the contents of database pages at a low level
pg_buffercache1.3examine the shared buffer cache
pg_freespacemap1.2examine the free space map (FSM)
tcn1.0Triggered change notifications
plperl1.0PL/Perl procedural language
uuid-ossp1.1generate universally unique identifiers (UUIDs)
plperlu1.0PL/PerlU untrusted procedural language
refint1.0functions for implementing referential integrity (obsolete)
xml21.1XPath querying and XSLT
plpgsql1.0PL/pgSQL procedural language
plpython3u1.0PL/Python3U untrusted procedural language
pltcl1.0PL/Tcl procedural language
pltclu1.0PL/TclU untrusted procedural language
polar_csn1.0polar_csn
sslinfo1.2information about SSL certificates
polar_monitor1.2examine the polardb information
polar_monitor_preload1.1examine the polardb information
polar_parameter_check1.0kernel extension for parameter validation
polar_px1.0Parallel Execution extension
tablefunc1.0functions that manipulate whole tables, including crosstab
polar_stat_env1.0env stat functions for PolarDB
smlar1.0compute similary of any one-dimensional arrays
timetravel1.0functions for implementing time travel
tsm_system_rows1.0TABLESAMPLE method which accepts number of rows as a limit
polar_stat_sql1.3Kernel statistics gathering, and sql plan nodes information gathering
tsm_system_time1.0TABLESAMPLE method which accepts time in milliseconds as a limit
polar_tde_utils1.0Internal extension for TDE
polar_vfs1.0polar_vfs
polar_worker1.0polar_worker
unaccent1.1text search dictionary that removes accents
postgres_fdw1.0foreign-data wrapper for remote PostgreSQL servers
  • Pigsty 专业版提供 PolarDB 离线安装支持,扩展插件编译支持,以及针对 PolarDB 集群进行专门适配的监控与管控支持。
  • Pigsty 与阿里云内核团队有合作,可以提供有偿内核兜底支持服务。

18.7 - PolarDB Oracle

使用阿里云商业版本的 PolarDB for Oracle 内核(闭源,PG14,仅在特殊企业版定制中可用)

Pigsty 允许使用 PolarDB 创建带有 “国产化信创资质” 的 PolarDB for Oracle 集群!

根据 【安全可靠测评结果公告(2023年第1号)】,附表三、集中式数据库。PolarDB v2.0 属于自主可控,安全可靠的国产信创数据库。

PolarDB for Oracle 是基于 PolarDB for PostgreSQL 进行二次开发的 Oracle 兼容版本,两者共用同一套内核,通过 --compatibility-mode 参数进行区分。

我们与阿里云内核团队合作,提供基于 PolarDB v2.0 内核与 Pigsty v3.0 RDS 的完整数据库解决方案,请联系销售咨询,或在阿里云市场自行采购。

PolarDB for Oracle 内核目前仅在 EL 系统中可用。


扩展

目前 PolarDB 2.0 (Oracle兼容) 内核自带了以下 188 个扩展插件:

namedefault_versioncomment
cube1.5data type for multidimensional cubes
ip4r2.4NULL
adminpack2.1administrative functions for PostgreSQL
dict_xsyn1.0text search dictionary template for extended synonym processing
amcheck1.4functions for verifying relation integrity
autoinc1.0functions for autoincrementing fields
hstore1.8data type for storing sets of (key, value) pairs
bloom1.0bloom access method - signature file based index
earthdistance1.1calculate great-circle distances on the surface of the Earth
hstore_plperl1.0transform between hstore and plperl
bool_plperl1.0transform between bool and plperl
file_fdw1.0foreign-data wrapper for flat file access
bool_plperlu1.0transform between bool and plperlu
fuzzystrmatch1.1determine similarities and distance between strings
hstore_plperlu1.0transform between hstore and plperlu
btree_gin1.3support for indexing common datatypes in GIN
hstore_plpython2u1.0transform between hstore and plpython2u
btree_gist1.6support for indexing common datatypes in GiST
hll2.17type for storing hyperloglog data
hstore_plpython3u1.0transform between hstore and plpython3u
citext1.6data type for case-insensitive character strings
hstore_plpythonu1.0transform between hstore and plpythonu
hypopg1.3.1Hypothetical indexes for PostgreSQL
insert_username1.0functions for tracking who changed a table
dblink1.2connect to other PostgreSQL databases from within a database
decoderbufs0.1.0Logical decoding plugin that delivers WAL stream changes using a Protocol Buffer format
intagg1.1integer aggregator and enumerator (obsolete)
dict_int1.0text search dictionary template for integers
intarray1.5functions, operators, and index support for 1-D arrays of integers
isn1.2data types for international product numbering standards
jsonb_plperl1.0transform between jsonb and plperl
jsonb_plperlu1.0transform between jsonb and plperlu
jsonb_plpython2u1.0transform between jsonb and plpython2u
jsonb_plpython3u1.0transform between jsonb and plpython3u
jsonb_plpythonu1.0transform between jsonb and plpythonu
lo1.1Large Object maintenance
log_fdw1.0foreign-data wrapper for csvlog
ltree1.2data type for hierarchical tree-like structures
ltree_plpython2u1.0transform between ltree and plpython2u
ltree_plpython3u1.0transform between ltree and plpython3u
ltree_plpythonu1.0transform between ltree and plpythonu
moddatetime1.0functions for tracking last modification time
old_snapshot1.0utilities in support of old_snapshot_threshold
oracle_fdw1.2foreign data wrapper for Oracle access
oss_fdw1.1foreign-data wrapper for OSS access
pageinspect2.1inspect the contents of database pages at a low level
pase0.0.1ant ai similarity search
pg_bigm1.2text similarity measurement and index searching based on bigrams
pg_freespacemap1.2examine the free space map (FSM)
pg_hint_plan1.4controls execution plan with hinting phrases in comment of special form
pg_buffercache1.5examine the shared buffer cache
pg_prewarm1.2prewarm relation data
pg_repack1.4.8-1Reorganize tables in PostgreSQL databases with minimal locks
pg_sphere1.0spherical objects with useful functions, operators and index support
pg_cron1.5Job scheduler for PostgreSQL
pg_jieba1.1.0a parser for full-text search of Chinese
pg_stat_kcache2.2.1Kernel statistics gathering
pg_stat_statements1.9track planning and execution statistics of all SQL statements executed
pg_surgery1.0extension to perform surgery on a damaged relation
pg_trgm1.6text similarity measurement and index searching based on trigrams
pg_visibility1.2examine the visibility map (VM) and page-level visibility info
pg_wait_sampling1.1sampling based statistics of wait events
pgaudit1.6.2provides auditing functionality
pgcrypto1.3cryptographic functions
pgrowlocks1.2show row-level locking information
pgstattuple1.5show tuple-level statistics
pgtap1.2.0Unit testing for PostgreSQL
pldbgapi1.1server-side support for debugging PL/pgSQL functions
plperl1.0PL/Perl procedural language
plperlu1.0PL/PerlU untrusted procedural language
plpgsql1.0PL/pgSQL procedural language
plpython2u1.0PL/Python2U untrusted procedural language
plpythonu1.0PL/PythonU untrusted procedural language
plsql1.0Oracle compatible PL/SQL procedural language
pltcl1.0PL/Tcl procedural language
pltclu1.0PL/TclU untrusted procedural language
polar_bfile1.0The BFILE data type enables access to binary file LOBs that are stored in file systems outside Database
polar_bpe1.0polar_bpe
polar_builtin_cast1.1Internal extension for builtin casts
polar_builtin_funcs2.0implement polar builtin functions
polar_builtin_type1.5polar_builtin_type for PolarDB
polar_builtin_view1.5polar_builtin_view
polar_catalog1.2polardb pg extend catalog
polar_channel1.0polar_channel
polar_constraint1.0polar_constraint
polar_csn1.0polar_csn
polar_dba_views1.0polar_dba_views
polar_dbms_alert1.2implement polar_dbms_alert - supports asynchronous notification of database events.
polar_dbms_application_info1.0implement polar_dbms_application_info - record names of executing modules or transactions in the database.
polar_dbms_pipe1.1implements polar_dbms_pipe - package lets two or more sessions in the same instance communicate.
polar_dbms_aq1.2implement dbms_aq - provides an interface to Advanced Queuing.
polar_dbms_lob1.3implement dbms_lob - provides subprograms to operate on BLOBs, CLOBs, and NCLOBs.
polar_dbms_output1.2implement polar_dbms_output - enables you to send messages from stored procedures.
polar_dbms_lock1.0implement polar_dbms_lock - provides an interface to Oracle Lock Management services.
polar_dbms_aqadm1.3polar_dbms_aqadm - procedures to manage Advanced Queuing configuration and administration information.
polar_dbms_assert1.0implement polar_dbms_assert - provide an interface to validate properties of the input value.
polar_dbms_metadata1.0implement polar_dbms_metadata - provides a way for you to retrieve metadata from the database dictionary.
polar_dbms_random1.0implement polar_dbms_random - a built-in random number generator, not intended for cryptography
polar_dbms_crypto1.1implement dbms_crypto - provides an interface to encrypt and decrypt stored data.
polar_dbms_redact1.0implement polar_dbms_redact - provides an interface to mask data from queries by an application.
polar_dbms_debug1.1server-side support for debugging PL/SQL functions
polar_dbms_job1.0polar_dbms_job
polar_dbms_mview1.1implement polar_dbms_mview - enables to refresh materialized views.
polar_dbms_job_preload1.0polar_dbms_job_preload
polar_dbms_obfuscation_toolkit1.1implement polar_dbms_obfuscation_toolkit - enables an application to get data md5.
polar_dbms_rls1.1implement polar_dbms_rls - a fine-grained access control administrative built-in package
polar_multi_toast_utils1.0polar_multi_toast_utils
polar_dbms_session1.2implement polar_dbms_session - support to set preferences and security levels.
polar_odciconst1.0implement ODCIConst - Provide some built-in constants in Oracle.
polar_dbms_sql1.2implement polar_dbms_sql - provides an interface to execute dynamic SQL.
polar_osfs_toolkit1.0osfs library tools and functions extension
polar_dbms_stats14.0stabilize plans by fixing statistics
polar_monitor1.5monitor functions for PolarDB
polar_osfs_utils1.0osfs library utils extension
polar_dbms_utility1.3implement polar_dbms_utility - provides various utility subprograms.
polar_parameter_check1.0kernel extension for parameter validation
polar_dbms_xmldom1.0implement dbms_xmldom and dbms_xmlparser - support standard DOM interface and xml parser object
polar_parameter_manager1.1Extension to select parameters for manger.
polar_faults1.0.0simulate some database faults for end user or testing system.
polar_monitor_preload1.1examine the polardb information
polar_proxy_utils1.0Extension to provide operations about proxy.
polar_feature_utils1.2PolarDB feature utilization
polar_global_awr1.0PolarDB Global AWR Report
polar_publication1.0support polardb pg logical replication
polar_global_cache1.0polar_global_cache
polar_px1.0Parallel Execution extension
polar_serverless1.0polar serverless extension
polar_resource_manager1.0a background process that forcibly frees user session process memory
polar_sys_context1.1implement polar_sys_context - returns the value of parameter associated with the context namespace at the current instant.
polar_gpc1.3polar_gpc
polar_tde_utils1.0Internal extension for TDE
polar_gtt1.1polar_gtt
polar_utl_encode1.2implement polar_utl_encode - provides functions that encode RAW data into a standard encoded format
polar_htap1.1extension for PolarDB HTAP
polar_htap_db1.0extension for PolarDB HTAP database level operation
polar_io_stat1.0polar io stat in multi dimension
polar_utl_file1.0implement utl_file - support PL/SQL programs can read and write operating system text files
polar_ivm1.0polar_ivm
polar_sql_mapping1.2Record error sqls and mapping them to correct one
polar_stat_sql1.0Kernel statistics gathering, and sql plan nodes information gathering
tds_fdw2.0.2Foreign data wrapper for querying a TDS database (Sybase or Microsoft SQL Server)
xml21.1XPath querying and XSLT
polar_upgrade_catalogs1.1Upgrade catalogs for old version instance
polar_utl_i18n1.1polar_utl_i18n
polar_utl_raw1.0implement utl_raw - provides SQL functions for manipulating RAW datatypes.
timescaledb2.9.2Enables scalable inserts and complex queries for time-series data
polar_vfs1.0polar virtual file system for different storage
polar_worker1.0polar_worker
postgres_fdw1.1foreign-data wrapper for remote PostgreSQL servers
refint1.0functions for implementing referential integrity (obsolete)
roaringbitmap0.5support for Roaring Bitmaps
tsm_system_time1.0TABLESAMPLE method which accepts time in milliseconds as a limit
vector0.5.0vector data type and ivfflat and hnsw access methods
rum1.3RUM index access method
unaccent1.1text search dictionary that removes accents
seg1.4data type for representing line segments or floating-point intervals
sequential_uuids1.0.2generator of sequential UUIDs
uuid-ossp1.1generate universally unique identifiers (UUIDs)
smlar1.0compute similary of any one-dimensional arrays
varbitx1.1varbit functions pack
sslinfo1.2information about SSL certificates
tablefunc1.0functions that manipulate whole tables, including crosstab
tcn1.0Triggered change notifications
zhparser1.0a parser for full-text search of Chinese
address_standardizer3.3.2Ganos PostGIS address standardizer
address_standardizer_data_us3.3.2Ganos PostGIS address standardizer data us
ganos_fdw6.0Ganos Spatial FDW extension for POLARDB
ganos_geometry6.0Ganos geometry lite extension for POLARDB
ganos_geometry_pyramid6.0Ganos Geometry Pyramid extension for POLARDB
ganos_geometry_sfcgal6.0Ganos geometry lite sfcgal extension for POLARDB
ganos_geomgrid6.0Ganos geometry grid extension for POLARDB
ganos_importer6.0Ganos Spatial importer extension for POLARDB
ganos_networking6.0Ganos networking
ganos_pointcloud6.0Ganos pointcloud extension For POLARDB
ganos_pointcloud_geometry6.0Ganos_pointcloud LIDAR data and ganos_geometry data for POLARDB
ganos_raster6.0Ganos raster extension for POLARDB
ganos_scene6.0Ganos scene extension for POLARDB
ganos_sfmesh6.0Ganos surface mesh extension for POLARDB
ganos_spatialref6.0Ganos spatial reference extension for POLARDB
ganos_trajectory6.0Ganos trajectory extension for POLARDB
ganos_vomesh6.0Ganos volumn mesh extension for POLARDB
postgis_tiger_geocoder3.3.2Ganos PostGIS tiger geocoder
postgis_topology3.3.2Ganos PostGIS topology

18.8 - Percona

支持 TDE 透明加密的 Percona Postgres 发行版

Percona Postgres 是一个带有 pg_tde(透明数据加密)扩展的补丁 Postgres 内核。

它与 PostgreSQL 18.1 兼容,在所有 Pigsty 支持的平台上都可用。


快速开始

使用 Pigsty 标准安装流程,配合 pgtde 配置模板。

curl -fsSL https://repo.pigsty.io/get | bash; cd ~/pigsty;
./configure -c pgtde     # 使用 percona postgres 内核
./deploy.yml             # 使用 pigsty 设置一切

配置

需要调整以下参数来部署 Percona 集群:

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  }
    pg_databases:
      - name: meta
        baseline: cmdb.sql
        comment: pigsty tde database
        schemas: [pigsty]
        extensions: [ vector, postgis, pg_tde ,pgaudit, { name: pg_stat_monitor, schema: monitor } ]
    pg_hba_rules:
      - { user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes' }
    node_crontab: [ '00 01 * * * postgres /pg/bin/pg-backup full' ] # 每天凌晨 1 点进行全量备份

    # Percona PostgreSQL TDE 临时设置
    pg_packages: [ percona-main, pgsql-common ]  # 安装 percona postgres 包
    pg_libs: 'pg_tde, pgaudit, pg_stat_statements, pg_stat_monitor, auto_explain'

扩展

Percona 提供了 80 个可用的扩展,包括 pg_tde, pgvector, postgis, pgaudit, set_user, pg_stat_monitor 等实用三方扩展。

扩展名版本说明
pg_tde2.1Percona 透明数据加密访问方法
vector0.8.1向量数据类型及 ivfflat 和 hnsw 访问方法
postgis3.5.4PostGIS 几何和地理空间类型及函数
pgaudit18.0提供审计功能
pg_stat_monitor2.3PostgreSQL 查询性能监控工具
set_user4.2.0类似 SET ROLE 但带有额外日志记录
pg_repack1.5.3以最小锁定重组 PostgreSQL 数据库中的表
hstore1.8用于存储(键,值)对集合的数据类型
ltree1.3用于层次树状结构的数据类型
pg_trgm1.6基于三元组的文本相似度测量和索引搜索

完整的 80 个扩展列表请参考 Percona Postgres 官方文档


关键特性

  • 透明数据加密:使用 pg_tde 扩展提供静态数据加密
  • PostgreSQL 18 兼容:基于最新 PostgreSQL 18 版本
  • 企业级扩展:包含 pgaudit、pg_stat_monitor 等企业级功能
  • 完整生态:支持 pgvector、PostGIS 等流行扩展

注意:目前处于稳定阶段 - 在生产使用前请彻底评估。

18.9 - PostgresML

如何使用 Pigsty 部署 PostgresML,在数据库内进行机器学习、模型训练、推理、Embedding 与 RAG。

PostgresML 是一个 PostgreSQL 扩展,支持最新的大语言模型(LLM)、向量操作、经典机器学习以及传统的 Postgres 应用负载。

PostgresML (pgml) 是一个用 Rust 编写的 PostgreSQL 扩展。您可以运行独立的 Docker 镜像,但本文档不是 docker-compose 模板介绍,仅供参考。

PostgresML 官方支持 Ubuntu 22.04,但我们也为 EL 8/9 维护了 RPM 版本,如果您不需要 CUDA 和 NVIDIA 相关功能的话。

您需要在数据库节点上能够访问互联网,以便从 PyPI 下载 Python 依赖,并从 HuggingFace 下载模型。


配置

PostgresML 是一个用 Rust 编写的扩展,官方支持 Ubuntu。Pigsty 在 EL8 和 EL9 上维护了 PostgresML 的 RPM 版本。

创建新集群

PostgresML 2.7.9 可用于 PostgreSQL 15,支持 Ubuntu 22.04(官方)、Debian 12 和 EL 8/9(Pigsty 维护)。要启用 pgml,首先需要安装扩展:

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 }
    pg_databases:
      - { name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty] ,extensions: [{name: postgis, schema: public}, {name: timescaledb}]}
    pg_hba_rules:
      - {user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes'}
    pg_libs: 'pgml, pg_stat_statements, auto_explain'
    pg_extensions: [ 'pgml_15 pgvector_15 wal2json_15 repack_15' ]  # ubuntu
    #pg_extensions: [ 'postgresql-pgml-15 postgresql-15-pgvector postgresql-15-wal2json postgresql-15-repack' ]  # ubuntu

在 EL 8/9 中,扩展名为 pgml_15,对应的 Ubuntu/Debian 名称为 postgresql-pgml-15。同时需要将 pgml 添加到 pg_libs 中。

在现有集群上启用

要在现有集群上启用 pgml,可以使用 Ansible 的 package 模块安装:

ansible pg-meta -m package -b -a 'name=pgml_15'
# ansible el8,el9 -m package -b -a 'name=pgml_15'           # EL 8/9
# ansible u22 -m package -b -a 'name=postgresql-pgml-15'    # Ubuntu 22.04 jammy

Python 依赖

您还需要在集群节点上安装 PostgresML 的 Python 依赖。官方教程:安装指南

安装 Python 和 PIP

确保已安装 python3pipvenv

# Ubuntu 22.04 (python3.10),需要使用 apt 安装 pip 和 venv
sudo apt install -y python3 python3-pip python3-venv

对于 EL 8 / EL9 及兼容发行版,可以使用 python3.11:

# EL 8/9,可以升级默认的 pip 和 virtualenv
sudo yum install -y python3.11 python3.11-pip       # 安装最新的 python3.11
python3.11 -m pip install --upgrade pip virtualenv  # 在 EL8 / EL9 上使用 python3.11
使用 PyPI 镜像

对于中国大陆用户,建议使用清华大学 PyPI 镜像

pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple    # 设置全局镜像(推荐)
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-package        # 单次安装时使用

安装依赖包

创建 Python 虚拟环境,并使用 piprequirements.txtrequirements-xformers.txt 安装依赖。

如果您使用的是 EL 8/9,需要将以下命令中的 python3 替换为 python3.11

su - postgres;                          # 使用数据库超级用户创建虚拟环境
mkdir -p /data/pgml; cd /data/pgml;     # 创建虚拟环境目录
python3    -m venv /data/pgml           # 创建虚拟环境目录(Ubuntu 22.04)
source /data/pgml/bin/activate          # 激活虚拟环境

# 写入 Python 依赖并使用 pip 安装
cat > /data/pgml/requirments.txt <<EOF
accelerate==0.22.0
auto-gptq==0.4.2
bitsandbytes==0.41.1
catboost==1.2
ctransformers==0.2.27
datasets==2.14.5
deepspeed==0.10.3
huggingface-hub==0.17.1
InstructorEmbedding==1.0.1
lightgbm==4.1.0
orjson==3.9.7
pandas==2.1.0
rich==13.5.2
rouge==1.0.1
sacrebleu==2.3.1
sacremoses==0.0.53
scikit-learn==1.3.0
sentencepiece==0.1.99
sentence-transformers==2.2.2
tokenizers==0.13.3
torch==2.0.1
torchaudio==2.0.2
torchvision==0.15.2
tqdm==4.66.1
transformers==4.33.1
xgboost==2.0.0
langchain==0.0.287
einops==0.6.1
pynvml==11.5.0
EOF

# 在虚拟环境中使用 pip 安装依赖
python3 -m pip install -r /data/pgml/requirments.txt
python3 -m pip install xformers==0.0.21 --no-dependencies

# 此外,有 3 个 Python 包需要使用 sudo 全局安装!
sudo python3 -m pip install xgboost lightgbm scikit-learn

启用 PostgresML

在所有集群节点上安装 pgml 扩展和 Python 依赖后,就可以在 PostgreSQL 集群上启用 pgml 了。

使用 patronictl 命令 配置集群,将 pgml 添加到 shared_preload_libraries,并在 pgml.venv 中指定您的虚拟环境目录:

shared_preload_libraries: pgml, timescaledb, pg_stat_statements, auto_explain
pgml.venv: '/data/pgml'

然后重启数据库集群,并使用 SQL 命令创建扩展:

CREATE EXTENSION vector;        -- 建议同时安装 pgvector!
CREATE EXTENSION pgml;          -- 在当前数据库中创建 PostgresML
SELECT pgml.version();          -- 打印 PostgresML 版本信息

如果一切正常,您应该会看到类似以下输出:

# create extension pgml;
INFO:  Python version: 3.11.2 (main, Oct  5 2023, 16:06:03) [GCC 8.5.0 20210514 (Red Hat 8.5.0-18)]
INFO:  Scikit-learn 1.3.0, XGBoost 2.0.0, LightGBM 4.1.0, NumPy 1.26.1
CREATE EXTENSION

# SELECT pgml.version(); -- 打印 PostgresML 版本信息
 version
---------
 2.7.8

大功告成!更多详情请参阅 PostgresML 官方文档:https://postgresml.org/docs/guides/use-cases/

18.10 - OpenHalo

MySQL 兼容的 Postgres 14 分支

OpenHalo 是一个开源的 PostgreSQL 内核,提供 MySQL 线协议兼容性。

OpenHalo 基于 PostgreSQL 14.10 内核版本,提供与 MySQL 5.7.32-log / 8.0 版本的线协议兼容性。

Pigsty 在所有支持的 Linux 平台上为 OpenHalo 提供部署支持。


快速开始

使用 Pigsty 的 标准安装流程mysql 配置模板。

curl -fsSL https://repo.pigsty.io/get | bash; cd ~/pigsty;
./configure -c mysql    # 使用 MySQL(openHalo)配置模板
./deploy.yml            # 安装,生产部署请先在 pigsty.yml 中修改密码

对于生产部署,请确保在运行安装剧本之前修改 pigsty.yml 配置文件中的密码参数。


配置

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 }
    pg_databases:
      - {name: postgres, extensions: [aux_mysql]} # mysql 兼容数据库
      - {name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty]}
    pg_hba_rules:
      - {user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes'}
    node_crontab: [ '00 01 * * * postgres /pg/bin/pg-backup full' ] # 每天凌晨 1 点进行全量备份

    # OpenHalo 临时设置
    pg_mode: mysql                    # HaloDB 的 MySQL 兼容模式
    pg_version: 14                    # 当前 HaloDB 兼容 PG 主版本 14
    pg_packages: [ openhalodb, pgsql-common ]  # 安装 openhalodb 而不是 postgresql 内核

使用

访问 MySQL 时,实际连接使用的是 postgres 数据库。请注意,MySQL 中的"数据库"概念实际上对应于 PostgreSQL 中的"Schema"。因此,use mysql 实际上使用的是 postgres 数据库内的 mysql Schema。

用于 MySQL 的用户名和密码与 PostgreSQL 中的相同。您可以使用标准的 PostgreSQL 方法管理用户和权限。

客户端访问

OpenHalo 提供 MySQL 线协议兼容性,默认监听端口 3306,允许 MySQL 客户端和驱动程序直接连接。

Pigsty 的 conf/mysql 配置默认安装 mysql 客户端工具。

您可以使用以下命令访问 MySQL:

mysql -h 127.0.0.1 -u dbuser_dba

目前,OpenHalo 官方确保 Navicat 可以正常访问此 MySQL 端口,但 Intellij IDEA 的 DataGrip 访问会导致错误。


修改说明

Pigsty 安装的 OpenHalo 内核基于 HaloTech-Co-Ltd/openHalo 内核进行了少量修改:

  • 将默认数据库名称从 halo0root 改回 postgres
  • 从默认版本号中删除 1.0. 前缀,恢复为 14.10
  • 修改默认配置文件以启用 MySQL 兼容性并默认监听端口 3306

请注意,Pigsty 不为使用 OpenHalo 内核提供任何保证。使用此内核时遇到的任何问题或需求应与原始供应商联系。

警告:目前处于实验阶段 - 在生产使用前请彻底评估。

18.11 - Greenplum

使用 Pigsty 部署/监控 Greenplum 集群,构建大规模并行处理(MPP)的 PostgreSQL 数据仓库集群!

Pigsty 支持部署 Greenplum 集群,及其衍生发行版 YMatrixDB,并提供了将现有 Greenplum 部署纳入 Pigsty 监控的能力。


概览

Greenplum / YMatrix 集群部署能力仅在专业版本/企业版本中提供,目前不对外开源。


安装

Pigsty 提供了 Greenplum 6 (@el7) 与 Greenplum 7 (@el8) 的安装包,开源版本用户可以自行安装配置。

# EL 7 Only (Greenplum6)
./node.yml -t node_install  -e '{"node_repo_modules":"pgsql","node_packages":["open-source-greenplum-db-6"]}'

# EL 8 Only (Greenplum7)
./node.yml -t node_install  -e '{"node_repo_modules":"pgsql","node_packages":["open-source-greenplum-db-7"]}'

配置

要定义 Greenplum 集群,需要用到 pg_mode = gpsql,并使用额外的身份参数 pg_shardgp_role

#================================================================#
#                        GPSQL Clusters                          #
#================================================================#

#----------------------------------#
# cluster: mx-mdw (gp master)
#----------------------------------#
mx-mdw:
  hosts:
    10.10.10.10: { pg_seq: 1, pg_role: primary , nodename: mx-mdw-1 }
  vars:
    gp_role: master          # this cluster is used as greenplum master
    pg_shard: mx             # pgsql sharding name & gpsql deployment name
    pg_cluster: mx-mdw       # this master cluster name is mx-mdw
    pg_databases:
      - { name: matrixmgr , extensions: [ { name: matrixdbts } ] }
      - { name: meta }
    pg_users:
      - { name: meta , password: DBUser.Meta , pgbouncer: true }
      - { name: dbuser_monitor , password: DBUser.Monitor , roles: [ dbrole_readonly ], superuser: true }

    pgbouncer_enabled: true                # enable pgbouncer for greenplum master
    pgbouncer_exporter_enabled: false      # enable pgbouncer_exporter for greenplum master
    pg_exporter_params: 'host=127.0.0.1&sslmode=disable'  # use 127.0.0.1 as local monitor host

#----------------------------------#
# cluster: mx-sdw (gp master)
#----------------------------------#
mx-sdw:
  hosts:
    10.10.10.11:
      nodename: mx-sdw-1        # greenplum segment node
      pg_instances:             # greenplum segment instances
        6000: { pg_cluster: mx-seg1, pg_seq: 1, pg_role: primary , pg_exporter_port: 9633 }
        6001: { pg_cluster: mx-seg2, pg_seq: 2, pg_role: replica , pg_exporter_port: 9634 }
    10.10.10.12:
      nodename: mx-sdw-2
      pg_instances:
        6000: { pg_cluster: mx-seg2, pg_seq: 1, pg_role: primary , pg_exporter_port: 9633  }
        6001: { pg_cluster: mx-seg3, pg_seq: 2, pg_role: replica , pg_exporter_port: 9634  }
    10.10.10.13:
      nodename: mx-sdw-3
      pg_instances:
        6000: { pg_cluster: mx-seg3, pg_seq: 1, pg_role: primary , pg_exporter_port: 9633 }
        6001: { pg_cluster: mx-seg1, pg_seq: 2, pg_role: replica , pg_exporter_port: 9634 }
  vars:
    gp_role: segment               # these are nodes for gp segments
    pg_shard: mx                   # pgsql sharding name & gpsql deployment name
    pg_cluster: mx-sdw             # these segment clusters name is mx-sdw
    pg_preflight_skip: true        # skip preflight check (since pg_seq & pg_role & pg_cluster not exists)
    pg_exporter_config: pg_exporter_basic.yml                             # use basic config to avoid segment server crash
    pg_exporter_params: 'options=-c%20gp_role%3Dutility&sslmode=disable'  # use gp_role = utility to connect to segments

此外,PG Exporter 需要额外的连接参数,才能连接到 Greenplum Segment 实例上采集监控指标。

18.12 - OrioleDB

PostgreSQL 的下一代 OLTP 引擎

OrioleDB 是一个 PostgreSQL 存储引擎扩展,声称能够提供 4 倍 OLTP 性能,没有 xid 环绕和表膨胀问题,并具有"云原生"(数据存储在 S3)能力。

OrioleDB 的最新版本基于 补丁版 PostgreSQL 17.0 和一个额外的 扩展

您可以使用 Pigsty 将 OrioleDB 作为 RDS 运行,它与 PG 17 兼容,在所有支持的 Linux 平台上都可用。 最新版本为 beta12,基于 PG 17_11 补丁。


快速开始

按照 Pigsty 标准安装 流程,使用 oriole 配置模板。

curl -fsSL https://repo.pigsty.io/get | bash; cd ~/pigsty;
./configure -c oriole    # 使用 OrioleDB 配置模板
./deploy.yml             # 使用 OrioleDB 安装 Pigsty

对于生产部署,请确保在运行 install 剧本之前修改 pigsty.yml 配置中的密码参数。


配置

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 }
    pg_databases:
      - {name: meta ,baseline: cmdb.sql ,comment: pigsty meta database ,schemas: [pigsty], extensions: [orioledb]}
    pg_hba_rules:
      - {user: dbuser_view , db: all ,addr: infra ,auth: pwd ,title: 'allow grafana dashboard access cmdb from infra nodes'}
    node_crontab: [ '00 01 * * * postgres /pg/bin/pg-backup full' ] # 每天凌晨 1 点进行全量备份

    # OrioleDB 临时设置
    pg_mode: oriole                                         # oriole 兼容模式
    pg_packages: [ orioledb, pgsql-common ]                 # 安装 OrioleDB 内核
    pg_libs: 'orioledb, pg_stat_statements, auto_explain'   # 加载 OrioleDB 扩展

使用

要使用 OrioleDB,您需要安装 orioledb_17oriolepg_17 包(目前仅提供 RPM 版本)。

使用 pgbench 初始化类似 TPC-B 的表,包含 100 个仓库:

pgbench -is 100 meta
pgbench -nv -P1 -c10 -S -T1000 meta
pgbench -nv -P1 -c50 -S -T1000 meta
pgbench -nv -P1 -c10    -T1000 meta
pgbench -nv -P1 -c50    -T1000 meta

接下来,您可以使用 orioledb 存储引擎重建这些表并观察性能差异:

-- 创建 OrioleDB 表
CREATE TABLE pgbench_accounts_o (LIKE pgbench_accounts INCLUDING ALL) USING orioledb;
CREATE TABLE pgbench_branches_o (LIKE pgbench_branches INCLUDING ALL) USING orioledb;
CREATE TABLE pgbench_history_o (LIKE pgbench_history INCLUDING ALL) USING orioledb;
CREATE TABLE pgbench_tellers_o (LIKE pgbench_tellers INCLUDING ALL) USING orioledb;

-- 从常规表复制数据到 OrioleDB 表
INSERT INTO pgbench_accounts_o SELECT * FROM pgbench_accounts;
INSERT INTO pgbench_branches_o SELECT * FROM pgbench_branches;
INSERT INTO pgbench_history_o SELECT  * FROM pgbench_history;
INSERT INTO pgbench_tellers_o SELECT * FROM pgbench_tellers;

-- 删除原始表并重命名 OrioleDB 表
DROP TABLE pgbench_accounts, pgbench_branches, pgbench_history, pgbench_tellers;
ALTER TABLE pgbench_accounts_o RENAME TO pgbench_accounts;
ALTER TABLE pgbench_branches_o RENAME TO pgbench_branches;
ALTER TABLE pgbench_history_o RENAME TO pgbench_history;
ALTER TABLE pgbench_tellers_o RENAME TO pgbench_tellers;

关键特性

  • 无 XID 回绕:消除事务 ID 回绕维护
  • 无表膨胀:高级存储管理防止表膨胀
  • 云存储:对 S3 兼容对象存储的原生支持
  • OLTP 优化:专为事务工作负载设计
  • 改进性能:更好的空间利用率和查询性能

注意:目前处于 Beta 阶段 - 在生产使用前请彻底评估。

18.13 - Cloudberry

使用 Pigsty 部署/监控 Cloudberry 集群,一个由 Greenplum 分叉而来的 MPP 数据仓库集群!

安装

Pigsty 提供了 Greenplum 6 (@el7) 与 Greenplum 7 (@el8) 的安装包,开源版本用户可以自行安装配置。

# EL 7 Only (Greenplum6)
./node.yml -t node_install  -e '{"node_repo_modules":"pgsql","node_packages":["cloudberrydb"]}'

# EL 8 Only (Greenplum7)
./node.yml -t node_install  -e '{"node_repo_modules":"pgsql","node_packages":["cloudberrydb"]}'

18.14 - Neon

使用 Neon 开源的 Serverless 版本 PostgreSQL 内核,自建灵活伸缩,Scale To Zero,灵活分叉的PG服务。

Neon 采用了存储与计算分离架构,提供了丝滑的自动扩缩容,Scale to Zero,以及数据库版本分叉等独家能力。

Neon 官网:https://neon.tech/

Neon 编译后的二进制产物过于庞大,目前不对开源版用户提供,目前处于试点阶段,有需求请联系 Pigsty 销售。

19 - 常见问题

PostgreSQL 常见问题答疑

我当前执行安装的用户为何不能使用 pg 管理别名?

从 Pigsty v4.0 开始,使用 pg 管理别名管理全局的 Patroni / PostgreSQL 集群的权限被收紧到了管理节点上的管理员分组(admin)。

node.yml 剧本创建的管理员(dba)默认具有此权限,而其他用户如果想要获得这个权限,需要你显式地将该用户加入到 admin 组中。

sudo usermod -aG admin <username>

PGSQL初始化失败:Fail to wait for postgres/patroni primary

这种错误信息存在多种可能,需要你 检查 Ansible,Systemd / Patroni / PostgreSQL 日志,找出真正的原因。

  • 可能性1:集群配置错误,找出错误的配置项修改并应用。
  • 可能性2:在部署中存在同名集群,或者之前的同名集群主节点被不正确地移除
  • 可能性3:在DCS中有同名集群残留的垃圾元数据:没有正确完成下线,你可以使用 etcdctl del --prefix /pg/<cls> 来手工删除残留数据(请小心)
  • 可能性4:你的 PostgreSQL 或节点相关 RPM 包没有被成功安装
  • 可能性5:你的 Watchdog 内核模块没有正确启用加载
  • 可能性6:你在初始化数据库时指定的语言 Locale 不存在(例如,使用了 en_US.UTF8,但没有安装英文语言包或 Locale 支持)
  • 如果你遇到了其他的原因,欢迎提交 Issue 或向社区求助。

PGSQL初始化失败:Fail to wait for postgres/patroni replica

存在几种可能的原因:

立即失败:通常是由于配置错误、网络问题、损坏的DCS元数据等原因。你必须检查 /pg/log 找出实际原因。

过了一会儿失败:这可能是由于源实例数据损坏。查看 PGSQL FAQ:如何在数据损坏时创建副本?

过了很长时间再超时:如果 wait for postgres replica 任务耗时 30 分钟或更长时间并由于超时而失败,这对于大型集群(例如,1TB+,可能需要几小时创建一个副本)是很常见的。

在这种情况下,底层创建副本的过程仍在进行。你可以使用 pg list <cls> 检查集群状态并等待副本赶上主节点。然后使用以下命令继续以下任务,完成完整的从库初始化:

./pgsql.yml -t pg_hba,pg_reload,pg_backup,pgbouncer,pg_vip,pg_dns,pg_service,pg_exporter,pg_register -l <problematic_replica>

PGSQL初始化失败:ABORT due to pg_safeguard enabled

这意味着正准备清理的 PostgreSQL 实例打开了防误删保险, 禁用 pg_safeguard 以移除 Postgres 实例。

如果防误删保险 pg_safeguard 打开,那么你就不能使用 bin/pgsql-rmpgsql-rm.yml 剧本移除正在运行的 PGSQL 实例了。

要禁用 pg_safeguard,你可以在配置清单中将 pg_safeguard 设置为 false,或者在执行剧本时使用命令参数 -e pg_safeguard=false

./pgsql-rm.yml -e pg_safeguard=false -l <cls_to_remove>    # 强制覆盖 pg_safeguard

如何确保故障转移中数据不丢失?

使用 crit.yml 参数模板,设置 pg_rpo0,或 配置集群 为同步提交模式。

考虑使用 同步备库法定多数提交 来确保故障转移过程中的零数据丢失。

更多细节,可以参考 安全考量 - 可用性 的相关介绍。


磁盘写满了如何抢救?

如果磁盘写满了,连 Shell 命令都无法执行,rm -rf /pg/dummy 可以释放一些救命空间。

默认情况下,pg_dummy_filesize 设置为 64MB。在生产环境中,建议将其增加到 8GB 或更大。

它将被放置在 PGSQL 主数据磁盘上的 /pg/dummy 路径下。你可以删除该文件以释放一些紧急空间:

至少可以让你在该节点上运行一些 shell 脚本来进一步回收其他空间(例如日志/WAL,过时数据,WAL归档与备份)。


当集群数据已经损坏时如何创建副本?

Pigsty 在所有实例的 patroni 配置中设置了 cloneform: true 标签,标记该实例可用于创建副本。

如果某个实例有损坏的数据文件,导致创建新副本的时候出错中断,那么你可以设置 clonefrom: false 来避免从损坏的实例中拉取数据。具体操作如下

$ vi /pg/bin/patroni.yml

tags:
  nofailover: false
  clonefrom: true      # ----------> change to false
  noloadbalance: false
  nosync: false
  version:  '15'
  spec: '4C.8G.50G'
  conf: 'oltp.yml'
  
$ systemctl reload patroni    # 重新加载 Patroni 配置

PostgreSQL 监控的性能损耗如何?

一个常规 PostgreSQL 实例抓取耗时大约 200ms。抓取间隔默认为 10 秒,对于一个生产多核数据库实例来说几乎微不足道。

请注意,Pigsty 默认开启了库内对象监控,所以如果您的数据库内有数以十万计的表/索引对象,抓取可能耗时会增加到几秒。

您可以修改 Prometheus 的抓取频率,请确保一点:抓取周期应当显著高于一次抓取的时长。


如何监控一个现存的 PostgreSQL 实例?

PGSQL Monitor 中提供了详细的监控配置说明。


如何手工从监控中移除 PostgreSQL 监控目标?

./pgsql-rm.yml -t rm_metrics -l <cls>     # 将集群 'cls' 的所有实例从 victoria 中移除
bin/pgmon-rm <ins>     # 用于从 Victoria 中移除单个实例 'ins' 的监控对象,特别适合移除添加的外部实例

20 - 其他说明

其他说明与杂项文档

20.1 - 用户/角色

用户/角色指的是使用 SQL 命令 CREATE USER/ROLE 创建的,数据库集簇内的逻辑对象。

在这里的上下文中,用户指的是使用 SQL 命令 CREATE USER/ROLE 创建的,数据库集簇内的逻辑对象。

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


定义用户

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

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

前者用于定义了整套环境中共用的角色与用户,后者定义单个集群中特有的业务角色与用户。二者形式相同,均为用户定义对象的数组。

你可以定义多个用户/角色,它们会按照先全局,后集群,最后按数组内排序的顺序依次创建,所以后面的用户可以属于前面定义的角色。

下面是 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      }

每个用户/角色定义都是一个 object,可能包括以下字段,以 dbuser_meta 用户为例:

- name: dbuser_meta               # 必需,`name` 是用户定义的唯一必选字段
  password: DBUser.Meta           # 可选,密码,可以是 scram-sha-256 哈希字符串或明文
  login: true                     # 可选,默认情况下可以登录
  superuser: false                # 可选,默认为 false,是超级用户吗?
  createdb: false                 # 可选,默认为 false,可以创建数据库吗?
  createrole: false               # 可选,默认为 false,可以创建角色吗?
  inherit: true                   # 可选,默认情况下,此角色可以使用继承的权限吗?
  replication: false              # 可选,默认为 false,此角色可以进行复制吗?
  bypassrls: false                # 可选,默认为 false,此角色可以绕过行级安全吗?
  pgbouncer: true                 # 可选,默认为 false,将此用户添加到 pgbouncer 用户列表吗?(使用连接池的生产用户应该显式定义为 true)
  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]           # 可选,默认角色为:dbrole_{admin,readonly,readwrite,offline}
  parameters: {}                  # 可选,使用 `ALTER ROLE SET` 针对这个角色,配置角色级的数据库参数
  pool_mode: transaction          # 可选,默认为 transaction 的 pgbouncer 池模式,用户级别
  pool_connlimit: -1              # 可选,用户级别的最大数据库连接数,默认 -1 禁用限制
  search_path: public             # 可选,根据 postgresql 文档的键值配置参数(例如:使用 pigsty 作为默认 search_path)
  • 唯一必需的字段是 name,它应该是 PostgreSQL 集群中的一个有效且唯一的用户名。
  • 角色不需要 password,但对于可登录的业务用户,通常是需要指定一个密码的。
  • password 可以是明文或 scram-sha-256 / md5 哈希字符串,请最好不要使用明文密码。
  • 用户/角色按数组顺序逐一创建,因此,请确保角色/分组的定义在成员之前。
  • loginsuperusercreatedbcreateroleinheritreplicationbypassrls 是布尔标志。
  • pgbouncer 默认是禁用的:要将业务用户添加到 pgbouncer 用户列表,您应当显式将其设置为 true

ACL系统

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

  • dbrole_readwrite:全局读写访问的角色(主属业务使用的生产账号应当具有数据库读写权限)
  • dbrole_readonly:全局只读访问的角色(如果别的业务想要只读访问,可以使用此角色)
  • dbrole_admin:拥有DDL权限的角色 (业务管理员,需要在应用中建表的场景)
  • dbrole_offline:受限的只读访问角色(只能访问 offline 实例,通常是个人用户)

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


创建用户

pg_default_rolespg_users定义 的用户和角色,将在集群初始化的 PROVISION 阶段中自动逐一创建。 如果您希望在现有的集群上 创建用户,可以使用 bin/pgsql-user 工具。 将新用户/角色定义添加到 all.children.<cls>.pg_users,并使用以下方法创建该数据库:

bin/pgsql-user <cls> <username>    # pgsql-user.yml -l <cls> -e username=<username>

不同于数据库,创建用户的剧本总是幂等的。当目标用户已经存在时,Pigsty会修改目标用户的属性使其符合配置。所以在现有集群上重复运行它通常不会有问题。


修改用户

修改 PostgreSQL 用户的属性的方式与 创建用户 相同。

首先,调整您的用户定义,修改需要调整的属性,然后执行以下命令应用:

bin/pgsql-user <cls> <username>    # pgsql-user.yml -l <cls> -e username=<username>

请注意,修改用户不会删除用户,而是通过 ALTER USER 命令修改用户属性;也不会回收用户的权限与分组,并使用 GRANT 命令授予新的角色。


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="
"dbuser_kong" "SCRAM-SHA-256$4096:bK8sLXIieMwFDz67/0dqXQ==$P/tCRgyKx9MC9LH3ErnKsnlOqgNd/nn2RyvThyiK6e4=:CDM8QZNHBdPf97ztusgnE7olaKDNHBN0WeAbP/nzu5A="
"dbuser_grafana" "SCRAM-SHA-256$4096:HjLdGaGmeIAGdWyn2gDt/Q==$jgoyOB8ugoce+Wqjr0EwFf8NaIEMtiTuQTg1iEJs9BM=:ed4HUFqLyB4YpRr+y25FBT7KnlFDnan6JPVT9imxzA4="
"dbuser_gitea" "SCRAM-SHA-256$4096:l1DBGCc4dtircZ8O8Fbzkw==$tpmGwgLuWPDog8IEKdsaDGtiPAxD16z09slvu+rHE74=:pYuFOSDuWSofpD9OZhG7oWvyAR0PQjJBffgHZLpLHds="
"dbuser_dba" "SCRAM-SHA-256$4096:zH8niABU7xmtblVUo2QFew==$Zj7/pq+ICZx7fDcXikiN7GLqkKFA+X5NsvAX6CMshF0=:pqevR2WpizjRecPIQjMZOm+Ap+x0kgPL2Iv5zHZs0+g="
"dbuser_bytebase" "SCRAM-SHA-256$4096:OMoTM9Zf8QcCCMD0svK5gg==$kMchqbf4iLK1U67pVOfGrERa/fY818AwqfBPhsTShNQ=:6HqWteN+AadrUnrgC0byr5A72noqnPugItQjOLFw0Wk="

而用户级别的连接池参数则是使用另一个单独的文件: /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 管理功能。

Pigsty 还提供了一个实用函数 pgb-route ,可以将 pgbouncer 数据库流量快速切换至集群中的其他节点,用于零停机迁移:

连接池用户配置文件 userlist.txtuseropts.txt 会在您 创建用户 时自动刷新,并通过在线重载配置的方式生效,正常不会影响现有的连接。

请注意,pgbouncer_auth_query 参数允许你使用动态查询来完成连接池用户认证,当您懒得管理连接池中的用户时,这是一种折中的方案。

20.2 - 数据库

数据库指的是使用 SQL 命令 CREATE DATABASE 创建的,数据库集簇内的逻辑对象。

在这里的上下文中,数据库指的是使用 SQL 命令 CREATE DATABASE 创建的,数据库集簇内的逻辑对象。

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

Pigsty会对默认模板数据库template1进行修改与定制,创建默认模式,安装默认扩展,配置默认权限,新创建的数据库默认会从template1继承这些设置。

默认情况下,所有业务数据库都会被1:1添加到 Pgbouncer 连接池中;pg_exporter 默认会通过 自动发现 机制查找所有业务数据库并进行库内对象监控。


定义数据库

业务数据库定义在数据库集群参数 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 }

每个数据库定义都是一个 object,可能包括以下字段,以 meta 数据库为例:

- name: meta                      # 必选,`name` 是数据库定义的唯一必选字段
  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                 # 可选,数据库所有者,默认为 postgres
  template: template1             # 可选,要使用的模板,默认为 template1,目标必须是一个模板数据库
  encoding: UTF8                  # 可选,数据库编码,默认为 UTF8(必须与模板数据库相同)
  locale: C                       # 可选,数据库地区设置,默认为 C(必须与模板数据库相同)
  lc_collate: C                   # 可选,数据库 collate 排序规则,默认为 C(必须与模板数据库相同),没有理由不建议更改。
  lc_ctype: C                     # 可选,数据库 ctype 字符集,默认为 C(必须与模板数据库相同)
  tablespace: pg_default          # 可选,默认表空间,默认为 'pg_default'
  allowconn: true                 # 可选,是否允许连接,默认为 true。显式设置 false 将完全禁止连接到此数据库
  revokeconn: false               # 可选,撤销公共连接权限。默认为 false,设置为 true 时,属主和管理员之外用户的 CONNECT 权限会被回收
  register_datasource: true       # 可选,是否将此数据库注册到 grafana 数据源?默认为 true,显式设置为 false 会跳过注册
  connlimit: -1                   # 可选,数据库连接限制,默认为 -1 ,不限制,设置为正整数则会限制连接数。
  pool_auth_user: dbuser_meta     # 可选,连接到此 pgbouncer 数据库的所有连接都将使用此用户进行验证(启用 pgbouncer_auth_query 才有用)
  pool_mode: transaction          # 可选,数据库级别的 pgbouncer 池化模式,默认为 transaction
  pool_size: 64                   # 可选,数据库级别的 pgbouncer 默认池子大小,默认为 64
  pool_size_reserve: 32           # 可选,数据库级别的 pgbouncer 池子保留空间,默认为 32,当默认池子不够用时,最多再申请这么多条突发连接。
  pool_size_min: 0                # 可选,数据库级别的 pgbouncer 池的最小大小,默认为 0
  pool_max_db_conn: 100           # 可选,数据库级别的最大数据库连接数,默认为 100

唯一必选的字段是 name,它应该是当前 PostgreSQL 集群中有效且唯一的数据库名称,其他参数都有合理的默认值。

  • name:数据库名称,必选项
  • baseline:SQL文件路径(Ansible搜索路径,通常位于files),用于初始化数据库内容。
  • owner:数据库属主,默认为postgres
  • template:数据库创建时使用的模板,默认为template1
  • encoding:数据库默认字符编码,默认为UTF8,默认与实例保持一致。建议不要配置与修改。
  • locale:数据库默认的本地化规则,默认为C,建议不要配置,与实例保持一致。
  • lc_collate:数据库默认的本地化字符串排序规则,默认与实例设置相同,建议不要修改,必须与模板数据库一致。强烈建议不要配置,或配置为C
  • lc_ctype:数据库默认的LOCALE,默认与实例设置相同,建议不要修改或设置,必须与模板数据库一致。建议配置为C或en_US.UTF8
  • allowconn:是否允许连接至数据库,默认为true,不建议修改。
  • revokeconn:是否回收连接至数据库的权限?默认为false。如果为true,则数据库上的PUBLIC CONNECT权限会被回收。只有默认用户(dbsu|monitor|admin|replicator|owner)可以连接。此外,admin|owner 会拥有GRANT OPTION,可以赋予其他用户连接权限。
  • tablespace:数据库关联的表空间,默认为pg_default
  • connlimit:数据库连接数限制,默认为-1,即没有限制。
  • extensions:对象数组 ,每一个对象定义了一个数据库中的扩展,以及其安装的模式
  • parameters:KV对象,每一个KV定义了一个需要针对数据库通过ALTER DATABASE修改的参数。
  • pgbouncer:布尔选项,是否将该数据库加入到Pgbouncer中。所有数据库都会加入至Pgbouncer列表,除非显式指定pgbouncer: false
  • comment:数据库备注信息。
  • pool_auth_user:启用 pgbouncer_auth_query 时,连接到此 pgbouncer 数据库的所有连接都将使用这里指定的用户执行认证查询。你需要使用一个具有访问 pg_shadow 表权限的用户。
  • pool_mode:数据库级别的 pgbouncer 池化模式,默认为 transaction,即事物池化。如果留空,会使用 pgbouncer_poolmode 参数作为默认值。
  • pool_size:数据库级别的 pgbouncer 默认池子大小,默认为 64
  • pool_size_reserve:数据库级别的 pgbouncer 池子保留空间,默认为 32,当默认池子不够用时,最多再申请这么多条突发连接。
  • pool_size_min: 数据库级别的 pgbouncer 池的最小大小,默认为 0
  • pool_max_db_conn: 数据库级别的 pgbouncer 连接池最大数据库连接数,默认为 100

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

关于数据库的访问权限,请参考 ACL:数据库权限 一节。


创建数据库

pg_databases定义 的数据库将在集群初始化时自动创建。 如果您希望在现有集群上 创建数据库,可以使用 bin/pgsql-db 包装脚本。 将新的数据库定义添加到 all.children.<cls>.pg_databases 中,并使用以下命令创建该数据库:

bin/pgsql-db <cls> <dbname>    # pgsql-db.yml -l <cls> -e dbname=<dbname>

下面是新建数据库时的一些注意事项:

创建数据库的剧本默认为幂等剧本,不过当您当使用 baseline 脚本时就不一定了:这种情况下,通常不建议在现有数据库上重复执行此操作,除非您确定所提供的 baseline SQL也是幂等的。

我们不建议您手工创建新的数据库,特别当您使用默认的 pgbouncer 连接池时:除非您愿意手工负责维护 Pgbouncer 中的数据库列表并与 PostgreSQL 保持一致。 使用 pgsql-db 工具或 pgsql-db.yml 剧本创建新数据库时,会将此数据库一并添加到 Pgbouncer 数据库 列表中。

如果您的数据库定义有一个非常规 owner(默认为 dbsu postgres),那么请确保在创建该数据库前,属主用户已经存在。 最佳实践永远是在创建数据库之前 创建 用户


Pgbouncer数据库

Pigsty 会默认为 PostgreSQL 实例 1:1 配置启用一个 Pgbouncer 连接池,使用 /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 的数据库列表定义文件将会被刷新,并通过在线重载配置的方式生效,正常不会影响现有的连接。

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

Pigsty 还提供了一个实用函数 pgb-route ,可以将 pgbouncer 数据库流量快速切换至集群中的其他节点,用于零停机迁移:

# route pgbouncer traffic to another cluster member
function pgb-route(){
  local ip=${1-'\/var\/run\/postgresql'}
  sed -ie "s/host=[^[:space:]]\+/host=${ip}/g" /etc/pgbouncer/pgbouncer.ini
  cat /etc/pgbouncer/pgbouncer.ini
}

20.3 - 服务/接入

分离读写操作,正确路由流量,稳定可靠地交付 PostgreSQL 集群提供的能力。

分离读写操作,正确路由流量,稳定可靠地交付 PostgreSQL 集群提供的能力。

服务 是一种抽象:它是数据库集群对外提供能力的形式,并封装了底层集群的细节。

服务对于生产环境中的 稳定接入 至关重要,在 高可用 集群自动故障时方显其价值,单机用户 通常不需要操心这个概念。


单机用户

“服务” 的概念是给生产环境用的,个人用户/单机集群可以不折腾,直接拿实例名/IP地址访问数据库。

例如,Pigsty 默认的单节点 pg-meta.meta 数据库,就可以直接用下面三个不同的用户连接上去。

psql postgres://dbuser_dba:DBUser.DBA@10.10.10.10/meta     # 直接用 DBA 超级用户连上去
psql postgres://dbuser_meta:DBUser.Meta@10.10.10.10/meta   # 用默认的业务管理员用户连上去
psql postgres://dbuser_view:DBUser.View@pg-meta/meta       # 用默认的只读用户走实例域名连上去

服务概述

在真实世界生产环境中,我们会使用基于复制的主从数据库集群。集群中有且仅有一个实例作为领导者(主库)可以接受写入。 而其他实例(从库)则会从持续从集群领导者获取变更日志,与领导者保持一致。同时,从库还可以承载只读请求,在读多写少的场景下可以显著分担主库的负担, 因此对集群的写入请求与只读请求进行区分,是一种十分常见的实践。

此外对于高频短连接的生产环境,我们还会通过连接池中间件(Pgbouncer)对请求进行池化,减少连接与后端进程的创建开销。但对于ETL与变更执行等场景,我们又需要绕过连接池,直接访问数据库。 同时,高可用集群在故障时会出现故障切换(Failover),故障切换会导致集群的领导者出现变更。因此高可用的数据库方案要求写入流量可以自动适配集群的领导者变化。 这些不同的访问需求(读写分离,池化与直连,故障切换自动适配)最终抽象出 服务 (Service)的概念。

通常来说,数据库集群都必须提供这种最基础的服务:

  • 读写服务(primary) :可以读写数据库

对于生产数据库集群,至少应当提供这两种服务:

  • 读写服务(primary) :写入数据:只能由主库所承载。
  • 只读服务(replica) :读取数据:可以由从库承载,没有从库时也可由主库承载

此外,根据具体的业务场景,可能还会有其他的服务,例如:

  • 默认直连服务(default) :允许(管理)用户,绕过连接池直接访问数据库的服务
  • 离线从库服务(offline) :不承接线上只读流量的专用从库,用于ETL与分析查询
  • 同步从库服务(standby) :没有复制延迟的只读服务,由 同步备库/主库处理只读查询
  • 延迟从库服务(delayed) :访问同一个集群在一段时间之前的旧数据,由 延迟从库 来处理

默认服务

Pigsty默认为每个 PostgreSQL 数据库集群提供四种不同的服务,以下是默认服务及其定义:

服务端口描述
primary5433生产读写,连接到主库连接池(6432)
replica5434生产只读,连接到备库连接池(6432)
default5436管理,ETL写入,直接访问主库(5432)
offline5438OLAP、ETL、个人用户、交互式查询

以默认的 pg-meta 集群为例,它提供四种默认服务:

psql postgres://dbuser_meta:DBUser.Meta@pg-meta:5433/meta   # pg-meta-primary : 通过主要的 pgbouncer(6432) 进行生产读写
psql postgres://dbuser_meta:DBUser.Meta@pg-meta:5434/meta   # pg-meta-replica : 通过备份的 pgbouncer(6432) 进行生产只读
psql postgres://dbuser_dba:DBUser.DBA@pg-meta:5436/meta     # pg-meta-default : 通过主要的 postgres(5432) 直接连接
psql postgres://dbuser_stats:DBUser.Stats@pg-meta:5438/meta # pg-meta-offline : 通过离线的 postgres(5432) 直接连接

从示例集群 架构图 上可以看出这四种服务的工作方式:

pigsty-ha.png

注意在这里pg-meta 域名指向了集群的 L2 VIP,进而指向集群主库上的 haproxy 负载均衡器,它负责将流量路由到不同的实例上,详见 服务接入


服务实现

在 Pigsty 中,服务使用 节点 上的 haproxy 来实现,通过主机节点上的不同端口进行区分。

Pigsty 所纳管的每个节点上都默认启用了 Haproxy 以对外暴露服务,而数据库节点也不例外。 集群中的节点尽管从数据库的视角来看有主从之分,但从服务的视角来看,每个节点都是相同的: 这意味着即使您访问的是从库节点,只要使用正确的服务端口,就依然可以使用到主库读写的服务。 这样的设计可以屏蔽复杂度:所以您只要可以访问 PostgreSQL 集群上的任意一个实例,就可以完整的访问到所有服务。

这样的设计类似于 Kubernetes 中的 NodePort 服务,同样在 Pigsty 中,每一个服务都包括以下两个核心要素:

  1. 通过 NodePort 暴露的访问端点(端口号,从哪访问?)
  2. 通过 Selectors 选择的目标实例(实例列表,谁来承载?)

Pigsty的服务交付边界止步于集群的HAProxy,用户可以用各种手段访问这些负载均衡器,请参考 接入服务

所有的服务都通过配置文件进行声明,例如,PostgreSQL 默认服务就是由 pg_default_services 参数所定义的:

pg_default_services:
- { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }
- { name: replica ,port: 5434 ,dest: default  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
- { name: default ,port: 5436 ,dest: postgres ,check: /primary   ,selector: "[]" }
- { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]"}

您也可以在 pg_services 中定义额外的服务,参数 pg_default_servicespg_services 都是由 服务定义 对象组成的数组。


定义服务

Pigsty 允许您定义自己的服务:

  • pg_default_services:所有 PostgreSQL 集群统一对外暴露的服务,默认有四个。
  • pg_services:额外的 PostgreSQL 服务,可以视需求在全局或集群级别定义。
  • haproxy_servies:直接定制 HAProxy 服务内容,可以用于其他组件的接入

对于 PostgreSQL 集群来说,通常只需要关注前两者即可。 每一条服务定义都会在所有相关 HAProxy 实例的配置目录下生成一个新的配置文件:/etc/haproxy/<svcname>.cfg 下面是一个自定义的服务样例 standby:当您想要对外提供没有复制延迟的只读服务时,就可以在 pg_services 新增这条记录:

- name: standby                   # 必选,服务名称,最终的 svc 名称会使用 `pg_cluster` 作为前缀,例如:pg-meta-standby
  port: 5435                      # 必选,暴露的服务端口(作为 kubernetes 服务节点端口模式)
  ip: "*"                         # 可选,服务绑定的 IP 地址,默认情况下为所有 IP 地址
  selector: "[]"                  # 必选,服务成员选择器,使用 JMESPath 来筛选配置清单
  backup: "[? pg_role == `primary`]"  # 可选,服务成员选择器(备份),也就是当默认选择器选中的实例都宕机后,服务才会由这里选中的实例成员来承载
  dest: default                   # 可选,目标端口,default|postgres|pgbouncer|<port_number>,默认为 'default',Default的意思就是使用 pg_default_service_dest 的取值来最终决定
  check: /sync                    # 可选,健康检查 URL 路径,默认为 /,这里使用 Patroni API:/sync ,只有同步备库和主库才会返回 200 健康状态码 
  maxconn: 5000                   # 可选,允许的前端连接最大数,默认为5000
  balance: roundrobin             # 可选,haproxy 负载均衡算法(默认为 roundrobin,其他选项:leastconn)
  options: 'inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100'

而上面的服务定义,在样例的三节点 pg-test 上将会被转换为 haproxy 配置文件 /etc/haproxy/pg-test-standby.conf

#---------------------------------------------------------------------
# service: pg-test-standby @ 10.10.10.11:5435
#---------------------------------------------------------------------
# service instances 10.10.10.11, 10.10.10.13, 10.10.10.12
# service backups   10.10.10.11
listen pg-test-standby
    bind *:5435            # <--- 绑定了所有IP地址上的 5435 端口
    mode tcp               # <--- 负载均衡器工作在 TCP 协议上
    maxconn 5000           # <--- 最大连接数为 5000,可按需调大
    balance roundrobin     # <--- 负载均衡算法为 rr 轮询,还可以使用 leastconn 
    option httpchk         # <--- 启用 HTTP 健康检查
    option http-keep-alive # <--- 保持HTTP连接
    http-check send meth OPTIONS uri /sync   # <---- 这里使用 /sync ,Patroni 健康检查 API ,只有同步备库和主库才会返回 200 健康状态码。 
    http-check expect status 200             # <---- 健康检查返回代码 200 代表正常
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers: # pg-test 集群全部三个实例都被 selector: "[]" 给圈中了,因为没有任何的筛选条件,所以都会作为 pg-test-replica 服务的后端服务器。但是因为还有 /sync 健康检查,所以只有主库和同步备库才能真正承载请求。
    server pg-test-1 10.10.10.11:6432 check port 8008 weight 100 backup  # <----- 唯独主库满足条件 pg_role == `primary`, 被 backup selector 选中。
    server pg-test-3 10.10.10.13:6432 check port 8008 weight 100         #        因此作为服务的兜底实例:平时不承载请求,其他从库全部宕机后,才会承载只读请求,从而最大避免了读写服务受到只读服务的影响
    server pg-test-2 10.10.10.12:6432 check port 8008 weight 100         #        

在这里,pg-test 集群全部三个实例都被 selector: "[]" 给圈中了,渲染进入 pg-test-replica 服务的后端服务器列表中。但是因为还有 /sync 健康检查,Patroni Rest API只有在主库和 同步备库 上才会返回代表健康的 HTTP 200 状态码,因此只有主库和同步备库才能真正承载请求。 此外,主库因为满足条件 pg_role == primary, 被 backup selector 选中,被标记为了备份服务器,只有当没有其他实例(也就是同步备库)可以满足需求时,才会顶上。


Primary服务

Primary服务可能是生产环境中最关键的服务,它在 5433 端口提供对数据库集群的读写能力,服务定义如下:

- { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }
  • 选择器参数 selector: "[]" 意味着所有集群成员都将被包括在Primary服务中
  • 但只有主库能够通过健康检查(check: /primary),实际承载Primary服务的流量。
  • 目的地参数 dest: default 意味着Primary服务的目的地受到 pg_default_service_dest 参数的影响
  • dest 默认值 default 会被替换为 pg_default_service_dest 的值,默认为 pgbouncer
  • 默认情况下 Primary 服务的目的地默认是主库上的连接池,也就是由 pgbouncer_port 指定的端口,默认为 6432

如果 pg_default_service_dest 的值为 postgres,那么 primary 服务的目的地就会绕过连接池,直接使用 PostgreSQL 数据库的端口(pg_port,默认值 5432),对于一些不希望使用连接池的场景,这个参数非常实用。

示例:pg-test-primary 的 haproxy 配置
listen pg-test-primary
    bind *:5433         # <--- primary 服务默认使用 5433 端口
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /primary # <--- primary 服务默认使用 Patroni RestAPI /primary 健康检查
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-1 10.10.10.11:6432 check port 8008 weight 100
    server pg-test-3 10.10.10.13:6432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:6432 check port 8008 weight 100

Patroni 的 高可用 机制确保任何时候最多只会有一个实例的 /primary 健康检查为真,因此Primary服务将始终将流量路由到主实例。

使用 Primary 服务而不是直连数据库的一个好处是,如果集群因为某种情况出现了双主(比如在没有watchdog的情况下kill -9杀死主库 Patroni),Haproxy在这种情况下仍然可以避免脑裂,因为它只会在 Patroni 存活且返回主库状态时才会分发流量。


Replica服务

Replica服务在生产环境中的重要性仅次于Primary服务,它在 5434 端口提供对数据库集群的只读能力,服务定义如下:

- { name: replica ,port: 5434 ,dest: default  ,check: /read-only ,selector: "[]" , backup: "[? pg_role == `primary` || pg_role == `offline` ]" }
  • 选择器参数 selector: "[]" 意味着所有集群成员都将被包括在Replica服务中
  • 所有实例都能够通过健康检查(check: /read-only),承载Replica服务的流量。
  • 备份选择器:[? pg_role == 'primary' || pg_role == 'offline' ] 将主库和 离线从库 标注为备份服务器。
  • 只有当所有 普通从库 都宕机后,Replica服务才会由主库或离线从库来承载。
  • 目的地参数 dest: default 意味着Replica服务的目的地也受到 pg_default_service_dest 参数的影响
  • dest 默认值 default 会被替换为 pg_default_service_dest 的值,默认为 pgbouncer,这一点和 Primary服务 相同
  • 默认情况下 Replica 服务的目的地默认是从库上的连接池,也就是由 pgbouncer_port 指定的端口,默认为 6432
示例:pg-test-replica 的 haproxy 配置
listen pg-test-replica
    bind *:5434
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /read-only
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-1 10.10.10.11:6432 check port 8008 weight 100 backup
    server pg-test-3 10.10.10.13:6432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:6432 check port 8008 weight 100

Replica服务非常灵活:如果有存活的专用 Replica 实例,那么它会优先使用这些实例来承载只读请求,只有当从库实例全部宕机后,才会由主库来兜底只读请求。对于常见的一主一从双节点集群就是:只要从库活着就用从库,从库挂了再用主库。

此外,除非专用只读实例全部宕机,Replica 服务也不会使用专用 Offline 实例,这样就避免了在线快查询与离线慢查询混在一起,相互影响。


Default服务

Default服务在 5436 端口上提供服务,它是Primary服务的变体。

Default服务总是绕过连接池直接连到主库上的 PostgreSQL,这对于管理连接、ETL写入、CDC数据变更捕获等都很有用。

- { name: primary ,port: 5433 ,dest: default  ,check: /primary   ,selector: "[]" }

如果 pg_default_service_dest 被修改为 postgres,那么可以说 Default 服务除了端口和名称内容之外,与 Primary 服务是完全等价的。在这种情况下,您可以考虑将 Default 从默认服务中剔除。

示例:pg-test-default 的 haproxy 配置
listen pg-test-default
    bind *:5436         # <--- 除了监听端口/目标端口和服务名,其他配置和 primary 服务一模一样
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /primary
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-1 10.10.10.11:5432 check port 8008 weight 100
    server pg-test-3 10.10.10.13:5432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:5432 check port 8008 weight 100

Offline服务

Default服务在 5438 端口上提供服务,它也绕开连接池直接访问 PostgreSQL 数据库,通常用于慢查询/分析查询/ETL读取/个人用户交互式查询,其服务定义如下:

- { name: offline ,port: 5438 ,dest: postgres ,check: /replica   ,selector: "[? pg_role == `offline` || pg_offline_query ]" , backup: "[? pg_role == `replica` && !pg_offline_query]"}

Offline服务将流量直接路由到专用的 离线从库 上,或者带有 pg_offline_query 标记的普通 只读实例

  • 选择器参数从集群中筛选出了两种实例:pg_role = offline 的离线从库,或是带有 pg_offline_query = true 标记的普通 只读实例
  • 专用离线从库和打标记的普通从库主要的区别在于:前者默认不承载 Replica服务 的请求,避免快慢请求混在一起,而后者默认会承载。
  • 备份选择器参数从集群中筛选出了一种实例:不带 offline 标记的普通从库,这意味着如果离线实例或者带Offline标记的普通从库挂了之后,其他普通的从库可以用来承载Offline服务。
  • 健康检查 /replica 只会针对从库返回 200, 主库会返回错误,因此 Offline服务 永远不会将流量分发到主库实例上去,哪怕集群中只剩这一台主库。
  • 同时,主库实例既不会被选择器圈中,也不会被备份选择器圈中,因此它永远不会承载Offline服务。因此 Offline 服务总是可以避免用户访问主库,从而避免对主库的影响。
示例:pg-test-offline 的 haproxy 配置
listen pg-test-offline
    bind *:5438
    mode tcp
    maxconn 5000
    balance roundrobin
    option httpchk
    option http-keep-alive
    http-check send meth OPTIONS uri /replica
    http-check expect status 200
    default-server inter 3s fastinter 1s downinter 5s rise 3 fall 3 on-marked-down shutdown-sessions slowstart 30s maxconn 3000 maxqueue 128 weight 100
    # servers
    server pg-test-3 10.10.10.13:5432 check port 8008 weight 100
    server pg-test-2 10.10.10.12:5432 check port 8008 weight 100 backup

Offline服务提供受限的只读服务,通常用于两类查询:交互式查询(个人用户),慢查询长事务(分析/ETL)。

Offline 服务需要额外的维护照顾:当集群发生主从切换或故障自动切换时,集群的实例角色会发生变化,而 Haproxy 的配置却不会自动发生变化。对于有多个从库的集群来说,这通常并不是一个问题。 然而对于一主一从,从库跑Offline查询的精简小集群而言,主从切换意味着从库变成了主库(健康检查失效),原来的主库变成了从库(不在 Offline 后端列表中),于是没有实例可以承载 Offline 服务了,因此需要手动 重载服务 以使变更生效。

如果您的业务模型较为简单,您可以考虑剔除 Default 服务与 Offline 服务,使用 Primary 服务与 Replica 服务直连数据库。


重载服务

当集群成员发生变化,如添加/删除副本、主备切换或调整相对权重时, 你需要 重载服务 以使更改生效。

bin/pgsql-svc <cls> [ip...]         # 为 lb 集群或 lb 实例重载服务
# ./pgsql.yml -t pg_service         # 重载服务的实际 ansible 任务

接入服务

Pigsty的服务交付边界止步于集群的HAProxy,用户可以用各种手段访问这些负载均衡器。

典型的做法是使用 DNS 或 VIP 接入,将其绑定在集群所有或任意数量的负载均衡器上。

pigsty-access.jpg

你可以使用不同的 主机 & 端口 组合,它们以不同的方式提供 PostgreSQL 服务。

主机

类型样例描述
集群域名pg-test通过集群域名访问(由 dnsmasq @ infra 节点解析)
集群 VIP 地址10.10.10.3通过由 vip-manager 管理的 L2 VIP 地址访问,绑定到主节点
实例主机名pg-test-1通过任何实例主机名访问(由 dnsmasq @ infra 节点解析)
实例 IP 地址10.10.10.11访问任何实例的 IP 地址

端口

Pigsty 使用不同的 端口 来区分 pg services

端口服务类型描述
5432postgres数据库直接访问 postgres 服务器
6432pgbouncer中间件访问 postgres 前先通过连接池中间件
5433primary服务访问主 pgbouncer (或 postgres)
5434replica服务访问备份 pgbouncer (或 postgres)
5436default服务访问主 postgres
5438offline服务访问离线 postgres

组合

# 通过集群域名访问
postgres://test@pg-test:5432/test # DNS -> L2 VIP -> 主直接连接
postgres://test@pg-test:6432/test # DNS -> L2 VIP -> 主连接池 -> 主
postgres://test@pg-test:5433/test # DNS -> L2 VIP -> HAProxy -> 主连接池 -> 主
postgres://test@pg-test:5434/test # DNS -> L2 VIP -> HAProxy -> 备份连接池 -> 备份
postgres://dbuser_dba@pg-test:5436/test # DNS -> L2 VIP -> HAProxy -> 主直接连接 (用于管理员)
postgres://dbuser_stats@pg-test:5438/test # DNS -> L2 VIP -> HAProxy -> 离线直接连接 (用于 ETL/个人查询)

# 通过集群 VIP 直接访问
postgres://test@10.10.10.3:5432/test # L2 VIP -> 主直接访问
postgres://test@10.10.10.3:6432/test # L2 VIP -> 主连接池 -> 主
postgres://test@10.10.10.3:5433/test # L2 VIP -> HAProxy -> 主连接池 -> 主
postgres://test@10.10.10.3:5434/test # L2 VIP -> HAProxy -> 备份连接池 -> 备份
postgres://dbuser_dba@10.10.10.3:5436/test # L2 VIP -> HAProxy -> 主直接连接 (用于管理员)
postgres://dbuser_stats@10.10.10.3::5438/test # L2 VIP -> HAProxy -> 离线直接连接 (用于 ETL/个人查询)

# 直接指定任何集群实例名
postgres://test@pg-test-1:5432/test # DNS -> 数据库实例直接连接 (单例访问)
postgres://test@pg-test-1:6432/test # DNS -> 连接池 -> 数据库
postgres://test@pg-test-1:5433/test # DNS -> HAProxy -> 连接池 -> 数据库读/写
postgres://test@pg-test-1:5434/test # DNS -> HAProxy -> 连接池 -> 数据库只读
postgres://dbuser_dba@pg-test-1:5436/test # DNS -> HAProxy -> 数据库直接连接
postgres://dbuser_stats@pg-test-1:5438/test # DNS -> HAProxy -> 数据库离线读/写

# 直接指定任何集群实例 IP 访问
postgres://test@10.10.10.11:5432/test # 数据库实例直接连接 (直接指定实例, 没有自动流量分配)
postgres://test@10.10.10.11:6432/test # 连接池 -> 数据库
postgres://test@10.10.10.11:5433/test # HAProxy -> 连接池 -> 数据库读/写
postgres://test@10.10.10.11:5434/test # HAProxy -> 连接池 -> 数据库只读
postgres://dbuser_dba@10.10.10.11:5436/test # HAProxy -> 数据库直接连接
postgres://dbuser_stats@10.10.10.11:5438/test # HAProxy -> 数据库离线读-写

# 智能客户端:自动进行读写分离
postgres://test@10.10.10.11:6432,10.10.10.12:6432,10.10.10.13:6432/test?target_session_attrs=primary
postgres://test@10.10.10.11:6432,10.10.10.12:6432,10.10.10.13:6432/test?target_session_attrs=prefer-standby

覆盖服务

你可以通过多种方式覆盖默认的服务配置,一种常见的需求是让 Primary服务Replica服务 绕过Pgbouncer连接池,直接访问 PostgreSQL 数据库。

为了实现这一点,你可以将 pg_default_service_dest 更改为 postgres,这样所有服务定义中 svc.dest='default' 的服务都会使用 postgres 而不是默认的 pgbouncer 作为目标。

如果您已经将 Primary服务 指向了 PostgreSQL,那么 default服务 就会比较多余,可以考虑移除。

如果您不需要区分个人交互式查询,分析/ETL慢查询,可以考虑从默认服务列表 pg_default_services 中移除 Offline服务

如果您不需要只读从库来分担在线只读流量,也可以从默认服务列表中移除 Replica服务


委托服务

Pigsty 通过节点上的 haproxy 暴露 PostgreSQL 服务。整个集群中的所有 haproxy 实例都使用相同的 服务定义 进行配置。

但是,你可以将 pg 服务委托给特定的节点分组(例如,专门的 haproxy 负载均衡器集群),而不是 PostgreSQL 集群成员上的 haproxy。

为此,你需要使用 pg_default_services 覆盖默认的服务定义,并将 pg_service_provider 设置为代理组名称。

例如,此配置将在端口 10013 的 proxy haproxy 节点组上公开 pg 集群的主服务。

pg_service_provider: proxy       # 使用端口 10013 上的 `proxy` 组的负载均衡器
pg_default_services:  [{ name: primary ,port: 10013 ,dest: postgres  ,check: /primary   ,selector: "[]" }]

用户需要确保每个委托服务的端口,在代理集群中都是唯一的。

在 43 节点生产环境仿真 沙箱 中提供了一个使用专用负载均衡器集群的例子:prod.yml

20.4 - 认证 / HBA

Pigsty 中基于主机的身份认证 HBA(Host-Based Authentication)详解。

Pigsty 中基于主机的身份认证 HBA(Host-Based Authentication)详解。

认证是 访问控制权限系统 的基石,PostgreSQL 拥有多种 认证 方法。

这里主要介绍 HBA:Host Based Authentication,HBA规则定义了哪些用户能够通过哪些方式从哪些地方访问哪些数据库。


客户端认证

要连接到PostgreSQL数据库,用户必须先经过认证(默认使用密码)。

您可以在连接字符串中提供密码(不安全)或使用PGPASSWORD环境变量或.pgpass文件传递密码。参考 psql 文档和 PostgreSQL连接字符串 以获取更多详细信息。

psql 'host=<host> port=<port> dbname=<dbname> user=<username> password=<password>'
psql postgres://<username>:<password>@<host>:<port>/<dbname>
PGPASSWORD=<password>; psql -U <username> -h <host> -p <port> -d <dbname>

例如,连接 Pigsty 默认的 meta 数据库,可以使用以下连接串:

psql 'host=10.10.10.10 port=5432 dbname=meta user=dbuser_dba password=DBUser.DBA'
psql postgres://dbuser_dba:DBUser.DBA@10.10.10.10:5432/meta
PGPASSWORD=DBUser.DBA; psql -U dbuser_dba -h 10.10.10.10 -p 5432 -d meta

默认配置下,Pigsty会启用服务端 SSL 加密,但不验证客户端 SSL 证书。要使用客户端SSL证书连接,你可以使用PGSSLCERTPGSSLKEY环境变量或sslkeysslcert参数提供客户端参数。

psql 'postgres://dbuser_dba:DBUser.DBA@10.10.10.10:5432/meta?sslkey=/path/to/dbuser_dba.key&sslcert=/path/to/dbuser_dba.crt'

客户端证书(CN = 用户名)可以使用本地CA与 cert.yml 剧本签发。


定义HBA

在Pigsty中,有四个与HBA规则有关的参数:

这些都是 HBA 规则对象的数组,每个HBA规则都是以下两种形式之一的对象:

1. 原始形式

原始形式的 HBA 与 PostgreSQL pg_hba.conf 的格式几乎完全相同:

- title: allow intranet password access
  role: common
  rules:
    - host   all  all  10.0.0.0/8      md5
    - host   all  all  172.16.0.0/12   md5
    - host   all  all  192.168.0.0/16  md5

在这种形式中,rules 字段是字符串数组,每一行都是条原始形式的 HBA规则title 字段会被渲染为一条注释,解释下面规则的作用。

role 字段用于说明该规则适用于哪些实例角色,当实例的 pg_rolerole相同时,HBA规则将被添加到这台实例的 HBA 中。

  • role: common的HBA规则将被添加到所有实例上。
  • role: primary 的 HBA 规则只会添加到主库实例上。
  • role: replica 的 HBA 规则只会添加到从库实例上。
  • role: offline的HBA规则将被添加到离线实例上( pg_role = offlinepg_offline_query = true

2. 别名形式

别名形式允许您用更简单清晰便捷的方式维护 HBA 规则:它用addrauthuserdb 字段替换了 rulestitleroleorder 字段则仍然生效。

- addr: 'intra'    # world|intra|infra|admin|local|localhost|cluster|<cidr>
  auth: 'pwd'      # trust|pwd|ssl|cert|deny|<official auth method>
  user: 'all'      # all|${dbsu}|${repl}|${admin}|${monitor}|<user>|<group>
  db: 'all'        # all|replication|....
  rules: []        # raw hba string precedence over above all
  title: allow intranet password access
  order: 100       # 排序权重,数字小的排前面(可选,默认追加到最后)
  • addr: where 哪些IP地址段受本条规则影响?
    • world: 所有的IP地址
    • intra: 所有的内网IP地址段: '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'
    • infra: Infra节点的IP地址
    • admin: admin_ip 管理节点的IP地址
    • local: 本地 Unix Socket
    • localhost: 本地 Unix Socket 以及TCP 127.0.0.1/32 环回地址
    • cluster: 同一个 PostgresQL 集群所有成员的IP地址
    • <cidr>: 一个特定的 CIDR 地址块或IP地址
  • auth: how 本条规则指定的认证方式?
    • deny: 拒绝访问
    • trust: 直接信任,不需要认证
    • pwd: 密码认证,根据 pg_pwd_enc 参数选用 md5scram-sha-256 认证
    • sha/scram-sha-256:强制使用 scram-sha-256 密码认证方式。
    • md5: md5 密码认证方式,但也可以兼容 scram-sha-256 认证,不建议使用。
    • ssl: 在密码认证 pwd 的基础上,强制要求启用SSL
    • ssl-md5: 在密码认证 md5 的基础上,强制要求启用SSL
    • ssl-sha: 在密码认证 sha 的基础上,强制要求启用SSL
    • os/ident: 使用操作系统用户的身份进行 ident 认证
    • peer: 使用 peer 认证方式,类似于 os ident
    • cert: 使用基于客户端SSL证书的认证方式,证书CN为用户名
  • user: who:哪些用户受本条规则影响?
  • db: which:哪些数据库受本条规则影响?
    • all: 所有数据库
    • replication: 允许建立复制连接(不指定特定数据库)
    • 某个特定的数据库

3. 定义位置

通常,全局的HBA定义在 all.vars 中,如果您想要修改全局默认的HBA规则,可以从 full.yml 模板中复制一份到 all.vars 中进行修改。

而集群特定的 HBA 规则定义在数据库的集群级配置中:

下面是一些集群HBA规则的定义例子:

pg-meta:
  hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
  vars:
    pg_cluster: pg-meta
    pg_hba_rules:
      - { user: dbuser_view ,db: all    ,addr: infra        ,auth: pwd  ,title: '允许 dbuser_view 从基础设施节点密码访问所有库'}
      - { user: all         ,db: all    ,addr: 100.0.0.0/8  ,auth: pwd  ,title: '允许所有用户从K8S网段密码访问所有库'          }
      - { user: '${admin}'  ,db: world  ,addr: 0.0.0.0/0    ,auth: cert ,title: '允许管理员用户从任何地方用客户端证书登陆'       }

重载HBA

HBA 是一个静态的规则配置文件,修改后需要重载才能生效。默认的 HBA 规则集合因为不涉及 Role 与集群成员,所以通常不需要重载。

如果您设计的 HBA 使用了特定的实例角色限制,或者集群成员限制,那么当集群实例成员发生变化(新增/下线/主从切换),一部分HBA规则的生效条件/涉及范围发生变化,通常也需要 重载HBA 以反映最新变化。

要重新加载 postgres/pgbouncer 的 hba 规则:

bin/pgsql-hba <cls>                 # 重新加载集群 `<cls>` 的 hba 规则
bin/pgsql-hba <cls> ip1 ip2...      # 重新加载特定实例的 hba 规则

底层实际执行的 Ansible 剧本命令为:

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

默认HBA

Pigsty 有一套默认的 HBA 规则,对于绝大多数场景来说,它已经足够安全了。这些规则使用别名形式,因此基本可以自我解释。

pg_default_hba_rules:             # postgres 全局默认的HBA规则,按 order 排序
  - {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}
pgb_default_hba_rules:            # pgbouncer 全局默认的HBA规则,按 order 排序
  - {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}

注意order 字段控制规则渲染顺序。0-99 用于高优先规则(如黑名单),100-650 为默认规则区间,1000+ 用于追加规则。详见 HBA 配置

示例:渲染 pg_hba.conf
#==============================================================#
# File      :   pg_hba.conf
# Desc      :   Postgres HBA Rules for pg-meta-1 [primary]
# Time      :   2023-01-11 15:19
# Host      :   pg-meta-1 @ 10.10.10.10:5432
# Path      :   /pg/data/pg_hba.conf
# Note      :   ANSIBLE MANAGED, DO NOT CHANGE!
# Author    :   Ruohang Feng (rh@vonng.com)
# License   :   Apache-2.0
#==============================================================#

# addr alias
# local     : /var/run/postgresql
# admin     : 10.10.10.10
# infra     : 10.10.10.10
# intra     : 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16

# user alias
# dbsu    :  postgres
# repl    :  replicator
# monitor :  dbuser_monitor
# admin   :  dbuser_dba

# dbsu access via local os user ident [default]
local    all                postgres                              ident

# dbsu replication from local os ident [default]
local    replication        postgres                              ident

# replicator replication from localhost [default]
local    replication        replicator                            scram-sha-256
host     replication        replicator         127.0.0.1/32       scram-sha-256

# replicator replication from intranet [default]
host     replication        replicator         10.0.0.0/8         scram-sha-256
host     replication        replicator         172.16.0.0/12      scram-sha-256
host     replication        replicator         192.168.0.0/16     scram-sha-256

# replicator postgres db from intranet [default]
host     postgres           replicator         10.0.0.0/8         scram-sha-256
host     postgres           replicator         172.16.0.0/12      scram-sha-256
host     postgres           replicator         192.168.0.0/16     scram-sha-256

# monitor from localhost with password [default]
local    all                dbuser_monitor                        scram-sha-256
host     all                dbuser_monitor     127.0.0.1/32       scram-sha-256

# monitor from infra host with password [default]
host     all                dbuser_monitor     10.10.10.10/32     scram-sha-256

# admin @ infra nodes with pwd & ssl [default]
hostssl  all                dbuser_dba         10.10.10.10/32     scram-sha-256

# admin @ everywhere with ssl & pwd [default]
hostssl  all                dbuser_dba         0.0.0.0/0          scram-sha-256

# pgbouncer read/write via local socket [default]
local    all                +dbrole_readonly                      scram-sha-256
host     all                +dbrole_readonly   127.0.0.1/32       scram-sha-256

# read/write biz user via password [default]
host     all                +dbrole_readonly   10.0.0.0/8         scram-sha-256
host     all                +dbrole_readonly   172.16.0.0/12      scram-sha-256
host     all                +dbrole_readonly   192.168.0.0/16     scram-sha-256

# allow etl offline tasks from intranet [default]
host     all                +dbrole_offline    10.0.0.0/8         scram-sha-256
host     all                +dbrole_offline    172.16.0.0/12      scram-sha-256
host     all                +dbrole_offline    192.168.0.0/16     scram-sha-256

# allow application database intranet access [common] [DISABLED]
#host    kong            dbuser_kong         10.0.0.0/8          md5
#host    bytebase        dbuser_bytebase     10.0.0.0/8          md5
#host    grafana         dbuser_grafana      10.0.0.0/8          md5
示例: 渲染 pgb_hba.conf
#==============================================================#
# File      :   pgb_hba.conf
# Desc      :   Pgbouncer HBA Rules for pg-meta-1 [primary]
# Time      :   2023-01-11 15:28
# Host      :   pg-meta-1 @ 10.10.10.10:5432
# Path      :   /etc/pgbouncer/pgb_hba.conf
# Note      :   ANSIBLE MANAGED, DO NOT CHANGE!
# Author    :   Ruohang Feng (rh@vonng.com)
# License   :   Apache-2.0
#==============================================================#

# PGBOUNCER HBA RULES FOR pg-meta-1 @ 10.10.10.10:6432
# ansible managed: 2023-01-11 14:30:58

# addr alias
# local     : /var/run/postgresql
# admin     : 10.10.10.10
# infra     : 10.10.10.10
# intra     : 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16

# user alias
# dbsu    :  postgres
# repl    :  replicator
# monitor :  dbuser_monitor
# admin   :  dbuser_dba

# dbsu local admin access with os ident [default]
local    pgbouncer          postgres                              peer

# allow all user local access with pwd [default]
local    all                all                                   scram-sha-256
host     all                all                127.0.0.1/32       scram-sha-256

# monitor access via intranet with pwd [default]
host     pgbouncer          dbuser_monitor     10.0.0.0/8         scram-sha-256
host     pgbouncer          dbuser_monitor     172.16.0.0/12      scram-sha-256
host     pgbouncer          dbuser_monitor     192.168.0.0/16     scram-sha-256

# reject all other monitor access addr [default]
host     all                dbuser_monitor     0.0.0.0/0          reject

# admin access via intranet with pwd [default]
host     all                dbuser_dba         10.0.0.0/8         scram-sha-256
host     all                dbuser_dba         172.16.0.0/12      scram-sha-256
host     all                dbuser_dba         192.168.0.0/16     scram-sha-256

# reject all other admin access addr [default]
host     all                dbuser_dba         0.0.0.0/0          reject

# allow all user intra access with pwd [default]
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

安全加固

对于那些需要更高安全性的场合,我们提供了一个安全加固的配置模板 security.yml,使用了以下的默认 HBA 规则集:

pg_default_hba_rules:             # postgres host-based auth rules by default, order by `order`
  - {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: ssl   ,title: 'replicator replication from localhost',order: 200}
  - {user: '${repl}'    ,db: replication ,addr: intra     ,auth: ssl   ,title: 'replicator replication from intranet' ,order: 250}
  - {user: '${repl}'    ,db: postgres    ,addr: intra     ,auth: ssl   ,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: ssl   ,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: cert  ,title: 'admin @ everywhere with ssl & cert'   ,order: 500}
  - {user: '+dbrole_readonly',db: all    ,addr: localhost ,auth: ssl   ,title: 'pgbouncer read/write via local socket',order: 550}
  - {user: '+dbrole_readonly',db: all    ,addr: intra     ,auth: ssl   ,title: 'read/write biz user via password'     ,order: 600}
  - {user: '+dbrole_offline' ,db: all    ,addr: intra     ,auth: ssl   ,title: 'allow etl offline tasks from intranet',order: 650}
pgb_default_hba_rules:            # pgbouncer host-based authentication rules, order by `order`
  - {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: ssl   ,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: ssl   ,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: ssl   ,title: 'allow all user intra access with pwd' ,order: 400}

更多信息,请参考 安全加固 一节。

20.5 - 访问控制

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

Pigsty 提供了一套开箱即用的,基于 角色系统权限系统 的访问控制模型。

权限控制很重要,但很多用户做不好。因此 Pigsty 提供了一套开箱即用的精简访问控制模型,为您的集群安全性提供一个兜底。


角色系统

Pigsty 默认的角色系统包含四个 默认角色 和四个 默认用户

角色名称属性所属描述
dbrole_readonlyNOLOGIN角色:全局只读访问
dbrole_readwriteNOLOGINdbrole_readonly角色:全局读写访问
dbrole_adminNOLOGINpg_monitor,dbrole_readwrite角色:管理员/对象创建
dbrole_offlineNOLOGIN角色:受限的只读访问
postgresSUPERUSER系统超级用户
replicatorREPLICATIONpg_monitor,dbrole_readonly系统复制用户
dbuser_dbaSUPERUSERdbrole_adminpgsql 管理用户
dbuser_monitorpg_monitorpgsql 监控用户

这些 角色与用户 的详细定义如下所示:

pg_default_roles:                 # 全局默认的角色与系统用户
  - { name: dbrole_readonly  ,login: false ,comment: role for global read-only access     }
  - { name: dbrole_offline   ,login: false ,comment: role for restricted read-only access }
  - { name: dbrole_readwrite ,login: false ,roles: [dbrole_readonly] ,comment: role for global read-write access }
  - { name: dbrole_admin     ,login: false ,roles: [pg_monitor, dbrole_readwrite] ,comment: role for object creation }
  - { name: postgres     ,superuser: true  ,comment: system superuser }
  - { name: replicator ,replication: true  ,roles: [pg_monitor, dbrole_readonly] ,comment: system replicator }
  - { name: dbuser_dba   ,superuser: true  ,roles: [dbrole_admin]  ,pgbouncer: true ,pool_mode: session, pool_connlimit: 16 ,comment: pgsql admin user }
  - { name: dbuser_monitor ,roles: [pg_monitor] ,pgbouncer: true ,parameters: {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment: pgsql monitor user }

默认角色

Pigsty 中有四个默认角色:

  • 业务只读 (dbrole_readonly): 用于全局只读访问的角色。如果别的业务想要此库只读访问权限,可以使用此角色。
  • 业务读写 (dbrole_readwrite): 用于全局读写访问的角色,主属业务使用的生产账号应当具有数据库读写权限
  • 业务管理员 (dbrole_admin): 拥有DDL权限的角色,通常用于业务管理员,或者需要在应用中建表的场景(比如各种业务软件)
  • 离线只读访问 (dbrole_offline): 受限的只读访问角色(只能访问 offline 实例,通常是个人用户,ETL工具账号)

默认角色在 pg_default_roles 中定义,除非您确实知道自己在干什么,建议不要更改默认角色的名称。

- { name: dbrole_readonly  , login: false , comment: role for global read-only access  }                            # 生产环境的只读角色
- { name: dbrole_offline ,   login: false , comment: role for restricted read-only access (offline instance) }      # 受限的只读角色
- { name: dbrole_readwrite , login: false , roles: [dbrole_readonly], comment: role for global read-write access }  # 生产环境的读写角色
- { name: dbrole_admin , login: false , roles: [pg_monitor, dbrole_readwrite] , comment: role for object creation } # 生产环境的 DDL 更改角色

默认用户

Pigsty 也有四个默认用户(系统用户):

  • 超级用户 (postgres),集群的所有者和创建者,与操作系统 dbsu 名称相同。
  • 复制用户 (replicator),用于主-从复制的系统用户。
  • 监控用户 (dbuser_monitor),用于监控数据库和连接池指标的用户。
  • 管理用户 (dbuser_dba),执行日常操作和数据库更改的管理员用户。

这4个默认用户的用户名/密码通过4对专用参数进行定义,并在很多地方引用:

在生产部署中记得更改这些密码,不要使用默认值!

pg_dbsu: postgres                             # 数据库超级用户名,这个用户名建议不要修改。
pg_dbsu_password: ''                          # 数据库超级用户密码,这个密码建议留空!禁止dbsu密码登陆。
pg_replication_username: replicator           # 系统复制用户名
pg_replication_password: DBUser.Replicator    # 系统复制密码,请务必修改此密码!
pg_monitor_username: dbuser_monitor           # 系统监控用户名
pg_monitor_password: DBUser.Monitor           # 系统监控密码,请务必修改此密码!
pg_admin_username: dbuser_dba                 # 系统管理用户名
pg_admin_password: DBUser.DBA                 # 系统管理密码,请务必修改此密码!

如果您修改默认用户的参数,在 pg_default_roles 中修改相应的角色 定义 即可:

- { name: postgres     ,superuser: true                                          ,comment: system superuser }
- { name: replicator ,replication: true  ,roles: [pg_monitor, dbrole_readonly]   ,comment: system replicator }
- { name: dbuser_dba   ,superuser: true  ,roles: [dbrole_admin]  ,pgbouncer: true ,pool_mode: session, pool_connlimit: 16 , comment: pgsql admin user }
- { name: dbuser_monitor   ,roles: [pg_monitor, dbrole_readonly] ,pgbouncer: true ,parameters: {log_min_duration_statement: 1000 } ,pool_mode: session ,pool_connlimit: 8 ,comment: pgsql monitor user }

权限系统

Pigsty 拥有一套开箱即用的权限模型,该模型与 默认角色 一起配合工作。

  • 所有用户都可以访问所有模式。
  • 只读用户(dbrole_readonly)可以从所有表中读取数据。(SELECT,EXECUTE)
  • 读写用户(dbrole_readwrite)可以向所有表中写入数据并运行 DML。(INSERT,UPDATE,DELETE)。
  • 管理员用户(dbrole_admin)可以创建对象并运行 DDL(CREATE,USAGE,TRUNCATE,REFERENCES,TRIGGER)。
  • 离线用户(dbrole_offline)类似只读用户,但访问受到限制,只允许访问 离线实例pg_role = 'offline'pg_offline_query = true
  • 由管理员用户创建的对象将具有正确的权限。
  • 所有数据库上都配置了默认权限,包括模板数据库。
  • 数据库连接权限由数据库 定义 管理。
  • 默认撤销PUBLIC在数据库和public模式下的CREATE权限。

对象权限

数据库中新建对象的默认权限由参数 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

由管理员新创建的对象,默认将会上述权限。使用 \ddp+ 可以查看这些默认权限:

类型访问权限
函数=X
dbrole_readonly=X
dbrole_offline=X
dbrole_admin=X
模式dbrole_readonly=U
dbrole_offline=U
dbrole_admin=UC
序列号dbrole_readonly=r
dbrole_offline=r
dbrole_readwrite=wU
dbrole_admin=rwU
dbrole_readonly=r
dbrole_offline=r
dbrole_readwrite=awd
dbrole_admin=arwdDxt

默认权限

ALTER DEFAULT PRIVILEGES 允许您设置将来创建的对象的权限。 它不会影响已经存在对象的权限,也不会影响非管理员用户创建的对象。

在 Pigsty 中,默认权限针对三个角色进行定义:

{% for priv in pg_default_privileges %}
ALTER DEFAULT PRIVILEGES FOR ROLE {{ pg_dbsu }} {{ priv }};
{% endfor %}

{% for priv in pg_default_privileges %}
ALTER DEFAULT PRIVILEGES FOR ROLE {{ pg_admin_username }} {{ priv }};
{% endfor %}

-- 对于其他业务管理员而言,它们应当在执行 DDL 前执行 SET ROLE dbrole_admin,从而使用对应的默认权限配置。
{% for priv in pg_default_privileges %}
ALTER DEFAULT PRIVILEGES FOR ROLE "dbrole_admin" {{ priv }};
{% endfor %}

这些内容将会被 PG集群初始化模板 pg-init-template.sql 所使用,在集群初始化的过程中渲染并输出至 /pg/tmp/pg-init-template.sql。 该命令会在 template1postgres 数据库中执行,新创建的数据库会通过模板 template1 继承这些默认权限配置。

也就是说,为了维持正确的对象权限,您必须用管理员用户来执行 DDL,它们可以是:

  1. {{ pg_dbsu }},默认为 postgres
  2. {{ pg_admin_username }},默认为 dbuser_dba
  3. 授予了 dbrole_admin 角色的业务管理员用户(通过 SET ROLE 切换为 dbrole_admin 身份)。

使用 postgres 作为全局对象所有者是明智的。如果您希望以业务管理员用户身份创建对象,创建之前必须使用 SET ROLE dbrole_admin 来维护正确的权限。

当然,您也可以在数据库中通过 ALTER DEFAULT PRIVILEGE FOR ROLE <some_biz_admin> XXX 来显式对业务管理员授予默认权限。


数据库权限

在 Pigsty 中,数据库(Database)层面的权限在 数据库定义 中被涵盖。

数据库有三个级别的权限:CONNECTCREATETEMP,以及一个特殊的’权限’:OWNERSHIP

- name: meta         # 必选,`name` 是数据库定义中唯一的必选字段
  owner: postgres    # 可选,数据库所有者,默认为 postgres
  allowconn: true    # 可选,是否允许连接,默认为 true。显式设置 false 将完全禁止连接到此数据库
  revokeconn: false  # 可选,撤销公共连接权限。默认为 false,设置为 true 时,属主和管理员之外用户的 CONNECT 权限会被回收
  • 如果 owner 参数存在,它作为数据库属主,替代默认的 {{ pg_dbsu }}(通常也就是postgres
  • 如果 revokeconnfalse,所有用户都有数据库的 CONNECT 权限,这是默认的行为。
  • 如果显式设置了 revokeconntrue
    • 数据库的 CONNECT 权限将从 PUBLIC 中撤销:普通用户无法连接上此数据库
    • CONNECT 权限将被显式授予 {{ pg_replication_username }}{{ pg_monitor_username }}{{ pg_admin_username }}
    • CONNECT 权限将 GRANT OPTION 被授予数据库属主,数据库属主用户可以自行授权其他用户连接权限。
  • revokeconn 选项可用于在同一个集群间隔离跨数据库访问,您可以为每个数据库创建不同的业务用户作为属主,并为它们设置 revokeconn 选项。
示例:数据库隔离
pg-infra:
  hosts:
    10.10.10.40: { pg_seq: 1, pg_role: primary }
    10.10.10.41: { pg_seq: 2, pg_role: replica , pg_offline_query: true }
  vars:
    pg_cluster: pg-infra
    pg_users:
      - { name: dbuser_confluence, password: mc2iohos , pgbouncer: true, roles: [ dbrole_admin ] }
      - { name: dbuser_gitlab, password: sdf23g22sfdd , pgbouncer: true, roles: [ dbrole_readwrite ] }
      - { name: dbuser_jira, password: sdpijfsfdsfdfs , pgbouncer: true, roles: [ dbrole_admin ] }
    pg_databases:
      - { name: confluence , revokeconn: true, owner: dbuser_confluence , connlimit: 100 }
      - { name: gitlab , revokeconn: true, owner: dbuser_gitlab, connlimit: 100 }
      - { name: jira , revokeconn: true, owner: dbuser_jira , connlimit: 100 }

CREATE权限

出于安全考虑,Pigsty 默认从 PUBLIC 撤销数据库上的 CREATE 权限,从 PostgreSQL 15 开始这也是默认行为。

数据库属主总是可以根据实际需要,来自行调整 CREATE 权限。