极狐 GitLab

故障排除 Geo PostgreSQL 复制

Tier: 专业版,旗舰版

Offering: 私有化部署

以下各节列出了修复复制错误消息(在 geo:check 输出中由 Database replication working? ... no 表示)的故障排除步骤。此处提供的说明主要假设单节点 Geo Linux 软件包部署,可能需要根据不同的环境进行调整。

移除非活跃复制槽#

当连接到复制槽的复制客户端(从站点)断开连接时,复制槽会被标记为“非活跃”。非活跃复制槽会导致 WAL 文件被保留,因为当客户端重新连接且复制槽再次变为活跃时,这些文件会被发送给客户端。如果从站点无法重新连接,请使用以下步骤移除其对应的非活跃复制槽:

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

    shell
    sudo gitlab-psql -d gitlabhq_production

    使用gitlab-rails dbconsole 不起作用,因为管理复制槽需要超级用户权限。

  2. 查看复制槽,如果它们处于非活跃状态则将其移除:

    sql
    SELECT * FROM pg_replication_slots;

    active 为 f的槽处于非活跃状态。

  • 如果该槽应当处于活跃状态,因为您有一个使用该槽配置的从站点:

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

消息:WARNING: oldest xmin is far in the past 且 pg_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

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

消息:设置复制时出现 Command exceeded allowed execution time?#

这可能发生在从站点上启动复制过程时,表明您的初始数据集太大,无法在默认超时时间(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中使用的空间量。

释放旧 PostgreSQL 数据目录占用的磁盘空间#

如果使用 Linux 软件包的站点磁盘空间不足,请删除遗留的 PostgreSQL 数据目录。站点可能会在多次 PostgreSQL 升级或 Geo 复制重新初始化过程中累积这些目录。每个目录都是数据库的完整副本。

以下目录位于 /var/opt/gitlab/postgresql/ 中。在从站点上,data 和 data.<old_version> 也位于 /var/opt/gitlab/geo-postgresql/(跟踪数据库)中:

目录创建者可安全删除的时机
data不适用永远不可删除。
data.<old_version>,例如 data.14gitlab-ctl pg-upgrade您确认升级正常工作后。
data.<unix_timestamp>,例如 data.1712345678gitlab-ctl replicate-geo-database您确认复制正常工作后。

data.<unix_timestamp> 中的时间戳显示 gitlab-ctl replicate-geo-database 替换该数据库副本的时间。该时间戳并不意味着该目录正在使用中。

如果您使用 --tmp-dir=<DIR> 运行了 gitlab-ctl pg-upgrade,则 data.<old_version> 目录位于 <DIR> 中,而不是 /var/opt/gitlab/postgresql/。在从站点上,跟踪数据库副本为 <DIR>/geo-data.<old_version>。要回退升级,请使用相同的 --tmp-dir 选项运行 gitlab-ctl revert-pg-upgrade。

不要删除 data 目录,它是正在使用的数据库。 保留您最近一次 PostgreSQL 升级产生的 data.<old_version> 目录, 直到您确认升级正常工作。 如果您使用了 --tmp-dir,请保留 <DIR> 中的目录。 在从站点上,也要保留跟踪数据库副本。 在包含多个 PostgreSQL 版本的 Linux 软件包版本上, gitlab-ctl revert-pg-upgrade 命令需要 data.<old_version> 目录。

要释放磁盘空间:

  1. 确认哪个目录正在使用。

    • 在所有站点上,运行以下命令:

      shell
      sudo gitlab-psql -c 'SHOW data_directory;'
    • 在从站点上,还要运行以下命令以检查跟踪数据库:

      shell
      sudo gitlab-geo-psql -c 'SHOW data_directory;'
  2. 列出遗留目录:

    shell
    sudo ls -d /var/opt/gitlab/*postgresql/data.*

    如果您更改了 postgresql['dir'],请改用您的自定义路径。 如果您使用 --tmp-dir=<DIR> 运行了 gitlab-ctl pg-upgrade,还要列出 <DIR> 中的目录:

    shell
    sudo ls -d <DIR>/*data.*
  3. 确认站点运行正常。

    • 在主站点上,运行以下命令。 确保输出中列出了每个从站点:

      shell
      sudo gitlab-psql -xc 'SELECT * FROM pg_stat_replication;'
    • 在从站点上,运行以下命令。确保输出中包含 Database replication working? ... yes:

      shell
      sudo gitlab-rake gitlab:geo:check
  4. 删除您不再需要的每个遗留目录。 保留您最近一次升级产生的 data.<old_version> 目录, 直到您确认升级正常工作。 为谨慎起见,还要保留最近的 data.<unix_timestamp> 目录, 直到您确认新副本正常工作,然后删除较旧的目录。

    不要删除 data。 要删除遗留目录,请使用遗留目录列表中的确切路径 运行以下命令:

    shell
    sudo rm -rf <path_to_leftover_directory>
  5. 建议。如果您删除了最近一次升级产生的 data.<old_version> 目录, 请删除版本文件。 gitlab-ctl revert-pg-upgrade 命令使用此文件来选择其默认目标版本。 要删除该文件,请运行:

    shell
    sudo rm -f /var/opt/gitlab/postgresql-version.old

有关更多信息,请参阅升级打包的 PostgreSQL 服务器。

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

在典型使用情况下,此错误消息很少出现,系统具有足够的恢复能力可以自行恢复。

但是,在某些情况下,从站点上的某些数据库查询可能会运行过长时间,这会增加此错误消息的出现频率。这可能导致某些查询因在每次复制时都被取消而永远无法完成。

这些长时间运行的查询计划在未来移除,但作为变通方法,我们建议启用 hot_standby_feedback。 这会增加主站点上出现膨胀的可能性,因为它会阻止 VACUUM 移除最近失效的行。但是,它已在 GitLab.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 模式。

要解决此问题,您可以:

  • 在 replicate-geo-database 命令中使用 --sslmode=verify-ca 参数。
  • 对于已复制的数据库,在 /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 节点的内存需求相匹配。

错误:could not open certificate file "/root/.postgresql/postgresql.crt"#

当您运行 gitlab-ctl replicate-geo-database 时,可能会遇到以下错误之一:

plaintext
could not open certificate file "/root/.postgresql/postgresql.crt": Permission denied
plaintext
could not open certificate file "/root/.postgresql/postgresql.crt": No such file or directory

出现此问题的原因是 gitlab-ctl replicate-geo-database 以 root 身份运行,而 gitlab-ctl replicate-geo-database 内部调用的 pg_basebackup 会在 /root/.postgresql/root.crt中查找 SSL CA 证书。当您使用 sslmode=verify-ca 或 sslmode=verify-full 时,需要此证书。

要解决此问题:

  1. 在从站点上也为 root 用户安装该证书。 使用您从主站点复制的同一个 server.crt 文件:

    shell
    1install \ 2 -D \ 3 -o root \ 4 -g root \ 5 -m 0400 \ 6 -T server.crt /root/.postgresql/root.crt
  2. 再次运行复制命令。

当身份验证因其他原因失败时,也可能出现此问题, 例如 gitlab_replicator 用户的密码不正确。 如果为 root 安装证书后仍未解决问题, 请确认您的复制凭据是否正确。

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

如果 sudo gitlab-rake gitlab:geo:status的输出显示 Database replication lag 随时间推移仍然显著偏高,可以检查数据库复制中的主节点,以确定数据库复制过程不同部分的延迟状态。这些值称为 write_lag、flush_lag 和 replay_lag。有关更多信息,请参阅 PostgreSQL 官方文档。

从主 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_lag 与 flush_lag 之间的时间差表明 WAL 字节已发送到基础存储系统,但尚未报告已刷新。 这些数据很可能未完全写入持久存储,而是可能保存在某种易失性写缓存中。
  • flush_lag 与 replay_lag 之间的差异表明 WAL 字节已成功持久化到存储,但数据库系统无法重放它们。

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

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

变通方法是产生一些数据库写入。例如,您可以登录主站点并创建一些议题和评论。

另一种变通方法是在主站点的数据库上运行 SQL 查询 CHECKPOINT;:

shell
sudo gitlab-psql -xc 'CHECKPOINT;'