PostgreSQL 14离线安装全攻略:RPM依赖打包、本地YUM源配置与初始化调优
2026/9/18 9:20:38 网站建设 项目流程

第一次在内网服务器上部署 PostgreSQL 14 的时候,我差点因为缺一个 libreadline 依赖把整个下午耗在反复装包上。后来摸清楚离线安装的完整链路,才发现这件事的难点根本不在“安装”本身,而在“打包”和“配置”这两个环节。很多团队的服务器都是在安全区里,没法直接连外网 yum 源,手里只有一台能联网的跳板机或者镜像机,这时候你必须在有网机器上把 PostgreSQL 14 的安装包连同所有依赖一起备齐,再搬到内网装好并调通。整个过程踩坑不少,但只要你把版本选择、依赖准备、初始化、配置文件这几个关键环节理顺,离线部署 PostgreSQL 14 完全可以一次成功。

这篇文章我会从我在生产环境里的实操经验出发,把离线安装 PostgreSQL 14 从下载到配置完完整整拆开讲,覆盖官方 RPM 包的选择、依赖收集、本地 YUM 源制作、initdb 初始化、postgresql.conf 和 pg_hba.conf 配置,以及离线环境里最常见的几类报错排查。无论你是刚接触 PostgreSQL 的小白,还是被项目临时派去内网部署的运维,这篇都能给你一套可以直接照做的流程。

1. 离线部署前先想清楚这几件事:版本确认与安装方式决策

1.1 为什么我推荐 14 系列而不是最新大版本

PostgreSQL 的大版本迭代速度很快,每年基本都会出一个新的大版本,但这不代表生产环境就要追新。PostgreSQL 14 发布于 2021 年,到现在已经迭代了大量小版本,稳定性和社区生态都到了非常成熟的阶段。很多企业内部基于 PostgreSQL 开发的应用,最初就是按 11、12、13 写的 SQL,迁移到 14 几乎不需要改代码,而且 14 本身在性能上相比 12、13 有明显提升,比如说 vacuum 机制更高效、逻辑复制支持更好的并行回放、正则表达式和 JSON 处理能力增强,这些对常规业务系统来说都是实打实的收益。

选 14 还有一层很现实的原因:离线环境下你没法频繁升级大版本。数据库一旦跑起来,数据文件和系统表结构就跟大版本绑定了,跨大版本升级需要专门的 pg_upgrade 流程,在不能联网下载新依赖包的内网环境里更麻烦。与其选一个太新、周边配套还没跟上的大版本,不如选一个已经稳定运行了两三年的 14 系列。当然,如果你所在企业在安全合规上要求必须使用较新版本,那选 15、16 也是可行的,但安装思路和我下面讲的基本一致,只是 RPM 包名称里的版本号不同。

1.2 选择 RPM 安装还是源码编译:离线场景的现实对比

接触过 PostgreSQL 的朋友应该知道,部署方式无非两条路:用官方 RPM/DEB 包安装,或者下载源码编译安装。在离线场景下,这个选择题会变得格外关键。

对比项官方 RPM 包安装源码编译安装
依赖处理有明确的依赖关系,可通过提前收集 RPM 包解决依赖库大多需要系统已有,缺失时要逐个源码编译
部署速度拷包、建源、yum install 三步搞定需要 configure、make、make install,时间以小时计
服务管理自带 systemd unit 文件,开箱即用通常要自己写 service 文件或使用 pg_ctl 手动管理
路径规范默认安装到 /usr/pgsql-14,数据目录在 /var/lib/pgsql/14可自定义路径,但所有路径都要自己规划
后续维护小版本升级方便,替换 RPM 包即可升级要重新编译,维护成本高

我的建议非常明确:只要能搞到匹配操作系统版本的官方 RPM 包,优先走 RPM 方案。离线环境里最怕的就是“装的时候一时爽,维护的时候火葬场”,RPM 方式至少让服务管理、目录规范、卸载清理都跟在线安装保持一致。而且 PostgreSQL 官方 YUM 仓库里每个 RPM 包都有明确的版本和系统标识,比如 postgresql14-server-14.11-1PGDG.rhel7.x86_64.rpm,你一眼就能看出这是给 RHEL/CentOS 7 用的,适合内网环境里严格管控软件版本的要求。

除非你的服务器 CPU 架构比较特殊,比如某些国产化环境里的 ARM 或 MIPS 架构,官方仓库没有现成 RPM 包,才考虑源码编译。源码编译最大的坑不是编译本身,而是依赖库缺失,内网环境装不了 readline-devel、zlib-devel 这些基础开发库的时候,你会发现连 configure 这关都过不去。

1.3 目标环境盘点清单

去内网机房之前,我建议你先花十分钟做一次环境盘点,确认下面这几项:

  • 操作系统版本和 CPU 架构,执行cat /etc/redhat-releaseuname -m,搞清楚是 CentOS 7、RHEL 8 还是其他兼容系统,是 x86_64 还是 aarch64,这决定了你应该下载哪个后缀的 RPM 包。
  • 是否已经装过其他版本的 PostgreSQL 或者其他数据库,避免端口冲突和 RPM 包冲突。
  • 服务器内存、磁盘空间情况,PostgreSQL 跑生产至少要有 2GB 内存、20GB 以上空闲磁盘,数据目录所在的挂载点需要重点确认。
  • 是否有 root 权限或 sudo 权限,离线安装过程中要创建系统用户、修改/etc/yum.repos.d、操作 systemd,没有 root 会非常被动。

这些信息不需要什么高级工具,几条命令就够。环境盘点做到位,后面打包就不会出现“包拿错了”“架构不对”“依赖冲突”这种低级问题。

2. 在一台能联网的机器上收集全套安装包:依赖链不容出错

2.1 下载入口:官方 YUM 仓库结构说明

PostgreSQL 官方提供了专门的 YUM 仓库,地址是download.postgresql.org/pub/repos/yum/,里面按大版本号、操作系统、CPU 架构分好了目录。以 14 版本为例,针对 RHEL/CentOS 7 x86_64 的路径大致是:

https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-7-x86_64

你需要提前在自己的网络环境里确认能访问到这个仓库。如果公司网络有限制,可以先在本地虚拟机或者公司允许联网的镜像机上一次性把所有包拉下来。直接在有网机器上配置临时 YUM 源是最便捷的做法,在/etc/yum.repos.d/下新建一个pgdg14.repo文件:

[pgdg14] name=PostgreSQL 14 for RHEL/CentOS 7 - x86_64 baseurl=https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-7-x86_64 enabled=1 gpgcheck=1 gpgkey=https://download.postgresql.org/pub/repos/yum/RPM-GPG-KEY-PGDG

如果你的有网机器是 CentOS 7,仓库配置好之后直接执行yum makecache fast就能把 PostgreSQL 14 的元数据拉下来。这里要注意,仓库配置里的$releasever变量到了内网环境经常会因为系统版本识别问题导致 baseurl 对不上,我后面会讲怎么处理。

2.2 用 yumdownloader 自动拉取依赖

手动一个个去官网下载 RPM 包很容易漏依赖,因为 PostgreSQL 14 的安装包依赖了 libpq、readline、zlib 等一堆基础库。最稳妥的方式是使用yumdownloader工具,它会根据当前系统的可用源自动解析依赖并下载所有需要的 RPM 包。

首先在有网机器上安装 yum-utils:

yum install -y yum-utils

然后创建目录并下载:

mkdir -p /tmp/pg14_packages cd /tmp/pg14_packages yumdownloader --resolve --destdir=/tmp/pg14_packages \ postgresql14-server postgresql14-contrib postgresql14

--resolve参数是核心,它会自动把所有运行时依赖一起下载下来,这样你拿到内网之后只要按照依赖顺序安装,就不会出现“装 server 时提示缺 libpq”这种问题。我建议把 postgresql14-contrib 也一起拉上,因为 contrib 包里有很多实用扩展,比如pg_stat_statements,后面做性能监控会用到。

另外,如果将来打算用 PostgreSQL 做开发或编译扩展,可以顺手把postgresql14-devel也下载了。这个包内网环境一般用不到,但备着一个不占多少空间,万一以后要装 TimescaleDB 这类扩展就有现成的头文件了。

2.3 手动备齐依赖库的兜底方案

yumdownloader 不是万能的。有些精简系统镜像在 base 源里就缺少个别依赖,或者有网机器和目标服务器 yum 源里的基础包版本有差异,导致下载列表里漏掉某些系统库。这时候你需要知道 PostgreSQL 14 的核心依赖到底有哪些,手动兜底。

我在 CentOS 7 上实测,PostgreSQL 14 的主要 RPM 依赖包括:

  • postgresql14-libs:PostgreSQL 客户端共享库,几乎所有组件都依赖它
  • libicu:提供 Unicode 和字符集支持
  • readline:psql 交互式命令行依赖
  • zlib:数据压缩相关
  • libxslt 和 libxml2:XML 处理功能
  • openssl-libs:SSL 加密通信
  • pam-libs:PAM 认证支持
  • systemd-libs:systemd 服务集成

如果 yumdownloader 没有把这些依赖全部拉下来,你可以手动去 CentOS 基础镜像仓库对应目录下载,或者更简单的方式是换一台带有完整 ISO 源或者阿里云镜像源的有网机器,重新执行一次 yumdownloader。

这里分享一个我常用的判断方法:下载完所有包之后,在目标服务器离线安装前,先在有网机器上把包作为本地源,执行一次yum install --downloadonly看有没有缺失的依赖被解析出来。把获取到的包和之前 yumdownloader 下载的合并,基本就齐了。

2.4 把安装包做成本地 YUM 源再拷走

很多人习惯直接把 RPM 包带到内网后用rpm -ivh *.rpm一把梭,我强烈不建议这么做。原因有两个:一是安装顺序不对会报依赖错误,你必须手动排序;二是 RPM 包之间如果存在版本覆盖关系,rpm -ivh处理起来很粗糙,不会自动升级或替换。更规范的做法是把这些 RPM 包做成一个本地 YUM 源,到内网后用 yum 安装,让 yum 自己处理依赖顺序。

在有网机器上安装 createrepo:

yum install -y createrepo cd /tmp/pg14_packages createrepo .

执行完之后,这个目录下会生成一个repodata子目录,里面是仓库元数据。整个/tmp/pg14_packages目录打包拷贝到内网服务器任意目录,比如/opt/pg14_rpm

tar czf pg14_packages.tar.gz /tmp/pg14_packages

到内网解压后,在/etc/yum.repos.d/下新建一个本地源配置:

[local-pg14] name=Local PostgreSQL 14 Repository baseurl=file:///opt/pg14_rpm enabled=1 gpgcheck=0

注意我在本地源里关闭了 gpgcheck,因为内网环境没有官方 GPG key,而且包来源是有网机器上一手拉下来的,可信度比较高。如果你想保留签名校验,可以提前把官方RPM-GPG-KEY-PGDG拷贝到内网并配置好 key,但这在离线环境里多一层管理负担,不是必须。

配置好后执行:

yum clean all yum makecache

接下来直接yum install -y postgresql14-server postgresql14-contrib,yum 会自动解析/opt/pg14_rpm目录下所有 RPM 包的依赖关系,你完全不用手动排序。这一步做对了,离线安装可以说已经成功了 70%。

3. 内网机器上的安装实战:RPM 安装与数据库初始化

3.1 上传与本地源配置

到这一步你手里应该有了一个完整的压缩包或者一个目录的 RPM 文件。上传到内网服务器之后,建议直接放到/opt/pg14_rpm这种固定路径,避免后面机器重启或者目录清理导致源失效。

上传方式根据内网环境来,常见的包括 scp、U 盘拷贝、运维平台的文件分发功能。文件落地后先校验一下包数量:

ls -l /opt/pg14_rpm/*.rpm

重点看有没有postgresql14-serverpostgresql14-contribpostgresql14-libs这几个关键包。确认无误后创建本地源配置文件,内容我在上面已经给出,这里不再重复。如果目标服务器是 CentOS 7,还要注意把系统自带的 base 源、epel 源临时禁用,否则 yum 会去外网找源,离线环境里会卡住或者超时。最简单的方式是给这些外部源配置文件加.bak后缀,或者把enabled=1临时改成enabled=0,装上 PostgreSQL 17之后再恢复。这里我多说一句,如果内网服务器本身有内网 YUM 源,不要彻底删掉原配置,只临时禁用就行,因为 PostgreSQL 依赖的那些基础库可能还需要从内网源补。

3.2 为什么装完 RPM 之后必须手动执行 initdb

很多第一次装 PostgreSQL 的人会踩一个坑:明明 RPM 包装完了、systemctl start postgresql-14却提示启动失败,或者服务起来了连上去报错说找不到数据库。这是因为 RPM 安装只是把二进制程序、脚本和默认配置放到系统目录里,它不会自动帮你创建数据目录和初始化数据库集群。

PostgreSQL 里有个核心概念叫“数据库集群”,它不是多台服务器的意思,而是指一个由配置、数据文件、WAL 日志组成的完整数据目录集合。初始化这个数据目录的动作就叫 initdb。就像你把一套工具箱买回家,工具箱本身不会自动把工具摆好,你必须自己打开柜子把工具分类放进去。

PostgreSQL 官方 RPM 包提供了初始化脚本,直接执行:

/usr/pgsql-14/bin/postgresql-14-setup initdb

这个脚本本质上是帮你以 postgres 用户身份调用 initdb,并把数据目录指定为/var/lib/pgsql/14/data。如果你执行后看到类似“Data directory initialized”的输出,就说明数据集群创建成功。

如果你想手动执行 initdb 以便更精确地控制字符集和 locale,可以这样操作:

su - postgres /usr/pgsql-14/bin/initdb -D /var/lib/pgsql/14/data \ --encoding=UTF8 \ --locale=en_US.UTF-8

这里我强烈建议--encoding=UTF8,因为默认的 SQL_ASCII 字符集下,中文存储和排序会出现意想不到的问题,尤其在做中文全文检索的时候。--locale建议选en_US.UTF-8,如果你的系统里没有安装 en_US 语言包,可以换成Czh_CN.UTF-8,具体看目标服务器有没有对应 locale。

3.3 首次启动与基础连接验证

数据目录初始化完成之后,就可以启动服务了:

systemctl start postgresql-14 systemctl status postgresql-14

如果状态是 active (running),继续检查端口是否监听:

ss -lntp | grep 5432

看到5432端口被postgres进程监听就说明服务正常。接下来登录数据库做一次基本验证。RPM 安装会自动创建名为postgres的系统用户,我们需要切换到该用户执行 psql:

su - postgres psql -U postgres

这里有一个细节需要注意:本机直接psql -U postgres走的是本地 socket 连接,认证方式默认是 peer,也就是说系统用户叫postgres,数据库用户叫postgres,就能免密登录。如果你发现提示输入密码,说明你的pg_hba.conf初始配置和默认不一样,先不用急,后面配置章节会讲清楚。

进入 psql 后可以先执行几条基础命令验证:

SELECT version(); SHOW port; SHOW data_directory;

能看到 PostgreSQL 14.x 版本号、端口 5432、数据目录/var/lib/pgsql/14/data就说明整个安装链路已经通了。

3.4 目录权限和 SELinux 对安装的影响

内网环境里经常见到初始化失败或者启动失败,原因不是 PostgreSQL 本身的问题,而是数据目录权限不对。RPM 安装默认会给/var/lib/pgsql/14/data设置成 postgres 用户所有,但如果你手动执行过 initdb,或者恢复过备份数据目录,很容易把目录所有者搞成 root。

检查权限:

ls -ld /var/lib/pgsql/14/data

正常应该是drwx------. 3 postgres postgres。如果不是,执行:

chown -R postgres:postgres /var/lib/pgsql/14/data chmod 700 /var/lib/pgsql/14/data

PostgreSQL 对数据目录权限很敏感,如果权限设置成 755,进程在启动时甚至会主动报错拒绝运行,这是它的安全策略,不是 bug。

另外,如果目标服务器开启了 SELinux,即使端口监听正常,远程连接也可能被 SELinux 拦截。快速判断方法:

getenforce

如果输出是 Enforcing,可以临时执行setenforce 0测试是不是 SELinux 拦截,确认后再决定是放宽策略还是彻底关闭。部分安全要求严格的内网服务器要求 SELinux 保持 Enforcing,这种情况下可以通过 audit2allow 生成自定义策略,但一般企业内网环境,稳妥起见我会先和运维确认安全基线,再决定处理方式。我自己的经验是,PostgreSQL 官方 RPM 自带了一个 SELinux compatibility 包postgresql14-contrib里的配套工具和策略,但实际情况中配置起来还是有点绕,所以如果安全基线允许,直接把数据库所在端口加入 SELinux 放行列表是最省力的方案。

4. 配置详解:postgresql.conf 与 pg_hba.conf 才是部署重点

4.1 监听地址和端口:改完不生效的常见原因

PostgreSQL 默认只监听localhost,也就是说从其他机器访问你的 5432 端口,连接会被直接拒绝。修改监听地址的方法是在postgresql.conf文件中设置:

listen_addresses = '*' port = 5432

listen_addresses支持设置多个 IP,比如'127.0.0.1, 192.168.10.20',只监听本机和内网 IP。如果你希望所有网卡都能接受连接,就写'*'

改完之后很多同学发现远程还是连不上,第一反应是systemctl restart postgresql-14重启服务,但重启后依然不行。这时候你要先确认自己改的配置文件是不是 PostgreSQL 真正读取的那个。PostgreSQL 的配置文件路径可以通过 SQL 查询:

SHOW config_file; SHOW hba_file;

我遇到过改了/etc/postgresql/14/main/postgresql.conf结果服务实际读取的是/var/lib/pgsql/14/data/postgresql.conf的情况,两边配置文件不同步,白白折腾半天。在 RPM 安装的标准环境下,postgresql.conf就位于数据目录里,也就是/var/lib/pgsql/14/data/postgresql.conf。不要凭记忆去改其他位置的同名文件,先执行 SHOW 确认路径。

修改配置后的生效规则也要清楚:listen_addressesport属于需要重启才能生效的参数。可以用systemctl reload postgresql-14平滑加载大部分参数,但监听地址和端口这类参数必须重启。生产环境如果不想中断业务,可以选择在维护窗口执行 restart,或者用pg_ctlcluster之类的工具做优雅重启。

4.2 内存参数怎么设才不至于拍脑袋

PostgreSQL 的内存参数直接影响查询性能和并发能力,很多离线部署的服务器专用于跑数据库,所以这些参数值得认真设置。下面几个是我每次部署都会重点确认的:

参数默认值建议参考说明
shared_buffers128MB物理内存的 25% 左右PostgreSQL 的共享缓存池,所有连接共享使用
work_mem4MB32MB 到 64MB单个排序、哈希操作可用的内存,不宜盲目调大
maintenance_work_mem64MB256MB 到 512MB用于 VACUUM、CREATE INDEX 等维护操作
effective_cache_size4GB物理内存的 50% 到 75%让优化器估算操作系统文件缓存大小
max_connections100按应用连接池实际需求每个连接都会消耗一定内存,不是越大越好

这里要解释一下 work_mem 的坑:它和 shared_buffers 不一样,是每个操作都可以分配的内存。比如一个查询里涉及 4 个排序操作,那它最多可能占用 4 倍的 work_mem。如果服务 100 个连接,同时各跑一个复杂排序,work_mem 调到 1GB 就会瞬间把内存吃满,触发 OOM。所以 work_mem 的正确调法是结合并发量,宁可小一点让它落盘,也不要大到把系统拖死。

修改后检查是否生效:

SHOW shared_buffers; SHOW work_mem;

如果行为准值没有变,你可能会重新确认修改位置。有些参数也支持通过ALTER SYSTEM设置,比如ALTER SYSTEM SET shared_buffers = '512MB';,这会把配置写到postgresql.auto.conf文件里,优先级高于 postgresql.conf,后续管理时要留意。

4.3 pg_hba.conf 认证规则与 14 的 scram-sha-256 变化

如果说 postgresql.conf 控制的是“数据库怎么跑”,那 pg_hba.conf 控制的就是“谁能连、怎么认证”。这个文件的全称是 Host-Based Authentication,每一行都是一条访问规则,从上到下匹配,一旦命中就不再继续往下走,所以规则顺序很关键。

离线部署时最常用的一套规则模板如下:

# TYPE DATABASE USER ADDRESS METHOD local all postgres peer local all all scram-sha-256 host all all 127.0.0.1/32 scram-sha-256 host all all 192.168.10.0/24 scram-sha-256

逐行解释:

  • 第一行:本地 socket 连接且系统用户是 postgres 时,用 peer 认证,直接免密登录。这是管理员维护通道,保持默认就好。
  • 第二行:本地 socket 连接其他用户时,要求输入密码,认证方式 scram-sha-256。
  • 第三行:允许本机 IP 通过 TCP 连接,要求密码。
  • 第四行:允许内网 192.168.10.0/24 网段的机器通过 TCP 连接,要求密码。

这里有个 PostgreSQL 14 带来的重要变化:从 15 开始,password_encryption默认值是scram-sha-256,但很多从 11、12 迁移到 14 的人还在沿用旧的 md5 认证。如果你的 pg_hba.conf 里写的是md5,而用户密码是以 scram-sha-256 方式存储的,认证就会失败。反过来也一样。所以 14 环境里我建议统一使用scram-sha-256,先把认证方式确定下来,再设置用户密码。

设置用户密码的命令:

ALTER USER postgres PASSWORD '强密码';

为应用单独创建用户更安全:

CREATE USER appuser WITH PASSWORD 'app密码'; GRANT CONNECT ON DATABASE appdb TO appuser;

我见过很多团队直接用 postgres 超级用户当应用连接账号,这在隔离的内网环境里可能问题不大,但一旦应用被攻破,数据库权限就是最高的,风险很高。离线内网系统也一样要有权限最小化的意识。

4.4 日志参数和中文环境设置

离线环境下调试问题主要靠日志,所以日志参数值得在部署时就配好。postgresql.conf 里建议打开这几个参数:

logging_collector = on log_directory = 'log' log_filename = 'postgresql-%a.log' log_rotation_age = 1d log_rotation_size = 100MB log_min_duration_statement = 1000

log_min_duration_statement表示执行时间超过 1000 毫秒的 SQL 会被记录,这对后续排查慢查询非常有用。日志文件会生成在数据目录下的log子目录里,比如/var/lib/pgsql/14/data/log,不是 Linux 系统日志目录,这个容易搞混。

关于中文环境,内网服务器经常会出现locale不存在导致 initdb 失败或字符集异常的问题。我前面建议用en_US.UTF-8初始化数据集群,因为大部分 Linux 系统默认带这个 locale。如果你确实要使用zh_CN.UTF-8,先确认服务器的 locale 是否可用:

locale -a | grep zh_CN

如果输出为空,说明系统还没装中文语言包。在线环境可以装glibc-langpack-zh,但离线环境里就得提前把语言包的 RPM 准备好。所以我通常选择用en_US.UTF-8初始化,数据库里照样可以存中文,完全不耽误业务功能,又少了一层环境依赖。

5. 服务自启动与日常运维命令速查

5.1 用 systemd 托管 pg_ctl 生命周期

PostgreSQL 官方 RPM 包自带 systemd 服务文件,服务名是postgresql-14。安装并初始化数据库后,执行:

systemctl enable postgresql-14 systemctl start postgresql-14

enable的目的是让 PostgreSQL 开机自启动,start是立即拉起服务。如果后续修改了端口或者数据库版本升级,服务的 unit 文件一般不需要手动改,官方 RPM 已经把环境变量和启动参数封装好了。

有时候内网服务器在启动时网络服务还没就绪,导致 PostgreSQL 启动后监听失败,这时你可以检查 systemd 服务文件里的依赖关系。官方 unit 文件通常是这样的:

[Unit] Description=PostgreSQL 14 database server After=network.target

如果遇到开机启动顺序问题,可以手动加一条依赖:

[Unit] After=network-online.target Wants=network-online.target

改完之后执行systemctl daemon-reload再重启服务。不过这种情况在企业内网环境里比较少,大多数时候网络服务启动比数据库快得多。

5.2 日常常用操作清单

部署完成后的日常运维操作,我整理成一张速查表,方便你需要时直接对照:

操作命令
启动服务systemctl start postgresql-14
停止服务systemctl stop postgresql-14
重启服务systemctl restart postgresql-14
重载配置systemctl reload postgresql-14
查看状态systemctl status postgresql-14
查看端口ss -lntp | grep 5432
本地连接su - postgres -c "psql -U postgres"
查看日志tail -f /var/lib/pgsql/14/data/log/postgresql-周六.log
查看数据目录du -sh /var/lib/pgsql/14/data
备份数据库pg_dump -U postgres -h 127.0.0.1 dbname > db.sql
恢复数据库psql -U postgres -h 127.0.0.1 dbname < db.sql

这里要特别提醒日志文件名里的%a是星期几,如果周一排查问题,日志文件可能是postgresql-Mon.log,你直接ls /var/lib/pgsql/14/data/log/看看实际生成的文件名就行。不要凭记忆去 tail 一个不存在的日志文件。

5.3 配置变更后的重载规则

修改 PostgreSQL 配置有两种方式:reloadrestartreload不会中断连接,适合修改日志等级、work_mem、shared_buffers 之外的大多数动态参数;restart会断开所有连接,适合修改shared_buffersmax_connectionsport这类 PostgreSQL 文档里明确标注为“需要重启才能生效”的参数。

我的操作习惯是:改完配置先执行systemctl reload,再在 psql 里用SHOW命令看参数是否生效。如果该参数必须重启才生效,SHOW出来的值还是旧的,这时候再计划 restart。

需要注意的是,ALTER SYSTEM SET设置的参数和 postgresql.conf 里的参数会叠加生效,优先级是 postgresql.auto.conf 高于 postgresql.conf。如果出现“改了 postgresql.conf 但参数没变”的情况,检查一下是不是之前用过 ALTER SYSTEM 写入了同样的参数,执行:

SELECT * FROM pg_file_settings WHERE sourcefile LIKE '%auto%';

看到具体配置来源后,你就可以决定是清理 auto.conf 记录,还是在 postgresql.conf 里直接改。

6. 离线安装高频报错:我把排查过程重新走了一遍

6.1 依赖缺失:rpm 安装顺序和报错解读

离线安装最常见的报错就是“Requires: libreadline.so.6()(64bit)”。看到这种报错,你的第一反应不应该是去网上搜这个库文件怎么下载,而是回想一下你有没有用 yum 方式安装,而是一开始就rpm -ivh *.rpm一把梭了。

rpm -ivh *.rpm的方式需要手动排序,装 postgresql14-server 之前必须先装 postgresql14-libs,而 libs 又依赖系统的基础库比如 readline、zlib。如果这些基础库正好在系统里没有,rpm 就会直接报错。最省心的办法就是我前面说的本地 YUM 源方案,yum 会自动按依赖顺序装好并提示缺什么。

如果系统提示缺少某个基础库,而你的离线包里又没有,那就只能回到有网机器上把对应的基础 RPM 包拉下来,或者看目标系统的 ISO 镜像里有没有相关包。我在这里提一个取巧的办法:找一台和目标服务器操作系统版本一致的有网机器,执行yumdownloader --resolve --destdir 目标目录 readline zlib libicu,再把拉下来的包补到离线包目录里。

6.2 初始化失败:权限和动态库问题

初始化失败分两种,一种是 initdb 执行时报权限错误,比如:

initdb: error: could not change permissions of directory "/var/lib/pgsql/14/data": Operation not permitted

这种几乎都是数据目录的所有权不对。你如果不是用官方postgresql-14-setup脚本,而是手动执行 initdb,就会遇到这个问题。解决方式是把数据目录 chown 给 postgres 用户,然后切换到 postgres 用户再跑 initdb。千万不要在 root 用户下强行执行 initdb,即使初始化成功,后续服务启动也会因为权限问题报错。

另一种是动态库加载失败,比如:

ERROR: could not load library "/usr/pgsql-14/lib/plpgsql.so": libpq.so.5: cannot open shared object file

这种通常出现在从源码编译或手动拷贝文件导致的环境变量不对。官方 RPM 安装时会在/etc/ld.so.conf.d/下写入 PostgreSQL 的库路径,如果你发现动态库找不到,检查一下有没有这个文件:

cat /etc/ld.so.conf.d/postgresql14*.conf

正常应该有类似/usr/pgsql-14/lib的路径。如果没有,手动创建并执行ldconfig刷新。

6.3 远程连接超时:防火墙、SELinux、postgresql.conf 三层排查

远程机器连不上数据库,我先说排查顺序,这个顺序是我踩过无数次坑之后沉淀下来的:

  1. 看服务是否监听在所有网卡上,使用ss -lntp | grep 5432,如果看到的 IP 是127.0.0.1:5432,那说明listen_addresses没有生效。
  2. 看防火墙是否放行 5432 端口,执行firewall-cmd --list-alliptables -L -n
  3. 看 SELinux 是否拦截,执行getenforce,Enforcing 状态下尝试setenforce 0临时关闭后重试。
  4. pg_hba.conf里有没有你客户端 IP 所在网段的规则。

按照这个顺序排查基本能覆盖 90% 的远程连接问题。我曾经在一台 CentOS 7 服务器上排了半天,最后发现是listen_addresses写成了'127.0.0.1',而不是'*',客户端来源 IP 直接不是本机,当然连不上。

6.4 认证失败:遇到“password authentication failed”先看日志

如果客户端报错FATAL: password authentication failed for user "appuser",第一反应不要急着去改密码,而是先看数据库日志:

tail -100 /var/lib/pgsql/14/data/log/postgresql-周一.log

日志里会明确告诉你认证类型和来源 IP。常见的几个认证失败原因:

  • 密码加密方式不匹配:pg_hba.conf 写 md5,但用户密码是 SCRAM 存储。
  • 认证方式被 peer 规则拦截:你从远程 TCP 连接,但命中了一条local规则,这通常是因为网络地址写成了本机路径。
  • 用户不存在:PostgreSQL 的账号是独立于系统账号的,你创建了系统用户不代表同时创建了数据库用户。

检查用户当前认证方式:

SELECT rolname, rolcanlogin FROM pg_roles WHERE rolname = 'appuser';

如果用户没问题,把 pg_hba.conf 里对应规则的 METHOD 改成scram-sha-256,再用ALTER USER重新设置一次密码,几乎都能解决。

另外,我提醒一下离线环境里容易出现的问题:如果你是从别的机器拷贝了pg_hba.conf过来,文件换行符和格式可能不对,末尾多了\r会让 PostgreSQL 解析失败。用file命令看看,再用vim打开确认每行结尾干净。

7. 让我在实战中收获最大的几个习惯

离线装了这么多次 PostgreSQL 14,我养成了一个习惯:每次安装完成之后,把/opt/pg14_rpm这个目录打包留存一份,标注好操作系统版本、CPU 架构、PostgreSQL 小版本号、依赖包清单。因为内网环境往往不止一套系统,可能过两个月又冒出来一台同版本的服务器要装同样的数据库,这时候直接把之前的包拿出来建源,十分钟就能搞定,不需要再跑到有网机器上重新拉一遍。

再有一个习惯,就是 deployments.md 一类的运维文档我坚持每次更新。PostgreSQL 离线安装最重要的记录不是“装好了”,而是“改了哪些配置、为什么改”。比如shared_buffers是从 128MB 提到了 1GB,原因是应用侧有大量的并发读请求;pg_hba.conf 放行了哪个网段,是给哪个应用系统提供的访问入口。这些信息如果不记下来,等到半年后排查慢查询或者做安全审计的时候,你会发现自己对着配置文件一脸茫然。

还一个特别容易被忽略的小技巧:在离线服务器上用psql -c "SELECT version();"输出结果前,先su - postgres切换用户。很多人习惯直接在 root 下执行psql -U postgres,然后遇到 peer 认证失败就蒙了。这个点我在前面提过一次,但值得再强调一遍,因为这是新手最容易卡住的地方。其实 PostgreSQL 的设计哲学一直都很清晰:系统用户和数据库用户分开管理,本地维护走 peer 认证,远程访问走密码认证,只要理解了这套逻辑,很多看似奇怪的报错都能迎刃而解。

最后留个建议:离线环境里备份恢复方案一定提前做好。PostgreSQL 14 的在线备份和恢复工具链比较成熟,建议把pg_dumparchive_command和定时备份脚本在部署当天就配好,别等到数据出了问题时才开始研究。离线环境补救手段有限,未雨绸缪比什么都重要。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询