PGDG 仓库 RPM 已修复 RHEL 小版本锁定问题:升级与核查指南

2026-09-28 27 预计阅读时间: 1 分钟
来源: postgr.es AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:9 分钟

在 RHEL、Rocky Linux 和 AlmaLinux 上使用 PostgreSQL Yum 仓库的管理员,需要尽快更新仓库配置 RPM。此前,同名的主版本与小版本仓库 RPM 会参与版本比较,可能导致 dnf update 把通用仓库包替换成当时最新的小版本包,并让系统在后续升级后仍停留在旧的小版本仓库。这个行为现已修复,但已经安装的仓库 RPM 不会自动摆脱旧状态,因此仍需要主动更新。

问题不是 PostgreSQL 包,而是仓库入口被固定了

为了分别支持各个 RHEL 小版本,构建系统会为 9.6、9.7、9.8、10.0 等版本生成独立的仓库 RPM,同时保留面向 9、10 等主版本的仓库 RPM。

问题来自三个条件的组合:

  • 主版本和小版本仓库 RPM 使用相同的包名;
  • 小版本专用 RPM 也会出现在当时最新的小版本仓库中;
  • DNF 根据 RPM 的版本与发行号选择更新包,而不会理解管理员原本想跟随“主版本”还是“当前操作系统小版本”。

因此,某台最初使用主版本仓库 RPM 的 RHEL 9 系统,可能在执行更新时被替换为面向 9.6 的仓库 RPM。之后,即使操作系统升级到 9.7,该仓库配置仍可能继续指向 9.6,而不是自动跟随新的系统版本。

这种问题很容易被忽略:操作系统升级成功,dnf repolist 也不一定报错,但 PostgreSQL 仓库提供的软件包集合已经和当前 OS 小版本错位。结果可能表现为更新不可见、依赖解析异常,或节点之间拿到不同的软件包版本。

修复后的预期行为

调整后的仓库 RPM 会跟随操作系统小版本,避免仓库入口永久停留在某个历史小版本。这里需要区分两件事:

  1. 上游已经修复仓库 RPM 的发布与升级行为;
  2. 已经安装旧仓库 RPM 的机器仍应更新该包,才能获得修正后的配置。

也就是说,仅升级操作系统或普通 PostgreSQL 软件包并不足够。仓库 RPM 本身属于供应链入口,它决定 DNF 去哪里读取元数据,应该被单独纳入升级和审计范围。

在节点上更新并验证

以下脚本假设仓库 RPM 的包名为 pgdg-redhat-repo。执行前可以移除 -y,先查看 DNF 的事务计划;生产环境则建议先在一台非关键节点上验证。

#!/usr/bin/env bash
set -euo pipefail

repo_pkg="pgdg-redhat-repo"

source /etc/os-release
printf 'Operating system: %s %s\n' "${NAME}" "${VERSION_ID}"

if ! rpm -q "${repo_pkg}" >/dev/null 2>&1; then
  echo "${repo_pkg} is not installed; nothing to update."
  exit 0
fi

echo "Before update:"
rpm -q --qf '%{NAME} %{VERSION}-%{RELEASE}.%{ARCH}\n' "${repo_pkg}"

sudo dnf --refresh upgrade -y "${repo_pkg}"

echo "After update:"
rpm -q --qf '%{NAME} %{VERSION}-%{RELEASE}.%{ARCH}\n' "${repo_pkg}"

echo "Enabled PGDG repositories:"
sudo dnf repolist --enabled | grep -i pgdg || true

echo "Repository configuration files:"
find /etc/yum.repos.d -maxdepth 1 \
  \( -iname '*pgdg*.repo' -o -iname '*pgdg*.rpmnew' \) \
  -print

如果旧仓库配置无法发现修复后的 RPM,应从组织批准的来源下载最新仓库 RPM,再从本地文件安装。把下面的路径替换成实际文件:

REPO_RPM=/path/to/approved/pgdg-redhat-repo-latest.noarch.rpm

rpm -K "${REPO_RPM}"
sudo dnf install -y "${REPO_RPM}"
sudo dnf clean metadata
sudo dnf makecache

rpm -K 用于检查 RPM 签名和摘要。不要为了绕过验证而使用 --nogpgcheck;如果签名无法验证,应先检查密钥来源、下载过程以及内部镜像同步状态。

更新后还可以直接查看仓库定义,确认没有意外遗留的小版本路径或旧配置:

sudo grep -RniE '^(baseurl|metalink|mirrorlist)=' \
  /etc/yum.repos.d/*pgdg*.repo 2>/dev/null || true

sudo dnf --refresh repolist --enabled
sudo dnf check-update || rc=$?

# dnf check-update 返回 100 表示存在可更新软件包,不代表命令失败。
if [[ ${rc:-0} -ne 0 && ${rc:-0} -ne 100 ]]; then
  exit "${rc}"
fi

如果 RPM 认为现有 .repo 文件被本地修改过,升级时可能生成 .rpmnew,而不是直接覆盖原文件。此时需要比较差异:

sudo find /etc/yum.repos.d -name '*.rpmnew' -print

# 将文件名替换为实际结果后再比较
sudo diff -u \
  /etc/yum.repos.d/pgdg-redhat-all.repo \
  /etc/yum.repos.d/pgdg-redhat-all.repo.rpmnew || true

不要直接删除自定义代理、内部镜像地址、GPG 检查或模块设置。应把修正后的版本选择逻辑与本地配置合并,再删除已处理的 .rpmnew 文件。

批量环境不能只看“更新成功”

在 Ansible、Salt 或其他配置管理系统中,建议同时采集以下信息:

  • /etc/os-release 中的 VERSION_ID;
  • pgdg-redhat-repo 的完整版本与发行号;
  • 已启用的 PGDG 仓库 ID;
  • 实际仓库配置中的 baseurl、metalink 或 mirrorlist;
  • 是否存在尚未处理的 .rpmnew 文件。

对于使用内部镜像的组织,还要确认镜像同步的不只是 PostgreSQL 软件包,也包括更新后的仓库 RPM。否则公网源已经修复,内网客户端仍可能继续安装旧版本。

需要特别谨慎的是 EUS、锁定 release 的订阅或刻意保持在某个小版本的系统。这些环境不应机械地追随最新小版本;管理员应确认新的仓库 RPM 与组织的生命周期策略一致,并在更新前检查 subscription-manager release、DNF versionlock 以及内部镜像保留策略。

建议的落地顺序

可以按以下顺序推进:

  1. 在测试节点记录 OS 小版本、仓库 RPM 版本和启用的仓库;
  2. 只更新仓库 RPM,检查事务中是否包含非预期的软件包;
  3. 刷新元数据并验证 PGDG 仓库可用;
  4. 检查 .rpmnew 和本地修改过的 .repo 文件;
  5. 执行一次 PostgreSQL 包更新预检,但不要在同一变更窗口中盲目升级数据库主版本;
  6. 验证通过后,再通过配置管理工具分批推广。

这次问题说明,仓库 RPM 并不是一次安装后就可以遗忘的引导文件。它控制后续所有软件包的来源和版本边界,应当像 GPG 密钥、镜像配置与系统生命周期策略一样持续维护和审计。


相关推荐