十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CentOS 7 安装 PostgreSQL 14 完全指南:从 PGDG 仓库到远程连接避坑

CentOS 7 安装 PostgreSQL 14 完全指南:从 PGDG 仓库到远程连接避坑 CentOS 7 上装 PostgreSQL 14这个话题其实已经不算新鲜但在生产环境里我一年至少被问到十几次。不是因为步骤有多难而是这里面藏着几个别人不会明说的坑系统自带的 yum 源里是 2012 年的 PostgreSQL 9.2、装完 PGDG 仓库后服务名不叫 postgresql 而叫 postgresql-14、默认只监听 localhost、认证方式默认走 scram-sha-256 而不是 md5。这篇文章把我这些年踩过的坑、验证过的流程完整写一遍从环境检查到远程连接、从初始化配置到日常备份尽量一步不落。不管你是搭学习环境的学生还是给生产库做基线部署的运维参考这套流程都能少走很多弯路。1. 安装前想清楚版本选型与环境准备1.1 为什么选 PostgreSQL 14 而不是系统自带版本很多人问过我同一个问题CentOS 7 官方源里就有 postgresql 包直接 yum install postgresql 不就行了吗这个问题我在实际项目里碰到过太多次必须说清楚。CentOS 7 基础源Base 仓库里带的 PostgreSQL 是 9.2 版那是 2012 年发布的老古董功能、性能、安全性都差得远尤其是对 JSONB、窗口函数、CTE、并行查询这些现代业务常用特性的支持几乎停留在上古时代。如果你只是装个数据库存点测试数据那 9.2 倒也能跑一旦涉及生产业务、新老数据迁移、对接新版本生态你会发现 9.2 连很多常见语法都报错更别提什么逻辑复制、分区表增强这些 10 之后才有的硬能力。PostgreSQL 14 恰好是 13 到 15 之间一个非常成熟的版本。它有并行 VACUUM、逻辑复制增强、连接管理优化、TOAST 行外存储改进稳定性经过了大规模生产验证。相比更新的 15/1614 的第三方插件兼容性和应用生态更成熟很多云厂商的托管数据库目前也大量运行在 14 上。我在 CentOS 7 上分别部署过 14、15、16说实话14 是兼容性和稳定性最省心的一个尤其是配合老一点的硬件和内核版本踩坑概率最低。所以这篇文章的主线就用 PostgreSQL 14这也是目前 CentOS 7 存量服务器上性价比最高的选择。1.2 环境检查确认系统版本与资源开工之前先花两分钟确认一下系统状况。我用过太多服务器一上来就装装到一半发现系统版本不对、磁盘不够甚至架构不对浪费时间也容易把环境搞乱。建议先执行这几条命令cat /etc/redhat-release uname -m free -h df -h第一条看系统版本确认是 CentOS 7.x第二条看架构PGDG 仓库区分 x86_64 和 aarch64如果机器是 ARM 架构下载地址要对应换掉第三条和第四条分别看内存和磁盘。PostgreSQL 14 安装包本身占用不大二进制包加依赖不超过 200MB但数据目录至少预留 10GB 以上生产环境按业务增长量来算建议单独挂载数据盘。内存方面2GB 起步能跑4GB 以上会更舒服后面调 shared_buffers 等参数时内存越大越有操作空间。还有一个很多人忽略的点检查系统时间。PostgreSQL 的认证、日志、复制都依赖准确的时间如果服务器时间偏差太大后面做逻辑复制或者排查问题时会非常痛苦。顺手跑一下date看看时间对不对通常 CentOS 7 用 chronyd 或 ntpd 同步时间如果时间不对可以先yum install -y chrony systemctl enable --now chronyd把时间同步搞定。1.3 三种安装方式的对比与选型在 CentOS 7 上装 PostgreSQL 14主流无非三种方式PGDG 官方 YUM 仓库安装、源码编译安装、Docker 容器安装。这三条路我都走过各有适合的场景。PGDG 官方仓库是首选也是本文的重点。它由 PostgreSQL 全球开发组维护针对 Linux 各大发行版打包安装、升级、卸载都走系统包管理服务也能用 systemctl 统一管理省心省力。源码编译适合需要自定义编译参数、或者目标机器无法访问外部网络的极端场景但对 PostgreSQL 这种复杂度很高的项目来说编译耗时长、依赖多而且后续升级很麻烦非必要我不推荐。Docker 安装适合快速验证、测试环境命令一行就能拉起一个实例但要把数据目录持久化到宿主机还要处理端口映射和容器重启策略网络模式差异也会带来一些隐性坑生产环境用得少。顺便说一句网上很多教程会教你下载 tar.gz 源码包自己编我建议除非有明确的定制需求否则直接在 PGDG 仓库里装就好。包管理器管版本、管依赖、管升级这是 Linux 世界的正道。很多人觉得源码编译看起来更可控实际上社区维护的 RPM 包在编译参数上已经做了充分的优化自己编译很难比它做得更好。2. 基于 PGDG 仓库的完整安装流程2.1 配置官方 YUM 源一个文件搞定版本选择PGDG 为各 Linux 发行版提供了统一的仓库 RPM 包安装这个 RPM 后系统会自动生成对应的 yum 源配置文件。在 CentOS 7 x86_64 上执行yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm装完这个 rpm 后/etc/yum.repos.d/下会多出 pgdg-redhat-all.repo 文件。打开看一眼你会发现里面按不同大版本分别定义了仓库段比如 pgdg14 对应 PostgreSQL 14pgdg15 对应 PostgreSQL 15。默认情况下这些仓库是全部启用的这也是为什么执行yum list available | grep postgresql时能看到一堆不同大版本的包。这里有个实际操作中的细节CentOS 7 自带的 Base 源也提供 postgresql 9.2 的包装了 PGDG 仓库后同一个软件名会存在多个源里的不同版本。为避免yum install postgresql时被基地源抢先装上 9.2PGDG 的 rpm 会在 yum 配置里自动加入 exclude 规则把 postgresql、postgresql-server 等基础包名从非 PGDG 源中排除掉。你装完仓库后可以用yum repolist确认仓库状态如果发现某个源被 exclude 影响也不用慌安装时显式指定包名带版本号即可比如 postgresql14-server。注意不要手动去改 pgdg-redhat-all.repo 里的 enabled 参数除非你很清楚自己在做什么。默认全部启用的状态意味着你可以自由选择装 14 还是 15 还是 16包名区分很清楚不会冲突。2.2 安装服务端与客户端仓库配置好之后安装就很简单了。在 CentOS 7 上安装 PostgreSQL 14我习惯把服务端和额外组件一起装yum install -y postgresql14-server postgresql14-contribpostgresql14-server 包含数据库服务端、initdb 初始化工具、pg_ctl 管理工具、psql 命令行客户端。postgresql14-contrib 则包含大量官方扩展和工具比如 pg_stat_statements、postgres_fdw、pgcrypto、hstore 等生产环境基本都会用到。我的习惯是一开始就把 contrib 装上省得后面用到某个扩展再补装。安装完成后二进制文件的路径在/usr/pgsql-14/bin/下数据目录默认是/var/lib/pgsql/14/data/配置文件是同一个目录下的 postgresql.conf 和 pg_hba.conf。注意这些路径和系统自带版本完全不同很多人第一反应去/var/lib/pgsql/data/找配置结果扑了个空。这个问题我后面还会再强调一次已经帮不止一个同事排查过这种目录找不到的疑问。验证一下版本/usr/pgsql-14/bin/postgres --version正常会输出postgres (PostgreSQL) 14.x说明核心程序已经就位。接下来进入初始化阶段不建议直接运行 postgres 命令启动服务而是用官方提供的 setup 脚本完成数据目录初始化和基础配置。2.3 初始化数据库并启动服务最容易踩坑的一步PostgreSQL 安装完成后并不会自动帮你初始化数据目录这一步需要手动执行。PGDG 打包时贴心准备了一个初始化脚本命令是/usr/pgsql-14/bin/postgresql-14-setup initdb执行成功后/var/lib/pgsql/14/data/下会生成 PG_VERSION、postgresql.conf、pg_hba.conf、base/ 等文件。这里有个非常关键的坑初始化操作必须以 postgres 用户执行或者用 root 执行上面的脚本脚本内部会自动切换到 postgres 用户。如果权限不对你会看到类似could not change directory to /root: Permission denied的报错。所以务必用上面这个 setup 脚本而不是手动 mkdir initdb脚本把属主、权限都处理好了。初始化完成后就可以启动服务了。很多新手在这里卡住因为他们在网上搜到的一般是systemctl start postgresql但 CentOS 7 下 PGDG 的 14 服务名是 postgresql-14带版本号后缀。以下两条命令才是正解systemctl enable postgresql-14 systemctl start postgresql-14enable 是设置开机自启start 是立即启动。执行systemctl status postgresql-14确认状态如果显示 active (running) 说明启动成功。顺手用ss -lntp | grep 5432看一下监听端口正常会看到0.0.0.0:5432或127.0.0.1:5432的监听记录。注意默认配置下 PostgreSQL 只监听 localhost这个我们马上会改。提示很多人把 enable 和 start 分开执行其实 systemctl 支持一条命令完成systemctl enable --now postgresql-14。--now 参数的意思是立即启动并同时设为开机自启我后面所有脚本里都用这个方式。3. 初始化配置密码、远程访问与系统安全3.1 修改 postgres 超级用户密码PostgreSQL 安装完成后默认会创建一个名为 postgres 的超级用户但这个用户在数据库层面的初始密码是未知的因为本地连接默认走 peer 认证——也就是说操作系统用户是 postgres就能直接以 postgres 数据库用户身份登录不需要密码。这个设计很安全但对于需要远程连接或通过应用连接数据库的场景你必须先给 postgres 设置一个密码。切换到 postgres 系统用户进入 psqlsu - postgres psql在 psql 里执行ALTER USER postgres WITH PASSWORD 你的强密码;然后\q退出。到这里postgres 用户的密码就设置好了。有一点需要说明PostgreSQL 14 默认的密码加密方式是 scram-sha-256这比老版本的 md5 更安全。如果你用 Navicat 之类比较老的客户端连接可能会遇到 password authentication failed 而实际上密码没输错的情况那就是客户端不支持 scram-sha-256。这种问题我会在后面的常见问题小节具体展开。3.2 开放远程访问两张核心配置文件一次说透数据库默认只允许本机连接这一步要改两个文件postgresql.conf 控制服务监听地址pg_hba.conf 控制客户端认证规则。先修改监听地址。编辑/var/lib/pgsql/14/data/postgresql.conf找到这一行#listen_addresses localhost改成listen_addresses *如果你的服务器有多个网卡也可以只监听特定 IP比如listen_addresses 192.168.1.10这样更安全。星号表示所有网卡都监听适合内网环境。改完后需要重启服务才能生效systemctl restart postgresql-14再说 pg_hba.conf。这个文件是 PostgreSQL 的访问控制清单按从上到下的顺序匹配认证规则。默认内容大致如下local all all peer host all all 127.0.0.1/32 ident host all all ::1/128 ident要允许远程主机连接在文件末尾追加一行host all all 0.0.0.0/0 scram-sha-256这一行的含义是允许任意 IP 通过 TCP 连接所有数据库认证方式为 scram-sha-256。如果你只想让某个网段连就把 0.0.0.0/0 换成具体的网段比如 192.168.1.0/24生产环境强烈建议这么做。改完这个文件不用重启执行下面命令重载配置即可systemctl reload postgresql-14注意pg_hba.conf 的匹配规则是从上到下逐行匹配匹配到第一条规则后就不再往下走。如果你在文件中间加了一条比较严格的规则又在末尾加了 0.0.0.0/0 的宽松规则实际生效的可能是先匹配到的严格规则。所以追加远程访问规则时一定要确保文件里没有更早的冲突规则挡在前面。3.3 防火墙与 SELinux 的处理改完配置文件远程还是连不上这是最常见的情况。绝大多数原因不是 PostgreSQL 配置错了而是系统层面的防火墙和 SELinux 拦住了。CentOS 7 默认使用 firewalld。先检查 5432 端口是否放行firewall-cmd --list-ports如果没有 5432/tcp执行firewall-cmd --permanent --add-port5432/tcp firewall-cmd --reload--permanent 表示永久生效--reload 让规则立即生效。如果你用的是 iptables 而不是 firewalld那就执行iptables -I INPUT -p tcp --dport 5432 -j ACCEPT并记得保存规则。SELinux 这块容易被忽略。CentOS 7 默认 SELinux 是 enforcing 模式虽然 PostgreSQL 默认端口 5432 通常不会被 SELinux 拦截入站连接但如果数据库需要作为客户端主动向外连接比如用 dblink、postgres_fdw、逻辑复制订阅或者你改了非默认端口就很可能被 SELinux 拦住。执行getenforce查看当前模式如果是 Enforcing可以先查看相关的布尔值getsebool -a | grep postgresql如果输出里 postgresql_can_network_connect 是 off执行下面的命令打开setsebool -P postgresql_can_network_connect on-P 参数表示持久化重启后依然生效。如果在排查问题时怀疑 SELinux 导致连接失败可以用setenforce 0临时切到 permissive 模式做个对比测试但生产环境测试完一定记得改回来。4. 日常管理服务控制、参数调整与备份策略4.1 systemd 服务管理与日志查看PostgreSQL 14 装好之后日常管理基本都被 systemd 接管了。这里把常用的命令列一下方便直接抄# 启动/停止/重启 systemctl start postgresql-14 systemctl stop postgresql-14 systemctl restart postgresql-14 # 重载配置pg_hba.conf 和部分 postgresql.conf 参数 systemctl reload postgresql-14 # 设置开机自启 systemctl enable postgresql-14 # 查看服务状态 systemctl status postgresql-14查日志有两个途径。一是归档日志PGDG 默认开启了日志收集日志文件在/var/lib/pgsql/14/data/log/目录下文件名类似 postgresql-日期.csv可以用tail -f实时跟踪最新日志。二是 systemd 的 journal 日志执行journalctl -u postgresql-14 -f也能看到服务输出。我在排查启动失败、认证失败时第一件事就是去翻这两类日志几乎所有错误原因都会直接写在里面。比如常见的 FATAL: password authentication failed for user xxx日志会明确告诉你认证失败的用户名和来源 IP排查效率比瞎猜高得多。4.2 关键性能参数初调四两拨千斤装好数据库能跑只是第一步生产环境还需要做基础性能调优。PostgreSQL 默认配置保守得离谱shared_buffers 只有 128MB这对稍微有点并发的业务完全不够。我一般初始化完就顺手把几个核心参数调了。用 postgres 用户登录 psql执行 ALTER SYSTEM 命令即可不需要手工编辑文件ALTER SYSTEM SET shared_buffers 1GB; ALTER SYSTEM SET effective_cache_size 3GB; ALTER SYSTEM SET maintenance_work_mem 256MB; ALTER SYSTEM SET work_mem 16MB; ALTER SYSTEM SET max_connections 200;这些参数怎么取值前提是你的机器物理内存是 4GB。shared_buffers 建议设置为物理内存的 1/4 左右这是 PostgreSQL 的共享缓冲区相当于数据库自己的高速缓存设太低会导致频繁磁盘 IO。effective_cache_size 是给查询规划器看的系统总缓存估值建议设为物理内存的 50% 到 75%。maintenance_work_mem 影响 CREATE INDEX、VACUUM 这类维护操作的速度设大一点能肉眼可见地加速建索引。work_mem 是单个查询排序、哈希操作的内存上限不能全局设得太大否则并发一高内存直接被吃光16MB 是一个比较稳妥的起点。max_connections 根据业务并发来定云主机或者小内存机器建议保持在 200 以内。注意ALTER SYSTEM 修改的参数一部分需要SELECT pg_reload_conf();重载一部分需要重启服务。shared_buffers 和 max_connections 属于需要重启的参数pg_reload_conf() 对它们无效。所以改完参数后如果pg_reload_conf()之后查询SHOW shared_buffers;发现没变化不要慌重启一次 PostgreSQL 就好。验证参数是否生效可以在 psql 里执行SHOW ALL;或者单独SHOW shared_buffers;。另外再提一句已经写进官方文档的优化点如果 PostgreSQL 运行环境和操作系统时钟同步有问题会影响性能监控的准确性但这不是功能故障生产环境只要确保 chronyd 正常运行即可不必过度纠结。4.3 备份与恢复不用等出事才想起备份这件事最怕的就是等出事了才想起。PostgreSQL 14 提供逻辑备份工具 pg_dump 和 pg_dumpall前者备份单个或多个数据库后者备份整个集群包括用户、角色等全局对象。我通常的做法是每天凌晨用 cron 做一次逻辑备份备份文件按日期归档并保留最近七天。一个简单的备份脚本思路如下#!/bin/bash BACKUP_DIR/backup/pgsql DATE$(date %Y%m%d%H%M) su - postgres -c pg_dumpall $BACKUP_DIR/all_$DATE.sql find $BACKUP_DIR -name all_*.sql -mtime 7 -delete恢复时也很直接比如恢复整个集群su - postgres -c psql -f $BACKUP_DIR/all_$DATE.sql postgres注意顺序问题先用 postgres 库作为连接目标来执行脚本脚本里会自动创建其他数据库和对象。逻辑备份虽然简单但只适合中小规模数据量如果数据量上了 TB 级还是建议上物理备份工具比如 pg_basebackup那是另一个话题这里不展开。备份的验证也很重要我吃过亏——定期随机抽一个备份文件恢复到临时实例里确认能正常启动、能查到数据才叫真备份否则只是一堆无效的磁盘占用。5. 常见问题与排查技巧实录5.1 服务启动失败或找不到服务名症状一执行systemctl start postgresql提示 Unit postgresql.service not found。原因很清楚PGDG 的服务名带版本号正确服务名是 postgresql-14。执行systemctl list-unit-files | grep postgresql可以列出所有相关服务单元一目了然。症状二systemctl start postgresql-14报错服务迟迟起不来。99% 是数据目录初始化有问题或者数据目录权限不对。这时候去翻日志看/var/lib/pgsql/14/data/log/下最新日志确认有没有出现FATAL: data directory /var/lib/pgsql/14/data has invalid permissions之类的提示。解决办法通常是把数据目录属主完整还给 postgres 用户chown -R postgres:postgres /var/lib/pgsql/14/data/然后重新 start。另一个常见原因是端口被占用用ss -lntp | grep 5432看一下是不是有其他进程占着 5432。5.2 远程连接超时或被拒绝症状在另一台机器上执行psql -h 服务器IP -p 5432 -U postgres -d postgres一直卡住超时或者直接提示 connection refused。排查顺序是固定的先确认数据库真的在监听ss -lntp | grep 5432再确认监听地址不是只绑了 127.0.0.1cat /var/lib/pgsql/14/data/postgresql.conf | grep listen_addresses然后确认防火墙放行firewall-cmd --list-ports | grep 5432最后确认 SELinux 不是 Enforcing 模式下拦了连接。这四个层级从内到外依次排查基本能定位到问题。很多时候问题出在用户以为改了配置但其实没改对文件或者改完没重启——listen_addresses 参数修改后必须重启服务才能生效只执行 reload 是没用的。5.3 认证失败的坑scram-sha-256 与旧客户端症状密码明明输对了但连接报错FATAL: password authentication failed for user postgres或者提示unsupported frontend protocol。第一个可能原因密码确实不对。检查 pg_hba.conf 里对应行的认证方式是不是 scram-sha-256如果老配置是 md5 而数据库里存的密码是 scram-sha-256 格式也会认证失败。解决办法是重新执行一遍 ALTER USER 设置密码让数据库按当前 password_encryption 参数重新生成密码哈希。第二个可能原因客户端太老不认识 scram-sha-256。PostgreSQL 14 默认的密码加密方式是 scram-sha-256一些老版本的 JDBC 驱动、Navicat、psqlODBC 会对它支持不完整表现就是各种奇怪的认证报错。处理方案有两个方向升级客户端驱动到支持 SCRAM 的版本这是最佳选择如果客户端实在没法升级可以在服务器端把 password_encryption 改为 md5然后用 ALTER USER 重新设置密码同时把 pg_hba.conf 里的认证方式改成 md5。需要强调的是这只是一种兼容性妥协生产环境还是建议优先升级客户端。5.4 一条实用速查表症状优先排查点常用命令服务起不来数据目录权限、端口占用tail -f /var/lib/pgsql/14/data/log/*.csv本地能连远程连不上监听地址、防火墙、SELinuxss -lntp | grep 5432、getenforce密码认证失败密码格式、客户端驱动SHOW password_encryption;连接数打满max_connections 与并发连接SELECT count(*) FROM pg_stat_activity;磁盘占用暴涨日志、WAL、数据膨胀pg_du、查看 pg_wal 目录大小最后再分享一个我个人习惯每次装完 PostgreSQL我会顺手在 psql 里执行SELECT version();把版本号、编译信息留档然后创建一个专门的监控账号只授予 pg_monitor 角色用于日常巡检和监控采集不要用 postgres 超级用户去跑监控。这个小习惯在后续对接监控系统、排查问题时能省下不少事也降低了误操作的风险。PostgreSQL 14 在 CentOS 7 上这套安装流程说穿了其实就三件事配对源、装对包、改对配置。但就是因为每一步都有好几个版本差异和默认值陷阱导致这个看似简单的任务在网络上有大量互相矛盾的教程。按照这篇文章的顺序走下来你应该已经拥有一个能远程连接、能开机自启、参数基线合理、有基础备份方案的数据库实例。如果你之后打算做高可用PostgreSQL 14 配套 Patroni 是目前公认最稳的方案那也是顺着这套基础环境继续往前走的事。我自己的经验是把基础部署做得越规范后面一切扩展都越顺手。
返回列表