常见问题

PostgreSQL 常见问题答疑

PGSQL初始化失败:ABORT due to postgres exists

这意味着正在初始化的 PostgreSQL 实例已经存在了, 将 pg_clean 设置为 true,并将 pg_safeguard 设置为 false,就可以在执行 pgsql.yml 期间强制清理现存实例。

如果 pg_cleantrue (并且 pg_safeguard 也为 false),pgsql.yml 剧本将会移除现有的 pgsql 数据并重新初始化为新的,这使得这个剧本真正幂等。

你可以通过使用一个特殊的任务标签 pg_purge 来强制清除现有的 PostgreSQL 数据,这个标签任务会忽略 pg_cleanpg_safeguard 的设置,所以非常危险。

./pgsql.yml -t pg_clean      # 优先考虑 pg_clean 和 pg_safeguard
./pgsql.yml -t pg_purge      # 忽略 pg_clean 和 pg_safeguard

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

———————–`

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>

如何安装其他的PostgreSQL大版本:12 - 14,以及 16beta

要安装 PostgreSQL 12 - 15,你必须在配置清单中设置 pg_version12131415,通常在集群级别配置这个参数。

pg_version: 16                    # 在此模板中安装 pg 16
pg_libs: 'pg_stat_statements, auto_explain' # 从 pg 16 beta 中移除 timescaledb,因为它不可用
pg_extensions: []                 # 目前缺少 pg16 扩展

prod.yml 43 节点生产环境仿真模板中提供了安装 12 - 16 大版本集群的示例。

详情请参考 PGSQL配置:切换大版本


如何为 PostgreSQL 启用大页/HugePage?

使用 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

如何确保故障转移中数据不丢失?

使用 crit.yml 参数模板,设置 pg_rpo0,或配置集群为同步提交模式。

考虑使用 同步备库法定多数提交 来确保故障转移过程中的零数据丢失。

更多细节,可以参考 安全考量 - 可用性 的相关介绍。


磁盘写满了如何抢救?

如果磁盘写满了,连 Shell 命令都无法执行,rm -rf /pg/dummy 可以释放一些救命空间。

默认情况下,pg_dummy_filesize 设置为 64MB。在生产环境中,建议将其增加到 8GB 或更大。

它将被放置在 PGSQL 主数据磁盘上的 /pg/dummy 路径下。你可以删除该文件以释放一些紧急空间:至少可以让你在该节点上运行一些 shell 脚本来进一步回收其他空间。


当集群数据已经损坏时如何创建副本?

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 中提供了详细的监控配置说明。


如何手工从 Prometheus 中移除 PostgreSQL 监控对象?

./pgsql-rm.yml -t prometheus -l <cls>     # 将集群 'cls' 的所有实例从 prometheus 中移除
bin/pgmon-rm <ins>     # 用于从 Prometheus 中移除单个实例 'ins' 的监控对象,特别适合移除添加的外部实例