CentOS 7上PostgreSQL 15安装配置与避坑指南
2026/9/13 21:19:15 网站建设 项目流程

PG这个数据库,这几年在圈子里确实越来越热。我在CentOS 7服务器上帮人装过太多次PostgreSQL,装完10.5又装12,再到现在的15、16,每次都能看到有人用系统默认源装出一个远古版本,然后各种兼容性问题层出不穷。这篇东西就打算把CentOS 7环境下的PostgreSQL安装这件事彻底讲透,从版本选型、源配置、初始化、调参与排坑一条龙捋一遍,适合刚接触Linux服务器的小白,也给那些已经踩过坑但没系统整理过思路的人做个参考。

1. 先别急着敲yum命令:安装前要敲定的三个决定

很多人拿到服务器第一反应就是yum install postgresql-server,这个动作在CentOS 7上会装出9.2版本——一个2012年的老古董。所以真正专业的安装流程,第一步根本不是执行安装命令,而是先想清楚三件事。

1.1 版本选择不是越新越好,但也不能迷信系统默认源

CentOS 7默认的AppStream仓库里只有PostgreSQL 9.2,官方支持期早就结束了,无论是安全补丁还是bug修复都断了粮。生产环境里我见过不少业务还跑在9.2上,问就是"当年装的懒得动",实际上遇到性能问题或者数据损坏,连官方技术支持都买不到,风险完全自担。

如果你是在做技术选型,我的建议是:新项目直接用PostgreSQL 15或16,这两个版本在JSON能力、分区表、并行查询上都有明显改进,而且官方至少还有四五年的维护周期。至于14及以下的版本,除非是既有业务没法动,否则真心不建议在新装环境里选了。

这里有个很实际的参考点:PostgreSQL官方版本支持周期通常是5年,一个主版本发布后,你可以大概推算它什么时候EOL。比如15是2023年10月发布的,支持到2028年底,现在装它,生命周期完全够用;而9.2这种2012年的版本,早就不该出现在任何新装环境里。

1.2 安装方式选型:官方YUM源、Docker还是编译源码

PostgreSQL在Linux上有好几种装法,每种都有自己的适用场景。

  • 官方YUM源安装:最推荐的生产环境方案。好处是版本统一、升级方便、和systemd集成好,systemctl start postgresql-15这种命令可以直接用,不需要额外写service文件。
  • Docker容器:适合测试环境或者微服务架构。一条docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=xxx postgres:15就能拉起实例,但生产环境要考虑数据卷挂载、网络模式、容器升级期间的数据迁移,复杂度并不低。
  • 编译安装:适合需要定制编译参数的特殊场景,比如自定义块大小、嵌入特定插件。但编译安装要手动处理依赖、初始化脚本、systemd服务,后期升级麻烦,一般人不建议碰。

在CentOS 7上,我几乎只推荐第一种方式,也就是通过PostgreSQL官方提供的YUM仓库来安装。这不仅是省事的问题,更重要的是PG官方会把RPM包和系统管理方式深度整合,比如自动帮你创建postgres用户、配置好systemd文件、初始化脚本,这些都是编译安装很难得到的红利。

1.3 磁盘与内存规划:别让数据库装完就陷入资源窘境

装数据库之前,最好先看一眼服务器的磁盘布局和内存情况。PostgreSQL的数据默认放在/var/lib/pgsql/15/data,这个路径依赖根分区或/var分区的空间。很多云服务器根分区就40G,装上操作系统、日志、依赖库以后已经去了大半,再把数据库塞进去,跑几周就告警。

至少确认三件事:

  1. df -h /var,确认可用空间足够(生产环境建议至少50G以上,具体看数据量)。
  2. free -m,确认内存不小于2G,如果内存吃紧,后面shared_buffers参数就得跟着调低。
  3. 最好把数据目录规划到独立数据盘,比如挂载到/data,然后初始化时指定目录,避免操作系统日志和数据库日志抢磁盘I/O。

这些前置决定看起来琐碎,但恰恰是决定安装后能不能稳定跑下去的关键。我见过太多人装完PG发现磁盘是根分区共享的,结果WAL日志一多直接把根分区塞满,整个服务器跟着崩。

2. CentOS 7基础准备:网络、yum源与依赖的三件套

安装环境认定好后,就进入实操了。CentOS 7.9是一个已经很成熟的系统版本,但正因为版本老,需要注意的基础细节反而更多。

2.1 网络配置与镜像源检查

装PostgreSQL要联网拉包,首先得确保服务器能正常访问外部仓库源。检查网络最简单的方法就是ping一下公网,或者直接curl -I https://www.postgresql.org看看能不能返回HTTP响应头。

如果网络不通,优先排查:

  • ip addr确认网卡IP是否配好,CentOS 7的网卡默认叫ens33eth0之类,如果没拿到IP,编辑/etc/sysconfig/network-scripts/ifcfg-ens33,把ONBOOT=no改成ONBOOT=yes,然后systemctl restart network
  • 检查DNS配置在/etc/resolv.conf里是否正确,对于国内服务器,可以临时换成nameserver 223.5.5.5nameserver 8.8.8.8测试。
  • 最简单的方法是换镜像源,阿里云、腾讯云都有CentOS 7的mirror,把/etc/yum.repos.d/CentOS-Base.repo里的baseurl指向镜像源,通常速度更快也更容易连通。

这一步别嫌啰嗦,很多人装到一半报错"Could not resolve host",回头查才发现是网络问题。

2.2 官方源与EPEL源的正确配置姿势

基础网络通了以后,需要给YUM添加额外的软件仓库。有两个源必须处理:EPEL和PostgreSQL官方源。

EPEL(Extra Packages for Enterprise Linux)是Fedora社区为RHEL系列维护的扩展包仓库,PostgreSQL官方源虽然本身能独立工作,但某些依赖可能需要EPEL支持,都装上更稳妥。

# 安装EPEL仓库 yum install -y epel-release # 安装PostgreSQL官方仓库RPM yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm

安装完以后检查一下仓库文件:

ls /etc/yum.repos.d/ # 你会看到 pgdg-15.repo、pgdg-redhat-all.repo 或者类似名称 yum repolist | grep pgdg

这里提醒一句:PostgreSQL官方仓库里包含了几乎所有历史版本的PG包,15和16的repo文件可能同时存在。如果你只装了最新仓库文件,通常在安装时可以通过指定包名后缀来区分版本,比如postgresql15-serverpostgresql16-server

2.3 时间同步、关闭大页等前置优化

安装之前做个快照级别的优化,能让数据库跑得更稳。

  • 时间同步:数据库的事务时间戳依赖系统时间,时间不准会导致主从复制、监控告警都不准。CentOS 7默认有chronyd,确认它在运行:systemctl status chronyd,没起来就systemctl start chronyd && systemctl enable chronyd
  • 关闭透明大页(THP):PostgreSQL对内存分配比较敏感,透明的hugepage在数据库场景下经常导致内存碎片化,官方建议关闭。方法是在/etc/rc.local里加一行echo never > /sys/kernel/mm/transparent_hugepage/enabled,然后重启生效。
  • 调整文件句柄和进程限制:数据库打开的文件数远超普通应用,在/etc/security/limits.conf里把postgres用户的nofilenproc调高,比如postgres soft nofile 65535postgres hard nofile 65535

这些细节不是必须做,但做了以后遇到高并发场景,你会明显感受到系统的余量更大。

3. 一步一步装好PostgreSQL 15:从添加官方源到initdb初始化

环境备齐后,终于可以进入正题了。下面的步骤都是在CentOS 7.9 + PostgreSQL 15的环境下验证过的,其他主版本流程类似,只需把命令里的15替换成对应版本号。

3.1 添加PostgreSQL官方YUM仓库

如果你还没添加官方源,先执行一遍:

yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm

仓库RPM安装后,主版本对应的repo文件会自动生成。为了安全起见,可以只保留需要版本的repo配置,或者直接编辑/etc/yum.repos.d/pgdg-redhat-all.repo,把不需要版本的enabled改为0,避免yum update时把多个PG主版本都升级了一下,虽然它们不会冲突安装,但仓库解析会变慢。

检查仓库是否生效:

yum clean all yum makecache yum search postgresql15-server

如果能看到postgresql15-server.x86_64字样,说明仓库OK。

3.2 安装服务端与contrib工具包

强烈建议同时装服务端和contrib包。contrib里包含了很多常用扩展和工具,比如pg_stat_statements(SQL性能分析)、pgcrypto(加解密函数)、uuid-ossp(UUID生成)等,没有这个包,后面想用这些功能都得临时补装。

yum install -y postgresql15-server postgresql15-contrib

安装完成后,PostgreSQL的可执行文件会在/usr/pgsql-15/bin/目录下,数据目录默认在/var/lib/pgsql/15/data/。可以通过下面命令验证安装是否成功:

/usr/pgsql-15/bin/postgres --version # postgres (PostgreSQL) 15.x

同时确认一下系统是否自动创建了postgres用户:

id postgres # uid=26(postgres) gid=26(postgres) 组=26(postgres)

这个用户是PG官方RPM包自动创建的,用于运行数据库进程,后面所有数据库操作都在这个用户下完成。

3.3 初始化数据目录与数据库实例的取舍

安装完成后,数据库的数据目录不会自动生成,需要手动初始化。官方RPM提供了一个便捷脚本:

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

这条命令会读取默认配置,用postgres用户身份创建数据目录并生成初始配置文件。脚本执行成功后,/var/lib/pgsql/15/data/下会出现postgresql.confpg_hba.confPG_VERSION等核心文件。

如果你想自定义数据目录,比如放在/data/pgsql,就不能用这个脚本了,得手动操作。其实也很简单,原理就是先用postgres用户创建目录,再调用initdb指定参数:

mkdir -p /data/pgsql chown postgres:postgres /data/pgsql su - postgres -c "/usr/pgsql-15/bin/initdb -D /data/pgsql --encoding=UTF8 --locale=en_US.UTF-8 --data-checksums"

这里有两个参数值得注意:--encoding=UTF8是让中文数据正常存储的关键,很多人忘记指定导致后面建库默认SQL_ASCII编码;--data-checksums是开启数据页校验,虽然有一点点性能开销,但能提前发现磁盘层面的静默数据损坏,对于生产环境非常值得开启。

关于initdb,还有一个容易纠结的问题:用脚本初始化还是手动初始化?能用官方脚本就别手动,因为脚本会处理好权限、SELinux标签、日志路径等一堆细节。只有当你确认要更改数据目录位置时才需要手动initdb,手动方式相当于绕过了官方默认路径,一切自己负责。

4. 服务管理与基础配置:让PostgreSQL按你的意愿跑起来

初始化之后,数据库还不能算真正立起来,需要启动服务、调整配置,并按需开放网络访问。这一步做得细致与否,直接影响后续使用的顺滑程度。

4.1 systemctl启停、开机自启与常见管理命令

PostgreSQL官方RPM会注册好systemd服务,名字带版本号后缀:

# 启动服务 systemctl start postgresql-15 # 设置开机自启 systemctl enable postgresql-15 # 查看运行状态 systemctl status postgresql-15

其他常用命令也一并列出来:

systemctl stop postgresql-15 # 停止 systemctl restart postgresql-15 # 重启 systemctl reload postgresql-15 # 重载配置,不中断连接

reloadrestart的区别值得说明一下:修改postgresql.conf里的多数参数后,并不需要重启数据库,reload让主进程重新读取配置文件即可,已连接的业务不会受影响。只有少数参数(如shared_buffers)是启动时加载、reload不生效的,那些参数才需要restart。

服务起来后,默认会监听本地5432端口,用postgres系统用户登录:

su - postgres psql -U postgres -p 5432

如果此时能进入psql提示符,说明服务正常。

4.2 postgresql.conf核心参数调整(shared_buffers、work_mem等)

默认配置适合低负载场景,但生产环境不可能满足于默认值。重点看/var/lib/pgsql/15/data/postgresql.conf里的几个参数。

  • shared_buffers:PG的共享缓冲池,决定数据缓存大小。一般建议设为物理内存的25%,比如服务器有8G内存,就设2GB。注意这个参数需要重启生效。
  • work_mem:单个排序或哈希操作可用的内存。不宜全局设太大,否则高并发下内存会瞬间打满。一般先给16MB~64MB,后续根据实际排序慢的SQL再调。
  • maintenance_work_mem:用于VACUUM、创建索引等维护操作的内存,可以设到256MB~512MB。
  • max_connections:默认100,如果业务并发高,可以调到200或300。注意每多一个连接都会占用一定内存,别盲目调大。
  • wal_level:默认是replica,如果要使用逻辑复制,需要保持这个值不变或改为logical

修改完成后,用SELECT pg_reload_conf();或在shell里执行systemctl reload postgresql-15应用改动,注意shared_buffers等参数需要重启。

一个实用的检查方式是,改完参数后跑一下:

SHOW shared_buffers; SHOW work_mem;

确认实际生效值和自己预想一致,避免配置了但没生效的尴尬。

4.3 认证与远程访问配置(pg_hba.conf + firewalld + SELinux)

本地连接验证没问题后,如果需要远程访问,还有三关要过:pg_hba.conf、防火墙、SELinux。

第一关,pg_hba.conf配置客户端认证。

配置文件位于/var/lib/pgsql/15/data/pg_hba.conf,默认只允许本地socket连接。增加远程访问行,比如允许192.168.1.0/24网段使用密码连接所有数据库:

host all all 192.168.1.0/24 scram-sha-256

同时确认postgresql.conf里的listen_addresses不是localhost,改为*或者具体的业务网卡IP:

listen_addresses = '*'

改完后重启服务或reload。

第二关,防火墙放行5432端口。

CentOS 7默认使用firewalld:

firewall-cmd --permanent --add-port=5432/tcp firewall-cmd --reload

如果服务器用的是云厂商安全组,还需要在控制台里同步放行5432端口,两者都放行才能通。

第三关,SELinux放行PostgreSQL网络访问。

CentOS 7默认SELinux是Enforcing,很多远程连不上就是它拦的。检查方式:

getenforce # Enforcing

临时放行:

setsebool -P httpd_can_network_connect_db 1 # 如果你用的是Apache转发

但PostgreSQL场景更常见的是需要放行5432端口:

semanage port -a -t postgresql_port_t -p tcp 5432

如果没有semanage命令,先装policycoreutils-python-utils

yum install -y policycoreutils-python-utils

这三关全过完,远程客户端才能连上数据库。我遇到过的远程连不上的案例里,大约一半是防火墙或安全组问题,三成是pg_hba.conf写错了,剩下两成才是SELinux。

5. 安装后必做的验证与空跑测试

服务跑起来,配置也改了,很多人就以为大功告成,直接去接业务了。但专业做法是先做一轮验证和空跑测试,把隐患在业务接入前暴露出来。

5.1 本地psql连接与基础操作验证

先切到postgres用户,用本地socket做基础验证:

su - postgres psql -U postgres -c "SELECT version();"

正常会输出类似:

PostgreSQL 15.x on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 ...

然后检查几个关键状态:

-- 查看当前连接情况 SELECT * FROM pg_stat_activity; -- 查看数据目录大小 SELECT pg_size_pretty(pg_database_size('postgres')); -- 确认关键扩展可用 CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

这里建议顺手建一个业务测试库,验证权限、编码都正常:

CREATE DATABASE testdb ENCODING 'UTF8' LC_COLLATE 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8' TEMPLATE template0;

注意TEMPLATE template0这个细节,生产库建库时最好不要用默认的template1,因为template1里可能带着你后来添加的对象,用template0更干净。

5.2 用pgbench做一次简单的读写压测

pgbench是PG自带的基准测试工具,装contrib包后就有。不需要压太多流量,简单的几十并发跑一跑,能确认磁盘I/O、CPU、内存配合没有明显问题。

su - postgres /usr/pgsql-15/bin/pgbench -i -s 10 testdb /usr/pgsql-15/bin/pgbench -c 20 -j 4 -T 60 -P 5 testdb

-i -s 10表示初始化10倍默认数据量,-c 20表示20个并发客户端,-j 4表示4个线程,-T 60表示持续60秒,-P 5表示每5秒打印一次进度。

压测完之后,重点看两个数据:TPS和平均延迟。如果在本地跑完,TPS高、延迟低,说明基础环境问题不大;如果TPS很低甚至卡死,多半是磁盘不行或者参数设置不合适,这时候排查比上线后再排查成本低得多。

5.3 日志检查与基线记录

PostgreSQL的日志默认输出到pg_log目录,检查是否有error或warning级信息:

grep -i error /var/lib/pgsql/15/data/log/* | tail -20

初始化阶段常见的warning大多是"could not open statistics file"这类,不必太担心,但如果出现"permission denied"或"out of memory"就需要立刻处理。

最后,把当前关键参数和版本记录到运维文档里,作为基线。将来如果数据库变慢,先对比基线,看是配置被改歪了,还是数据量增长导致的正常退化,能省下大量排查时间。

6. 安装阶段最容易踩的坑(每个都亲测过)

装PG这么多年,踩坑几乎成了常态。这些坑大多不在官方文档的前几页,但在真实环境里流量极高,我单独列出来,算是给读者提前发个免疫疫苗。

6.1 默认源装出9.2,升级迁移的连环坑

如果你手一快执行了yum install postgresql-server,装出来的就是9.2。这不是不能跑,问题是数据库一旦有业务数据,后面想升级到15或16会特别痛苦。pg_dump导出再导入虽然可行,但大库可能要停机几小时,还有各种扩展不兼容的问题。

避免方案只有一条:从一开始就用官方源,明确指定版本号。如果已经装了9.2还没什么数据,建议直接卸载重装:

yum remove -y postgresql-server postgresql rm -rf /var/lib/pgsql/data # 重新按官方源流程安装

别怕麻烦,现在十几分钟的操作能省出后面几天乃至几周的痛苦。

6.2 初始化时报权限/目录错误

postgresql-15-setup initdb如果报权限错误,大概率是数据目录被root用户创建过,或者postgres用户对父目录没有写权限。

最常见的场景是步骤3.3里自定义了/data/pgsql,但chown没执行,或者chown后父目录/data本身不可写。记住,PostgreSQL的postgres系统用户需要有对数据目录的完全rwx权限,并且父目录上的权限遍历也要放行。

另外,/var/lib/pgsql如果曾经被其他工具创建过非postgres属主,也会导致初始化失败。解决办法很简单,检查并修正属主:

ls -ld /var/lib/pgsql chown -R postgres:postgres /var/lib/pgsql

6.3 SELinux拦截导致的连接失败

服务器的SELinux状态对PostgreSQL影响很大。前文说过远程连不上可能有SELinux因素,实际上本地连接有时候也会被坑。

比如你自定义了数据目录到/data/pgsql,SELinux上下文不对,数据库进程可能都启动不了,或者启动后无法写入文件。这种情况下日志里通常会出现permission denied,但用普通手段检查文件权限又一切正常,很迷惑。

解决思路是给自定义目录打上正确的SELinux标签:

semanage fcontext -a -t postgresql_db_t "/data/pgsql(/.*)?" restorecon -Rv /data/pgsql

然后再启动服务。如果SELinux对你来说实在是不熟悉的领域,且服务器是纯内网环境,短期用setenforce 0临时关闭,验证问题是不是SELinux引起的也可以,但生产环境不建议长期关。

6.4 磁盘写满与WAL目录问题

PostgreSQL默认会在pg_wal目录积累WAL日志。在没有配置归档和定期清理的情况下,WAL目录会持续变大,尤其是高写入场景。如果数据和WAL都在同一块磁盘上,磁盘空间告急是早晚的事。

应对办法:

  1. 开启archive_mode并配置归档命令,把WAL定期归档到冷备目录或对象存储。
  2. 监控pg_wal目录大小,超过预期立刻告警。
  3. 在数据盘不足时,用符号链接把pg_wal指到独立的大容量磁盘。
mv /var/lib/pgsql/15/data/pg_wal /data/pg_wal ln -s /data/pg_wal /var/lib/pgsql/15/data/pg_wal chown -R postgres:postgres /data/pg_wal

这个操作要在数据库停止状态下做,否则会出大问题。做完后重启数据库,检查是否正常。

6.5 扩展插件缺失,功能上线的最后一刻掉链子

很多人在开发和测试环境用的是云数据库,或者apt安装的PG,插件很齐全。换成CentOS 7官方源RPM以后,发现某些扩展装不上,比如postgispg_repack,因为对应的contrib包没有安装或需要额外的扩展仓库。

如果遇到ERROR: could not open extension control file,先检查postgresql15-contrib是否安装了。如果业务明确需要地理信息相关功能,还需要单独装PostGIS相关的RPM包。提前在项目初始阶段就把需要的扩展列进模板,比开发到一半再焦虑地补环境好得多。


PostgreSQL安装这件事,说难其实也不难,只要在装之前把版本和源选对,环境细节处理好,初始化后把参数和认证配置捋清楚,生产环境基本就稳了。但说简单也不简单,版本、SELinux、防火墙、磁盘规划这些环节环环相扣,哪一环断了都可能导致后面的连锁问题。我个人最想强调的仍然是最开始那个决定:老老实实走官方YUM源、明确装自己需要的那个主版本,这个选择本身就能避开80%的坑。希望大家装库顺利,少走弯路。

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

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

立即咨询