Geo PostgreSQL 副本故障排查

  • Tier: 专业版, 旗舰版
  • Offering: 极狐GitLab 私有化部署

以下部分概述了解决复制错误消息(由 Database replication working? ... nogeo:check output 中指示)的方法。此处的说明大多假设为单节点的 Geo Linux 软件包部署,可能需要根据不同的环境进行调整。

删除不活跃的复制槽#

当复制客户端(一个次要站点)连接到复制槽后断开连接时,复制槽会被标记为“不活跃”。不活跃的复制槽会导致 WAL 文件被保留,因为它们在客户端重新连接时会发送给客户端,并且槽再次变为活跃状态。如果次要站点无法重新连接,请使用以下步骤删除其对应的不活跃复制槽:

  1. 在 Geo 主站点的数据库节点上启动一个 PostgreSQL 控制台会话

    shell
    sudo gitlab-psql -d gitlabhq_production
    使用 `gitlab-rails dbconsole` 无法工作,因为管理复制槽需要超级用户权限。
  2. 查看复制槽并在其不活跃时删除它们:

    sql
    SELECT * FROM pg_replication_slots;

    其中 activef 的槽是不活跃的。

  • 如果此槽应为活跃状态,因为您已配置了使用该槽的次要站点:

    • 查看 次要站点的 PostgreSQL 日志,以查看复制未运行的原因。

    • 如果次要站点无法重新连接:

      1. 使用 PostgreSQL 控制台会话删除该槽:

        sql
        SELECT pg_drop_replication_slot('<name_of_inactive_slot>');
      2. 重新启动复制过程,以正确地重新创建复制槽。

  • 如果您不再使用该槽(例如,您不再启用 Geo),请按照步骤删除该 Geo 站点

消息:WARNING: oldest xmin is far in the pastpg_wal 尺寸增长#

如果一个复制槽不活跃,与该槽对应的 pg_wal 日志将被保留(或直到槽再次活跃)。这会导致磁盘使用量持续增长,并且以下消息会在 PostgreSQL 日志 中反复出现:

plaintext
WARNING: oldest xmin is far in the past HINT: Close open transactions soon to avoid wraparound problems. You might also need to commit or roll back old prepared transactions, or drop stale replication slots.

要解决此问题,您应删除不活跃的复制槽并重新启动复制。

消息:ERROR: replication slots can only be used if max_replication_slots > 0#

这意味着需要在数据库上设置 max_replication_slots PostgreSQL 变量。此设置默认为 1。如果您有更多的次要站点,可能需要增加此值。

确保重新启动 PostgreSQL 以使其生效。有关更多详细信息,请参阅 PostgreSQL 复制设置指南。

消息:replication slot "geo_secondary_my_domain_com" does not exist#

当 PostgreSQL 没有为该名称的次要站点创建复制槽时,会出现此错误:

plaintext
FATAL: could not start WAL streaming: ERROR: replication slot "geo_secondary_my_domain_com" does not exist

您可能需要在次要站点上重新运行 复制过程

消息:“设置复制时命令超过了允许的执行时间”?#

这可能发生在次要站点上启动复制过程时,并表明您的初始数据集过大,无法在默认超时时间(30 分钟)内复制完成。

重新运行 gitlab-ctl replicate-geo-database,但包含一个更大的 --backup-timeout 值:

shell
sudo gitlab-ctl \ replicate-geo-database \ --host=<primary_node_hostname> \ --slot-name=<secondary_slot_name> \ --backup-timeout=21600

这使初始复制可以在最多六个小时内完成,而不是默认的 30 分钟。根据您的安装需求进行调整。

消息:“PANIC: could not write to file pg_xlog/xlogtemp.123: No space left on device”#

确定您在数据库中是否有任何未使用的复制槽。这可能导致 pg_xlog 中积累大量日志数据。

删除不活跃的槽可以减少 pg_xlog 中使用的空间。

消息:“ERROR: canceling statement due to conflict with recovery”#

此错误消息在典型使用中很少发生,系统足够有弹性来恢复。

然而,在某些条件下,次要站点上的一些数据库查询可能运行过长时间,这增加了此错误消息的频率。这可能导致某些查询因在每次复制中被取消而永远无法完成。

这些长时间运行的查询计划在未来被移除,但作为一种解决方法,我们建议启用hot_standby_feedback。这增加了站点膨胀的可能性,因为它阻止了 VACUUM 删除最近删除的行。但它已经在 JihuLab.com 上成功地应用于生产环境。

要启用 hot_standby_feedback,在次要站点的 /etc/gitlab/gitlab.rb 中添加以下内容:

ruby
postgresql['hot_standby_feedback'] = 'on'

然后重新配置极狐GitLab:

shell
sudo gitlab-ctl reconfigure

消息:server certificate for "PostgreSQL" does not match host name#

如果您看到此错误:

plaintext
FATAL: could not connect to the primary server: server certificate for "PostgreSQL" does not match host name

这是因为 Linux 软件包自动创建的 PostgreSQL 证书包含公共名称 PostgreSQL,但复制连接到不同的主机,并且极狐GitLab 默认尝试使用 verify-full SSL 模式。

为了解决此问题,您可以:

  • 使用 --sslmode=verify-ca 参数与 replicate-geo-database 命令。
  • 对于已复制的数据库,将 /var/opt/gitlab/postgresql/data/gitlab-geo.conf 中的 sslmode=verify-full 改为 sslmode=verify-ca,并运行 gitlab-ctl restart postgresql
  • 为 PostgreSQL 配置 SSL 使用自定义证书(包括在 CN 或 SAN 中用于连接数据库的主机名),而不是使用自动生成的证书。

消息:LOG: invalid CIDR mask in address#

这发生在 postgresql['md5_auth_cidr_addresses'] 中格式错误的地址上。

plaintext
2020-03-20_23:59:57.60499 LOG: invalid CIDR mask in address "***" 2020-03-20_23:59:57.60501 CONTEXT: line 74 of configuration file "/var/opt/gitlab/postgresql/data/pg_hba.conf"

为了解决此问题,请在 /etc/gitlab/gitlab.rb 中更新 postgresql['md5_auth_cidr_addresses'] 下的 IP 地址,以符合 CIDR 格式(例如,10.0.0.1/32)。

消息:LOG: invalid IP mask "md5": Name or service not known#

当您在 postgresql['md5_auth_cidr_addresses'] 中添加没有子网掩码的 IP 地址时会发生这种情况。

plaintext
2020-03-21_00:23:01.97353 LOG: invalid IP mask "md5": Name or service not known 2020-03-21_00:23:01.97354 CONTEXT: line 75 of configuration file "/var/opt/gitlab/postgresql/data/pg_hba.conf"

要解决此问题,请在 /etc/gitlab/gitlab.rb 中添加 postgresql['md5_auth_cidr_addresses'] 下的子网掩码,以符合 CIDR 格式(例如,10.0.0.1/32)。

消息:Found data in the gitlabhq_production database#

如果在运行 gitlab-ctl replicate-geo-database 时收到错误 Found data in the gitlabhq_production database!,则表示在 projects 表中检测到数据。当检测到一个或多个项目时,操作会中止以防止意外的数据丢失。要绕过此消息,请向命令传递 --force 选项。

消息:FATAL: could not map anonymous shared memory: Cannot allocate memory#

如果看到此消息,则表示次要站点的 PostgreSQL 尝试请求比可用内存更高的内存。

在 Patroni 日志中的示例错误消息(位于 Linux 软件包安装的 /var/log/gitlab/patroni/current):

plaintext
2023-11-21_23:55:18.63727 FATAL: could not map anonymous shared memory: Cannot allocate memory 2023-11-21_23:55:18.63729 HINT: This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently 17035526144 bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.

解决方法是增加次要站点的 PostgreSQL 节点可用的内存以匹配主站点的 PostgreSQL 节点的内存需求。

调查数据库复制延迟的原因#

如果 sudo gitlab-rake geo:status 的输出显示 Database replication lag 长时间保持显著高水平,可以检查数据库复制中的主节点以确定复制过程不同部分的延迟状态。这些值被称为 write_lagflush_lagreplay_lag

在主 Geo 节点的数据库中运行以下命令以提供相关输出:

shell
1gitlab-psql -xc 'SELECT write_lag,flush_lag,replay_lag FROM pg_stat_replication;' 2 3-[ RECORD 1 ]--------------- 4write_lag | 00:00:00.072392 5flush_lag | 00:00:00.108168 6replay_lag | 00:00:00.108283

如果这些值中的一个或多个显著高,这可能表示问题并应进一步调查。在确定原因时,请考虑:

  • write_lag 表示自从 WAL 字节从主站发送后到次要站点接收但尚未刷新或应用的时间。
  • write_lag 值可能表明主节点和次要节点之间的网络性能下降或网络速度不足。
  • flush_lag 值可能表明次要节点存储设备的磁盘 I/O 性能下降或不佳。
  • replay_lag 值可能表明 PostgreSQL 中的长时间运行的事务,或需要的资源(如 CPU)的饱和。
  • write_lagflush_lag 之间的时间差表示 WAL 字节已发送到基础存储系统,但尚未报告它们已被刷新。这些数据最有可能没有完全写入持久存储,可能保存在某种易失性写缓存中。
  • flush_lagreplay_lag 之间的差异表示已成功持久化到存储的 WAL 字节,但数据库系统无法重放。

卡在 Message: pg_basebackup: initiating base backup, waiting for checkpoint to complete#

如果初始复制卡在 Message: pg_basebackup: initiating base backup, waiting for checkpoint to complete,这意味着主节点未被积极使用。这大多发生在非生产极狐GitLab 服务器或全新的极狐GitLab 安装上。

解决方法是在主节点的数据库上运行 SQL 查询 CHECKPOINT;

shell
sudo gitlab-psql -xc 'CHECKPOINT;