{{< alert type=”warning” >}}

地理复制(Geo) 不能用于将PostgreSQL数据库从一个操作系统迁移到另一个操作系统。如果尝试这样做,从站点可能看似已100% 复制,但实际上部分数据并未复制,这会导致数据丢失。这是因为Geo依赖于PostgreSQL流复制,而它存在本文档中所述的局限性。另请参阅 地理复制故障排除 - 检查操作系统区域设置数据兼容性

{{< /alert >}}

如果升级运行 PostgreSQL 的操作系统,任何 locale 数据的更改可能会损坏数据库索引。特别是,升级到 glibc 2.28 很可能导致此问题。为避免此问题,请使用以下选项之一进行迁移,大致按复杂性排序:

  1. 推荐。备份和恢复
  2. 推荐。重建所有索引
  3. 仅重建受影响的索引

在尝试任何迁移之前,请确保进行备份,并在类似生产的环境中验证迁移过程。如果停机时间较长可能成为问题,请考虑在类似生产的环境中使用生产数据副本来测试不同的方法。

如果您运行的是扩展的极狐GitLab 环境,并且在运行 PostgreSQL 的节点上没有其他服务,那么我们建议单独升级 PostgreSQL 节点的操作系统。为减少复杂性和风险,请勿将该过程与其他更改结合,尤其是那些不需要停机的更改,例如仅运行 Puma 或 Sidekiq 的节点的操作系统升级。

备份和恢复

备份和恢复会重建整个数据库,包括索引。

  1. 选择一个计划的停机窗口。在所有节点中,停止不必要的极狐GitLab 服务:

    gitlab-ctl stop
    gitlab-ctl start postgresql
    
  2. 使用 pg_dump极狐GitLab 备份工具,排除所有数据类型,除了 db(因此仅备份数据库)备份 PostgreSQL 数据库。
  3. 在所有 PostgreSQL 节点中,升级操作系统。
  4. 在所有 PostgreSQL 节点中,升级操作系统后更新极狐GitLab 软件包源
  5. 在所有 PostgreSQL 节点中,安装相同极狐GitLab 版本的新软件包。
  6. 从备份中恢复 PostgreSQL 数据库。
  7. 在所有节点中,启动极狐GitLab。

优点

  • 简单明了。
  • 消除索引和表中的任何数据库膨胀,减少磁盘使用。

缺点

  • 随着数据库大小的增加,停机时间增加,最终变得有问题。它取决于许多因素,但如果您的数据库超过 100 GB,则可能需要大约 24 小时。

备份和恢复,使用 Geo 辅助站点

  1. 选择一个计划的停机窗口。在所有站点的所有节点中,停止不必要的极狐GitLab 服务:

    gitlab-ctl stop
    gitlab-ctl start postgresql
    
  2. 在主站点中,使用 pg_dump极狐GitLab 备份工具,排除所有数据类型,除了 db(因此仅备份数据库)备份 PostgreSQL 数据库。
  3. 在所有站点的所有 PostgreSQL 节点中,升级操作系统。
  4. 在所有站点的所有 PostgreSQL 节点中,升级操作系统后更新极狐GitLab 软件包源
  5. 在所有站点的所有 PostgreSQL 节点中,安装相同极狐GitLab 版本的新软件包。
  6. 在主站点中,从备份中恢复 PostgreSQL 数据库。
  7. 可选地,开始使用主站点,风险是没有辅助站点作为热备用。
  8. 重新设置 PostgreSQL 流式复制到辅助站点。
  9. 如果辅助站点接收来自用户的流量,请让只读副本数据库赶上进度,然后再启动极狐GitLab。
  10. 在所有站点的所有节点中,启动极狐GitLab。

重建所有索引

重建所有索引

  1. 选择一个计划的停机窗口。在所有节点中,停止不必要的极狐GitLab 服务:

    gitlab-ctl stop
    gitlab-ctl start postgresql
    
  2. 在所有 PostgreSQL 节点中,升级操作系统。
  3. 在所有 PostgreSQL 节点中,升级操作系统后更新极狐GitLab 软件包源
  4. 在所有 PostgreSQL 节点中,安装相同极狐GitLab 版本的新软件包。
  5. 数据库控制台中重建所有索引:

    SET statement_timeout = 0;
    REINDEX DATABASE gitlabhq_production;
    
  6. 重新索引数据库后,必须刷新所有受影响的排序规则的版本。更新系统目录以记录当前排序规则版本:

    ALTER COLLATION <collation_name> REFRESH VERSION;
    
  7. 在所有节点中,启动极狐GitLab。

优点

  • 简单明了。
  • 可能比备份和恢复更快,具体取决于许多因素。
  • 消除索引中的任何数据库膨胀,减少磁盘使用。

缺点

  • 随着数据库大小的增加,停机时间增加,最终变得有问题。

重建所有索引,使用 Geo 辅助站点

  1. 选择一个计划的停机窗口。在所有站点的所有节点中,停止不必要的极狐GitLab 服务:

    gitlab-ctl stop
    gitlab-ctl start postgresql
    
  2. 在所有 PostgreSQL 节点中,升级操作系统。
  3. 在所有 PostgreSQL 节点中,升级操作系统后更新极狐GitLab 软件包源
  4. 在所有 PostgreSQL 节点中,安装相同极狐GitLab 版本的新软件包。
  5. 在主站点的数据库控制台中重建所有索引:

    SET statement_timeout = 0;
    REINDEX DATABASE gitlabhq_production;
    
  6. 重新索引数据库后,必须刷新所有受影响的排序规则的版本。更新系统目录以记录当前排序规则版本:

    ALTER COLLATION <collation_name> REFRESH VERSION;
    
  7. 如果辅助站点接收来自用户的流量,请让只读副本数据库赶上进度,然后再启动极狐GitLab。
  8. 在所有站点的所有节点中,启动极狐GitLab。

仅重建受影响的索引

  1. 选择一个计划的停机窗口。在所有节点中,停止不必要的极狐GitLab 服务:

    gitlab-ctl stop
    gitlab-ctl start postgresql
    
  2. 在所有 PostgreSQL 节点中,升级操作系统。
  3. 在所有 PostgreSQL 节点中,升级操作系统后更新极狐GitLab 软件包源
  4. 在所有 PostgreSQL 节点中,安装相同极狐GitLab 版本的新软件包。
  5. 确定哪些索引受影响。
  6. 数据库控制台中为每个受影响的索引重新索引:

    SET statement_timeout = 0;
    REINDEX INDEX <index name> CONCURRENTLY;
    
  7. 重新索引错误索引后,必须刷新排序规则。更新系统目录以记录当前排序规则版本:

    ALTER COLLATION <collation_name> REFRESH VERSION;
    
  8. 在所有节点中,启动极狐GitLab。

优点

  • 停机时间不用于重建未受影响的索引。

缺点

  • 出错的机会更多。
  • 需要 PostgreSQL 专业知识来处理迁移过程中出现的意外问题。
  • 保留数据库膨胀。

仅重建受影响的索引,使用 Geo 辅助站点

  1. 选择一个计划的停机窗口。在所有站点的所有节点中,停止不必要的极狐GitLab 服务:

    gitlab-ctl stop
    gitlab-ctl start postgresql
    
  2. 在所有 PostgreSQL 节点中,升级操作系统。
  3. 在所有 PostgreSQL 节点中,升级操作系统后更新极狐GitLab 软件包源
  4. 在所有 PostgreSQL 节点中,安装相同极狐GitLab 版本的新软件包。
  5. 确定哪些索引受影响。
  6. 在主站点的数据库控制台中为每个受影响的索引重新索引:

    SET statement_timeout = 0;
    REINDEX INDEX <index name> CONCURRENTLY;
    
  7. 重新索引错误索引后,必须刷新排序规则。更新系统目录以记录当前排序规则版本:

    ALTER COLLATION <collation_name> REFRESH VERSION;
    
  8. 现有的 PostgreSQL 流式复制应将重新索引的更改复制到只读副本数据库。
  9. 在所有站点的所有节点中,启动极狐GitLab。

检查 glibc 版本

要查看使用的 glibc 版本,请运行 ldd --version

下表显示了为不同操作系统提供的 glibc 版本:

操作系统 glibc 版本
CentOS 7 2.17
RedHat Enterprise 8 2.28
RedHat Enterprise 9 2.34
Ubuntu 18.04 2.27
Ubuntu 20.04 2.31
Ubuntu 22.04 2.35
Ubuntu 24.04 2.39

例如,假设您从 CentOS 7 升级到 RedHat Enterprise 8。在这种情况下,在此升级的操作系统上使用 PostgreSQL 需要使用提到的两种方法之一,因为 glibc 从 2.17 升级到 2.28。如果未能正确处理排序规则更改,会导致极狐GitLab 中的严重故障,例如 runner 无法挑选带有标签的任务。

另一方面,如果 PostgreSQL 已经在 glibc 2.28 或更高版本上运行且没有问题,则您的索引应该可以继续工作而无需进一步操作。例如,如果您已经在 RedHat Enterprise 8 (glibc 2.28) 上运行 PostgreSQL 一段时间,并希望升级到 RedHat Enterprise 9 (glibc 2.34),则不应存在与排序规则相关的问题。

验证 glibc 排序规则版本

对于 PostgreSQL 13 及更高版本,您可以使用此 SQL 查询验证数据库排序规则版本是否与系统匹配:

SELECT collname AS COLLATION_NAME,
       collversion AS VERSION,
       pg_collation_actual_version(oid) AS actual_version
FROM pg_collation
WHERE collprovider = 'c';

匹配的排序规则示例

例如,在 Ubuntu 22.04 系统上,正确索引的系统输出如下:

gitlabhq_production=# SELECT collname AS COLLATION_NAME,
       collversion AS VERSION,
       pg_collation_actual_version(oid) AS actual_version
FROM pg_collation
WHERE collprovider = 'c';
 collation_name | version | actual_version
----------------+---------+----------------
 C              |         |
 POSIX          |         |
 ucs_basic      |         |
 C.utf8         |         |
 en_US.utf8     | 2.35    | 2.35
 en_US          | 2.35    | 2.35
(6 rows)

不匹配的排序规则示例

另一方面,如果您从 Ubuntu 18.04 升级到 22.04 而未重新索引,您可能会看到:

gitlabhq_production=# SELECT collname AS COLLATION_NAME,
       collversion AS VERSION,
       pg_collation_actual_version(oid) AS actual_version
FROM pg_collation
WHERE collprovider = 'c';
 collation_name | version | actual_version
----------------+---------+----------------
 C              |         |
 POSIX          |         |
 ucs_basic      |         |
 C.utf8         |         |
 en_US.utf8     | 2.27    | 2.35
 en_US          | 2.27    | 2.35
(6 rows)

流式复制

损坏的索引问题会影响 PostgreSQL 流式复制。在允许读取具有不同 locale 数据的副本之前,您必须重建所有索引仅重建受影响的索引

其他 Geo 变体

上述升级程序不是一成不变的。由于 Geo 存在冗余基础设施,因此可能有更多选项。您可以考虑根据您的用例进行修改,但务必权衡增加的复杂性。以下是一些示例:

为了在主站点和其他辅助站点的操作系统升级期间保留辅助站点作为灾难情况下的热备用:

  1. 隔离辅助站点的数据以免受主站点上的更改:暂停辅助站点。
  2. 执行主站点的操作系统升级。
  3. 如果操作系统升级失败且主站点无法恢复,则提升辅助站点,
  4. 将用户路由到它,然后稍后再试。
  5. 请注意,这会让您没有最新的辅助站点。

为了在操作系统升级期间为用户提供对极狐GitLab 的只读访问(部分停机):

  1. 在主站点上启用维护模式而不是停止它。
  2. 提升辅助站点但尚未将用户路由到它。
  3. 执行已提升站点的操作系统升级。
  4. 将用户路由到已提升的站点而不是旧的主站点。
  5. 将旧的主站点设置为新的辅助站点。

{{< alert type=”warning” >}}

即使辅助站点已经有数据库的只读副本,您也不能在提升前升级其操作系统。如果尝试这样做,则辅助站点可能会错过某些 Git 仓库或文件的复制,因为索引已损坏。请参阅流式复制

{{< /alert >}}