ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

CentOS 7上PostgreSQL 15安装配置与避坑指南

CentOS 7上PostgreSQL 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_PASSWORDxxx postgres:15就能拉起实例但生产环境要考虑数据卷挂载、网络模式、容器升级期间的数据迁移复杂度并不低。编译安装适合需要定制编译参数的特殊场景比如自定义块大小、嵌入特定插件。但编译安装要手动处理依赖、初始化脚本、systemd服务后期升级麻烦一般人不建议碰。在CentOS 7上我几乎只推荐第一种方式也就是通过PostgreSQL官方提供的YUM仓库来安装。这不仅是省事的问题更重要的是PG官方会把RPM包和系统管理方式深度整合比如自动帮你创建postgres用户、配置好systemd文件、初始化脚本这些都是编译安装很难得到的红利。1.3 磁盘与内存规划别让数据库装完就陷入资源窘境装数据库之前最好先看一眼服务器的磁盘布局和内存情况。PostgreSQL的数据默认放在/var/lib/pgsql/15/data这个路径依赖根分区或/var分区的空间。很多云服务器根分区就40G装上操作系统、日志、依赖库以后已经去了大半再把数据库塞进去跑几周就告警。至少确认三件事df -h /var确认可用空间足够生产环境建议至少50G以上具体看数据量。free -m确认内存不小于2G如果内存吃紧后面shared_buffers参数就得跟着调低。最好把数据目录规划到独立数据盘比如挂载到/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的网卡默认叫ens33、eth0之类如果没拿到IP编辑/etc/sysconfig/network-scripts/ifcfg-ens33把ONBOOTno改成ONBOOTyes然后systemctl restart network。检查DNS配置在/etc/resolv.conf里是否正确对于国内服务器可以临时换成nameserver 223.5.5.5和nameserver 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官方源。EPELExtra 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-server和postgresql16-server。2.3 时间同步、关闭大页等前置优化安装之前做个快照级别的优化能让数据库跑得更稳。时间同步数据库的事务时间戳依赖系统时间时间不准会导致主从复制、监控告警都不准。CentOS 7默认有chronyd确认它在运行systemctl status chronyd没起来就systemctl start chronyd systemctl enable chronyd。关闭透明大页THPPostgreSQL对内存分配比较敏感透明的hugepage在数据库场景下经常导致内存碎片化官方建议关闭。方法是在/etc/rc.local里加一行echo never /sys/kernel/mm/transparent_hugepage/enabled然后重启生效。调整文件句柄和进程限制数据库打开的文件数远超普通应用在/etc/security/limits.conf里把postgres用户的nofile和nproc调高比如postgres soft nofile 65535、postgres 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_statementsSQL性能分析、pgcrypto加解密函数、uuid-osspUUID生成等没有这个包后面想用这些功能都得临时补装。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 # uid26(postgres) gid26(postgres) 组26(postgres)这个用户是PG官方RPM包自动创建的用于运行数据库进程后面所有数据库操作都在这个用户下完成。3.3 初始化数据目录与数据库实例的取舍安装完成后数据库的数据目录不会自动生成需要手动初始化。官方RPM提供了一个便捷脚本/usr/pgsql-15/bin/postgresql-15-setup initdb这条命令会读取默认配置用postgres用户身份创建数据目录并生成初始配置文件。脚本执行成功后/var/lib/pgsql/15/data/下会出现postgresql.conf、pg_hba.conf、PG_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 --encodingUTF8 --localeen_US.UTF-8 --data-checksums这里有两个参数值得注意--encodingUTF8是让中文数据正常存储的关键很多人忘记指定导致后面建库默认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 # 重载配置不中断连接reload和restart的区别值得说明一下修改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_buffersPG的共享缓冲池决定数据缓存大小。一般建议设为物理内存的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改为*或者具体的业务网卡IPlisten_addresses *改完后重启服务或reload。第二关防火墙放行5432端口。CentOS 7默认使用firewalldfirewall-cmd --permanent --add-port5432/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-utilsyum 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/pgsql6.3 SELinux拦截导致的连接失败服务器的SELinux状态对PostgreSQL影响很大。前文说过远程连不上可能有SELinux因素实际上本地连接有时候也会被坑。比如你自定义了数据目录到/data/pgsqlSELinux上下文不对数据库进程可能都启动不了或者启动后无法写入文件。这种情况下日志里通常会出现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都在同一块磁盘上磁盘空间告急是早晚的事。应对办法开启archive_mode并配置归档命令把WAL定期归档到冷备目录或对象存储。监控pg_wal目录大小超过预期立刻告警。在数据盘不足时用符号链接把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以后发现某些扩展装不上比如postgis、pg_repack因为对应的contrib包没有安装或需要额外的扩展仓库。如果遇到ERROR: could not open extension control file先检查postgresql15-contrib是否安装了。如果业务明确需要地理信息相关功能还需要单独装PostGIS相关的RPM包。提前在项目初始阶段就把需要的扩展列进模板比开发到一半再焦虑地补环境好得多。PostgreSQL安装这件事说难其实也不难只要在装之前把版本和源选对环境细节处理好初始化后把参数和认证配置捋清楚生产环境基本就稳了。但说简单也不简单版本、SELinux、防火墙、磁盘规划这些环节环环相扣哪一环断了都可能导致后面的连锁问题。我个人最想强调的仍然是最开始那个决定老老实实走官方YUM源、明确装自己需要的那个主版本这个选择本身就能避开80%的坑。希望大家装库顺利少走弯路。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进