ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

PostgreSQL安装部署全指南:版本选择、平台适配与初始化配置

PostgreSQL安装部署全指南:版本选择、平台适配与初始化配置

1. 安装前的三个关键判断:版本、平台与软件源

很多人第一次接触 PostgreSQL 时,第一反应是打开官网找下载页。这个思路没错,但实际落地时,最影响安装效率的往往是三个前置判断:选哪个版本、在什么平台装、用什么方式装。这三个问题没想清楚,后面大概率会卡壳或者装出一个用着别扭的环境。

先说版本。PostgreSQL 的版本号看起来很简单,当前主流稳定版本已经到 16、17 这一代,但这里有个常见的误区:不一定要追最新版本,但要尽量避开快接近 EOL(生命周期结束)的旧版本。官方对每个大版本提供约五年的维护支持,比如某个版本如果已经发布了四年以上,那它离停止维护就不远了。对于生产环境,我通常会选“上一个已稳定发布一年以上”的版本,而不是刚发布的大版本——刚发布的大版本虽然功能新,但生态里的扩展插件、监控工具、备份工具未必第一时间适配。对于学习、测试环境,选最新稳定版完全没问题,反正数据丢了也不心疼。

其次是平台。PostgreSQL 在 Linux、Windows、macOS 上都能跑,但安装方式和后续的管理体验差异非常大。Linux 下最推荐用系统包管理器安装,因为这样可以跟随系统的安全更新机制统一升级;Windows 下有官方的图形化安装器,全程点鼠标;macOS 则建议用 Homebrew。还有一种通用方式是 Docker 容器化部署,不过这篇文章主要聚焦在裸机、虚拟机上的传统安装方式,Docker 部署涉及的数据持久化和网络模式是另一套逻辑,后面有机会单独展开。

最后是软件源的选择。这一步最容易被忽略,却直接决定了你能否顺利装完。很多人在 CentOS 上直接执行yum install postgresql,结果装出来的是老掉牙的版本,就是因为默认系统源里的 PostgreSQL 包版本太旧。正确做法是添加 PostgreSQL 官方提供的软件源,或者使用发行版自带的同名基础源加官方源做优先级配置。不用官方源、只靠默认源的话,版本落后、依赖冲突都是家常便饭。

提示:安装之前还有个很容易忽略的小事——确认服务器时间、时区、主机名没有明显异常。PostgreSQL 的日志和事务时间戳都依赖系统时钟,如果时间飘了,后面排查问题时看日志会非常痛苦。

2. Linux 环境安装:以包管理器为主线的最稳路径

Linux 是 PostgreSQL 部署最主流的平台,没有之一。我平时接触最多的两种发行族是 Debian/Ubuntu 和 RHEL/CentOS,两者的安装思路一致,但命令和配置文件路径有差异。这一章分别展开。

2.1 Ubuntu/Debian 系列:官方源 + apt 三步搞定

Ubuntu 的系统源里其实自带 PostgreSQL 包,但版本往往偏旧。我的习惯是先用官方提供的 apt 仓库切换脚本,把官方源加进去,再用 apt 安装。

# 导入官方 GPG 密钥并添加软件源 sudo apt install -y curl gnupg curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor -o /usr/share/keyrings/postgresql-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/postgresql-keyring.gpg] $(lsb_release -cs)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list # 更新索引并安装 sudo apt update sudo apt install -y postgresql-16

这里解释一下刚才做了什么。GPG 密钥的作用是保证你从官方源下载的软件包确实是官方发布的,防止源被篡改。把密钥转成 keyring 文件放到/usr/share/keyrings下,是 Ubuntu 新版本对第三方源推荐的做法,比直接把密钥丢给 apt 更安全。

安装完成后,Ubuntu 的包管理脚本会自动帮你做两件事:创建一个名为postgres的系统用户,以及初始化默认的数据目录/var/lib/postgresql/16/main。这意味着你不需要手动执行initdb——至少在默认路径下不需要。同时,服务也会被注册成 systemd 服务,名字叫postgresql。

验证是否装好,直接看服务状态:

systemctl status postgresql systemctl enable postgresql # 设置开机自启

如果服务状态是 active (running),这一步就成了。需要注意的是,Ubuntu 下同时装了多个 PostgreSQL 大版本时,systemctl status postgresql看的是一个聚合服务,它会把所有版本的实例都拉起来。单版本场景不用管这个细节。

2.2 RHEL/CentOS 系列:先加 EPEL 再装官方源

CentOS/RHEL 的情况比 Ubuntu 复杂一点。默认的 base 源里没有 PostgreSQL 的最新版本,所以要先装 EPEL(Extra Packages for Enterprise Linux)仓库,然后添加 PostgreSQL 官方的 yum 仓库。

# 安装 EPEL(具体包名随系统版本不同略作调整) sudo yum install -y epel-release # 安装官方仓库 RPM 包(以 PostgreSQL 16 为例,RHEL 9 / CentOS 9 环境) sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

添加完仓库后,有一个关键的坑要提醒:官方仓库自带一个pgdg-redhat-all.repo文件,里面区分配置了多个子仓库。建议你打开/etc/yum.repos.d/pgdg-redhat-all.repo检查一下,如果之前系统里装的是系统自带的旧版 PostgreSQL,需要把某些系统自带的模块禁掉,否则 yum 会在依赖解析时报冲突。

安装命令和 Ubuntu 的略有不同:

sudo yum install -y postgresql16-server postgresql16

RHEL 系列在安装完之后,默认不会初始化数据目录,需要手动执行初始化和开机自启:

sudo /usr/pgsql-16/bin/postgresql-16-setup initdb sudo systemctl enable --now postgresql-16

postgresql-16-setup本质上是对initdb的封装,它会按官方默认参数初始化数据目录到/var/lib/pgsql/16/data,并且把目录所有者设置为postgres用户。这一步如果漏了,启动服务时会直接报错“数据目录不存在或为空”,这是个高频问题。

2.3 两种发行族管理方式对比

装完并不代表万事大吉,后续服务管理命令也需要记住。这里把 Ubuntu 和 RHEL 系列的差异整理成一张表,方便对照。

操作项Ubuntu/DebianRHEL/CentOS
安装包来源PostgreSQL 官方 apt 源PostgreSQL 官方 yum 源 + EPEL
服务名称postgresqlpostgresql-16
数据目录/var/lib/postgresql/16/main/var/lib/pgsql/16/data
启动服务systemctl start postgresqlsystemctl start postgresql-16
初始化数据目录安装时自动完成需手动执行 setup initdb
配置文件主文件/etc/postgresql/16/main/postgresql.conf/var/lib/pgsql/16/data/postgresql.conf
客户端认证配置/etc/postgresql/16/main/pg_hba.conf/var/lib/pgsql/16/data/pg_hba.conf

这张表也是我日常排查问题时最先想到的对照清单。很多人装的是同一套数据库,但因为发行版不同,连配置文件路径都找不对,更别提修改配置了。把路径记牢,后面调优化参数、改监听地址的时候才不会手忙脚乱。

3. Windows 与 macOS:图形化安装与 Homebrew 路线

虽然 Linux 是服务器端的主流,但本地开发机用 Windows 或 macOS 的开发者也不在少数。很多人装 PostgreSQL 只是为了本地调试,这时候再开一台 Linux 虚拟机就有点小题大做了。这章分别讲一下这两个平台最舒服的安装方式。

3.1 Windows:官方安装器 + 记住安装路径

Windows 下没有包管理器那种统一的体验,最可靠的方式就是使用官方提供的图形化安装器。

到 PostgreSQL 官网下载页面选择对应 Windows 版本的安装包,双击运行后,安装向导会一步步引导你完成:选择数据目录、设置超级用户 postgres 的密码,以及指定监听端口(默认 5432)。整个过程中最重要的一点是——记住你设置的 postgres 密码和安装路径。

安装路径默认在C:\Program Files\PostgreSQL\16,里面包含bin目录,这个目录里的psql.exe、pg_ctl.exe、pg_dump.exe都是后续高频使用的命令行工具。为了方便在任意终端调用,我强烈建议把C:\Program Files\PostgreSQL\16\bin加到系统环境变量 PATH 里,否则每次都得先cd到 bin 目录才能执行命令。

Windows 下还有一个让新手困惑的点:官方安装器自带了一个名为pgAdmin的图形化管理工具,很多人以为安装完就自动会用,结果打开后不知道该填什么连接参数。这里提示一下,pgAdmin 连接本机时,主机填localhost,端口填5432,用户名填postgres,密码就是你安装时设置的那个,就这么简单。

提示:Windows 下安装完毕之后,服务列表中会多出一个名为postgresql-x64-16的 Windows 服务,默认自动启动。如果哪天启动失败,可以在“服务”管理器中右键查看该服务的登录身份和依赖项,通常能定位到是目录权限不足或端口被占用。

3.2 macOS:Homebrew 一条命令搞定

macOS 上最省心的方式是 Homebrew。前提是你已经装好了 Homebrew 本身,然后执行:

brew install postgresql@16

Homebrew 装完会提示你执行的一些初始化命令,其中最关键的是数据库目录的初始化。新版 Homebrew 的做法通常是这样:

# 如果之前没有初始化过,先执行这条 initdb --locale=C -E UTF-8 /usr/local/var/postgresql@16 # 启动服务并设置开机自启 brew services start postgresql@16

这里解释一下initdb的--locale=C -E UTF-8参数:--locale=C表示使用 C 语言环境,避免因系统 locale 不同导致排序规则异常;-E UTF-8显式指定数据库内码为 UTF-8。这两个参数在日常开发中几乎是必加的,不加的话,之后创建数据库如果默认 locale 不是 UTF-8,存储中文时会出现乱码或排序错乱的问题。

Homebrew 方式安装的 PostgreSQL,默认数据目录在/usr/local/var/postgresql@16或/opt/homebrew/var/postgresql@16(取决于 Apple Silicon 还是 Intel 芯片)。配置文件同样在这个目录下的postgresql.conf里。这一点和 Linux 差别很大,注意别把路径搞混。

3.3 本地环境安装后的最小验证

不管是 Windows 还是 macOS,装完后第一件建议做的事,不是急着建表,而是先确认命令行工具能正常连上。

在 macOS 上执行:

psql postgres

如果你当前系统用户名不是 postgres,这条命令可能报错。macOS 的 Homebrew 版本默认会创建一个与你系统用户名同名的超级用户,所以更稳妥的方式是:

psql -U $(whoami) postgres

而在 Windows 下,由于安装时已经设置了 postgres 密码,默认执行:

psql -U postgres -h localhost

然后输入你设置密码即可。能进入postgres=#提示符,说明这台的安装链路已经通了。

4. 初始化配置:装完不等于能用

很多教程讲到“安装完成、服务启动”就结束了,但实际上这只是走完了一半。PostgreSQL 默认的配置是非常保守的:只监听本机回环地址、只允许本地 peer 认证、默认实例没有任何业务数据库。这一章讲清楚装完后必须做的几件事。

4.1 理解 postgres 用户与 peer 认证

在 Linux 平台上,PostgreSQL 安装完成后会创建一个名为postgres的系统用户。你第一次连接数据库时,需要切换到该用户,或者用该用户的身份执行 psql。

这背后的机制是 PostgreSQL 默认的pg_hba.conf中对本地连接使用了peer认证方式。所谓 peer 认证,就是“操作系统用户是谁,数据库用户就是谁”。也就是说,你当前 Linux 的用户名如果不是postgres,那你用 psql 连接时,即使指定了用户名和密码,也可能被拒绝,因为当前系统身份不是 postgres 用户。

正确的进入方式:

sudo -u postgres psql

sudo -u postgres的意思是临时切换到 postgres 系统用户身份,然后执行 psql。此时 PostgreSQL 看到操作系统用户是 postgres,对照 peer 认证规则,匹配到数据库用户 postgres,于是放行。

很多新手第一次装完,在普通用户下直接执行psql -U postgres,然后被要求输入密码,输入了安装时设置的密码却仍然登录失败,就是因为忽略了 peer 认证这个机制。这一点放在四种认证方式里是最容易让人懵的。

4.2 修改默认密码并创建业务用户

进入 psql 后,第一件事是给 postgres 设置一个自己记得住的强密码:

ALTER USER postgres WITH PASSWORD '你的新密码';

接着创建业务用的普通用户和业务数据库。比如我要创建一个名为appuser的用户,密码为apppass,归属数据库为appdb:

CREATE USER appuser WITH PASSWORD 'apppass'; CREATE DATABASE appdb OWNER appuser; GRANT ALL PRIVILEGES ON DATABASE appdb TO appuser;

这里解释一下OWNER appuser的含义:数据库的所有者是 appuser,也就是说后续建表、建索引等操作,默认以 appuser 身份进行。如果不指定 owner,默认所有者就是当前执行 CREATE DATABASE 的用户(即 postgres),那后面 appuser 在这个库里做操作时反而会因为权限不足而报错。这个小细节在生产环境里经常引发权限问题。

4.3 开启远程访问:postgresql.conf 与 pg_hba.conf 双改

默认情况下 PostgreSQL 只监听 127.0.0.1,这意味着其他机器没法通过网络连接过来。如果你有一台应用服务器和数据库服务器分离,必须改两个地方。

第一个是修改postgresql.conf中的监听地址。找到listen_addresses这一行,把默认的localhost改成*或具体 IP:

listen_addresses = '*'

同时建议把port = 5432显式确认一下。

第二个是修改pg_hba.conf,增加允许远程主机连接的认证规则。比如我希望允许 192.168.1.0/24 网段的机器用密码连接所有数据库:

host all all 192.168.1.0/24 scram-sha-256

这一行的含义是:来自 192.168.1.0/24 网段的客户端,可以以任意数据库用户连接任意数据库,认证方式为scram-sha-256。scram-sha-256是当前推荐的密码认证协议,安全性远好于旧的md5,除非你的客户端工具实在太老,否则都建议用这个。

改完两个文件后,记得重启服务:

sudo systemctl restart postgresql # Ubuntu sudo systemctl restart postgresql-16 # CentOS

这里有个坑:有些人只改了pg_hba.conf,没改listen_addresses;有些人改了监听地址,没改 pg_hba.conf。必须两个文件同时匹配才能联通。我排查过的远程连接问题里,十有八九都是只改了一半。

注意:如果服务器上有防火墙(比如 firewalld 或 ufw),还需要放行 5432 端口。这一步经常被忽略,结果配置文件改得都对,但外部就是连不上,最后发现是防火墙默默地拦了一刀。

5. 验证安装:从进程查看到基础 CRUD 自检

安装配置全部完成后,不能直接说“装好了,收工”。你需要做一套完整的自检,确认数据库不仅能启动、能连接,还能正常读写。这一章分享一套我自己的验证流程,顺手可以用作日常巡检的起步模板。

5.1 版本、进程与端口检查

先在系统层面确认三件事:

psql --version systemctl status postgresql # Linux 下检查服务状态 ss -tlnp | grep 5432 # 确认端口在监听

psql --version输出的版本号要和你要装的版本一致。ss -tlnp查看 5432 端口时,如果看到127.0.0.1:5432说明只在本地监听,看到0.0.0.0:5432或*:5432说明已经可以对外提供服务,后者对应你已经修改过listen_addresses。

Windows 下对应命令是:

psql --version netstat -ano | findstr 5432 Get-Service postgresql-x64-16

检查完状态后,进入 psql 执行一条版本查询:

SELECT version();

这个不仅能确认在用的协议版本,还能顺便验证是否成功连上了数据库实例。

5.2 建库、建表与 CRUD 验证

连接没问题之后,我习惯做一个最小化的读写验证,确认存储引擎和权限链路没有隐藏问题。

CREATE TABLE user_info ( id SERIAL PRIMARY KEY, username VARCHAR(50) NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT now() ); INSERT INTO user_info (username) VALUES ('zhangsan'), ('lisi'); SELECT * FROM user_info; UPDATE user_info SET username = 'wangwu' WHERE id = 1; DELETE FROM user_info WHERE id = 2;

这套操作如果全都顺利执行,说明:

  • 数据目录可写(否则建表会报磁盘权限错误)
  • 序列自增正常(SERIAL 字段)
  • 事务和默认值机制正常
  • 当前用户具备 DML 权限

需要提醒的是,验证表建完记得清理掉,特别是如果你用的测试账号在生产库上做验证,残留的测试表会让人困惑。使用完毕直接执行:

DROP TABLE user_info;

如果你想清理得更彻底,把测试库直接删掉也行:

DROP DATABASE appdb;

但注意:DROP DATABASE 不能在事务块内执行,也不能在连接着目标库时删除它。如果当前正连着 appdb 执行 DROP,会提示“数据库正在被其他用户访问”,需要先切换到 postgres 库再删。

5.3 常用管理命令速查

做验证时我还会顺手检查一些日常管理常用的视图和命令,把它们当作安装完成后是否正常的附加指标。

-- 查看当前连接数 SELECT count(*) FROM pg_stat_activity; -- 查看数据库列表 \l -- 查看表空间的使用情况 SELECT datname, pg_size_pretty(pg_database_size(datname)) AS size FROM pg_database;

其中pg_stat_activity非常有用。如果之后有人抱怨连接连不上,执行:

SELECT pid, usename, application_name, client_addr, state FROM pg_stat_activity;

能立刻看出当前到底有哪些连接、它们各自处于什么状态。state如果全是idle,说明大量连接闲置——这时候调max_connections或者连接池配置,比瞎猜有效得多。

6. 安装过程中的高频坑与排查思路

不是每次安装都顺风顺水,遇到过的问题多了,经验就积累起来了。这一章把我遇到过的高频坑按出现概率排个序,并给出完整的排查链路,帮助你遇到类似问题时不用去搜索引擎捞半天。

6.1 无法以 postgres 身份登录:peer 认证与 sudo 的坑

现象:在 Ubuntu 服务器上执行psql -U postgres,提示密码认证失败,即使刚设置过密码也没用。

根因:前面解释过,Linux 下默认本地认证是 peer,系统不认你在 psql 里输入的密码,只认操作系统当前用户身份。普通用户没有切换权限,自然无法连上 postgres 用户。

排查链路:

  1. 先确认当前系统用户:whoami
  2. 确认是否执行了sudo -u postgres psql,而不是直接psql -U postgres
  3. 如果 sudo 提示“不在 sudoers 文件中”,需要先让 root 用户把当前用户加进 sudo 组

修复:正常使用sudo -u postgres psql,进入后修改 pg_hba.conf,把本机连接认证方式改成scram-sha-256,这样就可以支持输入密码登录。但我不建议对本地连接这么改,peer 认证本身是安全的,没必要自找麻烦。

6.2 远程连接提示 no pg_hba.conf entry

现象:应用服务器连接数据库服务器时,报错消息包含no pg_hba.conf entry for host "192.168.x.x"。

根因:PostgreSQL 在收到客户端请求后,会逐行从上到下扫描 pg_hba.conf,找第一条匹配该 IP 和数据库的规则。如果扫描完都没有匹配行,就拒绝连接。

排查链路:

  1. 打开 pg_hba.conf,看有没有匹配你客户端 IP 段的行
  2. 注意规则顺序——pg_hba.conf 是自上而下匹配的,匹配到第一条就不再往后看。如果你在前面写了host all all 0.0.0.0/0 reject,那后面的放行规则永远不会生效
  3. 修改完记得reload,不用重启:
sudo systemctl reload postgresql

经验:pg_hba.conf 的规则顺序问题,是数据库运维里最容易踩但又最容易忽视的坑。建议把所有精确 IP 的规则写在前面,把宽泛的放行规则(如 0.0.0.0/0)写在最后,这样逻辑最清晰。

6.3 端口被占用与 socket 目录权限

现象:启动服务时直接报错端口被占用,或者 psql 连接时提示找不到 socket 文件。

根因:Ubuntu 下 PostgreSQL 默认会在/var/run/postgresql创建 socket 文件。如果你手动改了unix_socket_directories,权限设置不对,客户端就找不到连接入口。另一个常见场景是,8080 等端口被其他进程占用时,5432 好像没冲突,但有些高版本安装程序会占据另一个内部 socket 目录,导致冲突。

排查链路:

  1. ss -tlnp | grep 5432查看端口占用
  2. 如果端口被其他进程占用,要么换端口,要么停掉占用进程
  3. 查看 socket 目录是否存在且属主正确:ls -ld /var/run/postgresql
  4. 如果目录不存在或所属不对,用chown postgres:postgres修正属主

6.4 编码与 locale 问题:中文乱码根因

现象:数据库创建成功,插入中文数据后查出来是乱码或报invalid byte sequence for encoding "UTF8"。

根因:初始化集群时没有正确设置编码,数据库模板库的字符集和客户端字符集不一致。

排查链路:

SHOW server_encoding; SHOW client_encoding;

如果server_encoding不是 UTF8,说明初始化时 locale 设置有问题。在 Linux 下先确认系统 locale 支持情况:

locale -a | grep -i utf

如果系统里根本没有 UTF-8 locale,需要先安装或生成对应的 locale 文件。

修复:在已初始化的情况下,最省事的办法是重装或重新 initdb,显式指定参数:

initdb -D /var/lib/postgresql/16/main --encoding=UTF8 --locale=C.UTF-8

如果只是想让单个客户端会话正常显示中文,可以执行SET client_encoding TO 'UTF8';,但这只是治标不治本。数据都乱掉之后,再想转化编码非常麻烦。所以初始化那一步就把编码固定下来,是最省心也最正确的方式。

7. 安装之后的扩展:插件与日常维护初探

到此其实安装篇的核心内容已经讲完了。但我始终认为,一个完整的安装教程至少要带一点点“装完之后你会面对什么”的预告。这一章简短聊一下 postgis、pgvector 这类常见插件和备份习惯,作为后续深入的方向。

PostgreSQL 的插件机制和 MySQL 的引擎概念不太一样。插件是一个个独立的扩展库,启用时通常在 psql 里执行一条 CREATE EXTENSION 即可。例如:

CREATE EXTENSION IF NOT EXISTS pgcrypto;

如果你想用地理空间能力,就装postgis;想用向量检索能力,就装pgvector。这类操作往往是安装完成后的第一件正事,因此我把最常见的扩展启用命令列在这里。具体插件的编译安装过程,等真正用到了再展开也不迟。

备份这件事,我的经验是安装完成当天就把 crontab 或者定时任务配置好。PostgreSQL 自带pg_dump/pg_dumpall,最简单的全库备份脚本如下:

#!/bin/bash BACKUP_DIR="/backup/postgres" DATE=$(date +%Y%m%d_%H%M%S) pg_dump -U postgres -h localhost appdb -F c -f "$BACKUP_DIR/appdb_$DATE.dump" find "$BACKUP_DIR" -type f -name "*.dump" -mtime +7 -delete

这个脚本做了两件事:把appdb数据库备份为自定义格式的 dump 文件,并清理 7 天前的旧备份。建议先在命令行手动执行一遍确认没报错,再加到 crontab 里,否则定时任务出错了你都不知道。

我在实际运维中最深的体会是:PostgreSQL 的安装本身不难,难的是安装完成之后的那一整套配套习惯——密码策略、权限规划、备份策略、监控指标。这些东西如果从第一天就有意识地建立起来,后面不管数据库体量怎么涨,你都稳得住。反过来说,如果装完就急着写业务代码,等数据量上来再回头补运维功课,那成本会翻好几倍。这大概也是为什么我建议每一位刚接触 PostgreSQL 的开发者,都抽出半小时把安装后的基础配置和验证流程完整走一遍。

RELATED READING

延伸阅读

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