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 postgresql16RHEL 系列在安装完之后,默认不会初始化数据目录,需要手动执行初始化和开机自启:
sudo /usr/pgsql-16/bin/postgresql-16-setup initdb sudo systemctl enable --now postgresql-16postgresql-16-setup本质上是对initdb的封装,它会按官方默认参数初始化数据目录到/var/lib/pgsql/16/data,并且把目录所有者设置为postgres用户。这一步如果漏了,启动服务时会直接报错“数据目录不存在或为空”,这是个高频问题。
2.3 两种发行族管理方式对比
装完并不代表万事大吉,后续服务管理命令也需要记住。这里把 Ubuntu 和 RHEL 系列的差异整理成一张表,方便对照。
| 操作项 | Ubuntu/Debian | RHEL/CentOS |
|---|---|---|
| 安装包来源 | PostgreSQL 官方 apt 源 | PostgreSQL 官方 yum 源 + EPEL |
| 服务名称 | postgresql | postgresql-16 |
| 数据目录 | /var/lib/postgresql/16/main | /var/lib/pgsql/16/data |
| 启动服务 | systemctl start postgresql | systemctl 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@16Homebrew 装完会提示你执行的一些初始化命令,其中最关键的是数据库目录的初始化。新版 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 psqlsudo -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 用户。
排查链路:
- 先确认当前系统用户:
whoami - 确认是否执行了
sudo -u postgres psql,而不是直接psql -U postgres - 如果 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 和数据库的规则。如果扫描完都没有匹配行,就拒绝连接。
排查链路:
- 打开 pg_hba.conf,看有没有匹配你客户端 IP 段的行
- 注意规则顺序——pg_hba.conf 是自上而下匹配的,匹配到第一条就不再往后看。如果你在前面写了
host all all 0.0.0.0/0 reject,那后面的放行规则永远不会生效 - 修改完记得
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 目录,导致冲突。
排查链路:
ss -tlnp | grep 5432查看端口占用- 如果端口被其他进程占用,要么换端口,要么停掉占用进程
- 查看 socket 目录是否存在且属主正确:
ls -ld /var/run/postgresql - 如果目录不存在或所属不对,用
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 的开发者,都抽出半小时把安装后的基础配置和验证流程完整走一遍。