Geo PostgreSQL 复制故障排除
- Tier: Premium, Ultimate
- Offering: GitLab Self-Managed
以下各节概述了用于修复复制错误消息的故障排除步骤(在 geo:check 输出中显示为 Database replication working? ... no)。
此处提供的说明主要假设为单节点 Geo Linux 包部署,可能需要根据不同环境进行调整。
移除不活跃的复制槽
当连接到复制槽的复制客户端(一个辅助站点)断开连接时,该复制槽会被标记为“不活跃”。 不活跃的复制槽会导致 WAL 文件被保留,因为当客户端重新连接并且复制槽再次变为活跃时,这些文件需要被发送给客户端。 如果辅助站点无法重新连接,请使用以下步骤移除其对应的不活跃复制槽:
-
在 Geo 主站点的数据库节点上启动 PostgreSQL 控制台会话:
sudo gitlab-psql -d gitlabhq_production使用
gitlab-rails dbconsole无效,因为管理复制槽需要超级用户权限。 -
查看复制槽,如果它们不活跃,则将其移除:
SELECT * FROM pg_replication_slots;active字段为f的槽是不活跃的。
-
如果此槽本应是活跃的,因为你有一个使用该槽配置的辅助站点:
-
查看辅助站点的 PostgreSQL 日志,以了解复制未运行的原因。
-
如果辅助站点无法再重新连接:
-
使用 PostgreSQL 控制台会话移除该槽:
SELECT pg_drop_replication_slot('<name_of_inactive_slot>'); -
重新启动复制过程,这将正确地重新创建复制槽。
-
-
-
如果你不再使用该槽(例如,你已不再启用 Geo),请按照移除该 Geo 站点的步骤操作。
消息:WARNING: oldest xmin is far in the past 和 pg_wal 大小持续增长
如果复制槽不活跃,则与该槽对应的 pg_wal 日志将被永久保留(或直到该槽再次变为活跃)。
这会导致磁盘使用量持续增长,并且以下消息会反复出现在 PostgreSQL 日志中:
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 没有为该名称的辅助站点配置复制槽时,会发生此错误:
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 指定一个更大的值:
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 清理最近死亡的行。
然而,此方法已在 GitLab.com 的生产环境中成功使用。
要启用 hot_standby_feedback,请在辅助站点的 /etc/gitlab/gitlab.rb 文件中添加以下内容:
postgresql['hot_standby_feedback'] = 'on'然后重新配置 GitLab:
sudo gitlab-ctl reconfigure为帮助我们解决此问题,请考虑在该议题上发表评论。
消息:server certificate for "PostgreSQL" does not match host name
如果你看到此错误:
FATAL: could not connect to the primary server: server certificate for "PostgreSQL" does not match host name发生此错误的原因是,Linux 包自动创建的 PostgreSQL 证书包含通用名称 (Common Name) 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'] 中的地址格式不正确时,会发生此情况。
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 地址时,会发生此情况。
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'] 下为 IP 地址添加子网掩码,使其符合 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):
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_lag、flush_lag 和 replay_lag。更多信息,请参阅 PostgreSQL 官方文档。
在 Geo 主节点的数据库上运行以下命令以获取相关输出:
gitlab-psql -xc 'SELECT write_lag,flush_lag,replay_lag FROM pg_stat_replication;'
-[ RECORD 1 ]---------------
write_lag | 00:00:00.072392
flush_lag | 00:00:00.108168
replay_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;:
sudo gitlab-psql -xc 'CHECKPOINT;'