PostgreSQL 数据库安装部署教程(Linux 多发行版 + Windows + Docker 全覆盖)
PostgreSQL 是排名最靠前的开源关系型数据库,性能、功能直逼商业库:窗口函数、分区表、JSON/JSONB、全文检索、物化视图、逻辑复制、外表(FDW)一应俱全,还支持 C/Python/Java 写自定义函数。很多 DBA 从 Oracle/SQL Server 转过来,最头疼的不是 SQL(超级像),而是安装方式和那些隐藏的坑。本文一篇讲透 PostgreSQL 在各种环境下的安装、初始化、配置与验证。
一句话总结
PostgreSQL 安装的核心套路 = 官方源安装(yum/apt,推荐)+ initdb 初始化 + postgresql.conf 优化 + pg_hba.conf 放行 + systemd 托管 。记住三个"和 Oracle 不一样":超级用户叫 postgres、数据目录用 initdb 生成、默认只监听 localhost,其余都是日常。
一、先认识 PostgreSQL
1.1 它是什么
PostgreSQL(简称 PG)是一款有 30 余年历史的开源对象关系型数据库,由全球社区维护,采用 PostgreSQL License(类 MIT,可商用无费用)。它在 DB-Engines 排名中常年稳居开源数据库第一。
1.2 和常见商业库的定位对比
| 特性 | PostgreSQL | Oracle | SQL Server |
|---|---|---|---|
| 授权 | 开源免费(类 MIT) | 商业授权 | 商业授权 |
| 运营商 | 社区 + 多家商业支持 | 甲骨文 | 微软 |
| 高可用方案 | 流复制 + Patroni(托管)/ repmgr / 逻辑复制 | RAC / Data Guard | Always On |
| 自带读写分离 | 流复制原生支持 | Active Data Guard | 只读副本 |
| JSON 支持 | JSONB(索引查询) | JSON 有限 | 有限 |
| 全文检索 | 原生(中文需分词插件) | Oracle Text | Full-Text |
| 与 Oracle 兼容性 | 有 oracle_fdw、兼容插件 | 原生 | 原生 |
对 DBA 来说最有吸引力的两点:功能接近商业库 + 零授权成本。国内信创、降本增效背景下,Oracle→PG 的迁移需求近几年暴涨。
二、版本选择与环境准备
2.1 版本怎么选
PostgreSQL 每年 9 月发布一个大版本,奇数版本(17、19)会引入较多新特性,偶数版本(16、18)主打稳定优化。截至本文,最新版本为 19.x。
| 版本 | 发布时间 | 定位 | 适合场景 |
|---|---|---|---|
| 14.x | 2021-09 | 老稳定版 | 存量环境 |
| 15.x | 2022-10 | 稳定版 | 保守生产 |
| 16.x | 2023-09 | 成熟稳定 | 生产首选(推荐) |
| 17.x | 2024-09 | 新特性较多 | 新项目可选 |
| 18.x | 2025-09 | 最新稳定大版 | 新项目推荐 |
| 19.x | 2026-09 | 刚发布 | 测试、尝鲜 |
markdown
选型口诀:生产求稳 → 16 / 18;新项目尝新 → 17 / 18;
刚发布的版本(19)至少等 2~3 个补丁(19.2+)再上生产。
2.2 环境确认清单
bash
# 确认操作系统
cat /etc/os-release | head -3
# 确认内存/磁盘
free -h && df -h /data
# 确认内核架构
uname -m
# 确认端口占用(PG 默认 5432)
ss -lntp | grep 5432 || echo "5432 未被占用"
| 项目 | 最低要求 | 生产建议 |
|---|---|---|
| CPU | 1 核 | 4 核+ |
| 内存 | 1 GB | 16 GB+(大小为数据量的 1/8~1/4) |
| 磁盘 | 10 GB(系统) | 数据盘独立,SSD,容量=预估 1.5 倍 |
| 系统 | RHEL 8/9、Rocky、Ubuntu 20.04+ | 与业务环境一致 |
| 端口 | 5432 | 内网可达,防火墙放行 |
三、四种安装方式怎么选
| 安装方式 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|
| 官方 yum/apt 源 | 一键安装、自动建服务、便于升级 | 使用发行版官方源的版本可能偏旧 | 生产首选 |
| 源码编译 | 版本自由、可定制编译参数 | 步骤多、无自动服务、编译耗时长 | 特殊版本、定制环境 |
| Windows 安装器 | 图形向导、自带 pgAdmin | 生产服务器很少用 Windows | 学习、测试、Windows 环境 |
| Docker | 秒级部署、环境隔离 | 数据持久化需挂卷,性能有微弱损失 | 开发测试、CI |
结论先行:Linux 生产环境 = 官方仓库 + rpm/deb 包;学习验证 = Docker 最省事。
四、Linux 安装(yum 源,RHEL/CentOS/Rocky/Alma)
4.1 添加官方 yum 仓库
以 PostgreSQL 17 为例(RHEL 系 8/9 通用,本文以 Rocky 9 演示):
bash
# 1. 安装官方仓库 rpm(RedHat 系 9)
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# 2. 关闭系统自带仓库中的 postgresql
sudo dnf -qy module disable postgresql
# 3. 安装客户端与服务器
sudo dnf install -y postgresql17-server postgresql17-contrib postgresql17-libs
# 4. 确认版本
/usr/pgsql-17/bin/postgres --version
版本号对应表:
postgresql17-server对应 PG17;要装 16 把包名换成postgresql16-server即可。不要混装两个大版本。
4.2 初始化数据目录
bash
# 数据目录默认是 /var/lib/pgsql/17/data,也可以指定其他路径
sudo -u postgres /usr/pgsql-17/bin/initdb -D /var/lib/pgsql/17/data \
--encoding=UTF8 --locale=en_US.UTF-8 --data-checksums
# 查看帮确认生成了哪些文件
sudo ls /var/lib/pgsql/17/data/
初始化后的核心文件清单:
| 文件/目录 | 作用 |
|---|---|
postgresql.conf |
主配置文件(性能、日志、连接) |
pg_hba.conf |
客户端访问认证配置 |
PG_VERSION |
记录版本 |
base/ |
默认数据库目录(postgres、template0/1) |
postgresql.auto.conf |
ALTER SYSTEM 生成的高级配置 |
pg_ident.conf |
身份映射(SSO 场景用) |
template0/1是模板库:template1 默认含你的扩展,新建库以它为蓝本(所以别在 template1 乱装插件)。
4.3 启动服务并设置开机自启
bash
sudo systemctl enable postgresql-17
sudo systemctl start postgresql-17
systemctl status postgresql-17
验证进程与端口:
bash
sudo -u postgres psql -c "SELECT version();"
ss -lntp | grep 5432
五、Ubuntu/Debian 安装(apt 源)
bash
# 1. 添加官方 apt 仓库(以 22.04 LTS + PG17 为例)
sudo apt install -y wget gnupg ca-certificates
sudo install -d /usr/share/postgresql-common/pgdg
sudo wget -O /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \
https://www.postgresql.org/media/keys/ACCC4CF8.asc
echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
https://apt.postgresql.org/pub/repos/apt jammy-pgdg main" \
| sudo tee /etc/apt/sources.list.d/pgdg.list
# 2. 安装
sudo apt update
sudo apt install -y postgresql-17 postgresql-contrib-17
# 3. 服务管理
sudo systemctl status postgresql@17-main
sudo systemctl enable postgresql@17-main
⚠️ Ubuntu 的坑:Debian 系把数据目录放在
/etc/postgresql/17/main/,配置文件分散在/etc/postgresql/17/main/,和 RHEL 系(全在数据目录下)不一样。改配置要改 /etc 下的,不是数据目录下的。
| 发行版 | 服务名 | 配置文件位置 | 数据目录 |
|---|---|---|---|
| RHEL/Rocky | postgresql-17 |
/var/lib/pgsql/17/data/ |
同上 |
| Ubuntu/Debian | postgresql@17-main |
/etc/postgresql/17/main/ |
/var/lib/postgresql/17/main/ |
六、Windows 安装(图形向导)
6.1 下载安装
- 到 EnterpriseDB 下载页 下载
EDB Installer(包含 pgAdmin 和 Stack Builder) - 运行安装器,逐项确认:
| 步骤 | 选择 |
|---|---|
| 安装目录 | C:\Program Files\PostgreSQL\17 |
| 数据目录 | C:\Program Files\PostgreSQL\17\data |
| 组件 | 勾选 PostgreSQL Server + pgAdmin 4 + Stack Builder |
| 超级用户密码 | ⚠️ 设置 postgres 的密码,记牢! |
| 端口 | 5432 |
| 区域 | Chinese (Simplified, China) |
- 完成后自动注册 Windows 服务
postgresql-x64-17,开机自启
6.2 命令行验证(免安装 psql 客户端)
bat
:: 把 pg 的 bin 加进 PATH(下次重启终端生效)
setx PATH "%PATH%;C:\Program Files\PostgreSQL\17\bin"
:: 连接测试
psql -U postgres -h localhost -p 5432
Windows 生产环境少见,但开发机、测试机、培训环境用 Windows 装 PG 是最快的上手方式。注意:Windows 下目录路径用反斜杠,配置文件路径和 Linux 有差异。
七、Docker 安装(最快上手)
7.1 单机快速跑起来
bash
# 拉镜像并启动(-v 挂卷持久化,-e 设置密码)
docker run -d --name pg17 \
-e POSTGRES_PASSWORD=mysecret \
-e POSTGRES_USER=dba \
-e POSTGRES_DB=testdb \
-p 5432:5432 \
-v pgdata:/var/lib/postgresql/data \
postgres:17
# 进入容器执行 psql
docker exec -it pg17 psql -U dba -d testdb
7.2 docker-compose 规范版
yaml
# docker-compose.yml
services:
postgres:
image: postgres:17
container_name: pg17
restart: always
environment:
POSTGRES_USER: dba
POSTGRES_PASSWORD: "${DB_PASSWORD}" # 用环境变量,别硬编码
TZ: Asia/Shanghai
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
- ./init:/docker-entrypoint-initdb.d # 第一次启动自动执行初始化 SQL
healthcheck:
test: ["CMD-SHELL", "pg_isready -U dba -d testdb"]
interval: 10s
timeout: 5s
retries: 5
volumes:
pgdata:
7.3 Docker 的坑
| 坑 | 说明 |
|---|---|
| 不挂卷 = 数据全没 | 容器删了数据就没了,必须挂 -v |
| 官方镜像自动 initdb | 首次启动自动初始化,POSTGRES_PASSWORD 只对初启用 |
| 容器内是 root | 官方镜像默认 postgres 用户,进容器操作注意权限 |
| 版本 tag | postgres:17 = 17 最新补丁;要挑特定补丁用 postgres:17.3 |
| 别对运行中的容器改密码 | 环境变量只在首次初始化生效,之后改要改数据配置 |
八、初始化后的关键配置
8.1 必须先改的 postgresql.conf 参数
bash
sudo -u postgres vi /var/lib/pgsql/17/data/postgresql.conf
| 参数 | 默认值 | 建议 | 说明 |
|---|---|---|---|
listen_addresses |
localhost |
* 或内网 IP |
允许远程连接(改完重启) |
port |
5432 | 5432 | 一般不用改 |
max_connections |
100 | 按业务定,100~500 | 过高会吃内存(每连接约 5MB) |
shared_buffers |
128MB | 内存 1/4 | PG 的 Buffer 池,最重要参数 |
effective_cache_size |
4GB | 内存 3/4 | 给优化器的"可用缓存"参考 |
work_mem |
4MB | 4~64MB | 排序/哈希内存,每条 SQL 每次分配 |
checkpoint_timeout |
5min | 15min | 间隔越长,恢复点越稀疏 |
max_wal_size |
1GB | 2~8GB | WAL 上限,影响恢复速度 |
wal_level |
replica | replica | 流复制/逻辑复制需要 replica 及以上 |
log_min_duration_statement |
-1(关) | 1000(1s+ 记日志) | 慢 SQL 追踪 |
timezone |
系统 | Asia/Shanghai |
业务时区 |
bash
# 一个 16G 内存服务器的快速示例(追加到 postgresql.conf 末尾即可)
shared_buffers = 4GB
effective_cache_size = 12GB
work_mem = 16MB
max_connections = 200
max_wal_size = 4GB
log_min_duration_statement = 1000
# 编辑完后重启生效
sudo systemctl restart postgresql-17
改参数的两条红线 :
listen_addresses、shared_buffers这类参数必须改在postgresql.conf(或ALTER SYSTEM SET),改后重启 ;而work_mem之类可用SET会话级临时调,不用重启。
8.2 pg_hba.conf:远程连接配置(90% 的"连不上"都是它)
bash
sudo -u postgres vi /var/lib/pgsql/17/data/pg_hba.conf
规则格式:连接类型 数据库 用户 地址 认证方式,从上到下匹配,第一条命中即生效:
conf
# 本机无需密码(默认已有)
local all all trust
# 内网网段:192.168.1.0/24 用密码认证
host all all 192.168.1.0/24 scram-sha-256
# 特定用户只允许特定 IP
host mydb appuser 10.0.5.100/32 scram-sha-256
# 允许所有(不推荐生产,测试可用)
host all all 0.0.0.0/0 scram-sha-256
| 认证方式 | 安全级别 | 说明 |
|---|---|---|
trust |
极低 | 不验证密码,仅限本机/测试 |
md5 |
低 | 已过时,明文传输哈希 |
scram-sha-256 |
高 | PG10+ 生产推荐 |
cert |
最高 | SSL 证书认证 |
设置远程用户密码:
sql
-- 设置/修改 postgres 用户密码
ALTER USER postgres WITH PASSWORD '新密码';
-- 建业务用户(生产别用 postgres 连程序)
CREATE USER appuser WITH PASSWORD 'apppass' LOGIN;
GRANT CONNECT ON DATABASE mydb TO appuser;
PG 三连检查清单 :①
listen_addresses是否放开 ②pg_hba.conf是否加了网段行 ③ 防火墙/安全组是否放行 5432。很多同学只改其中一个,然后抓瞎半天。
九、开机自启与日常管理
9.1 systemd 服务管理(RHEL 系)
bash
sudo systemctl enable postgresql-17 # 开机自启
sudo systemctl start postgresql-17
sudo systemctl stop postgresql-17
sudo systemctl restart postgresql-17
sudo systemctl status postgresql-17
9.2 常用管理命令速查
bash
# 连接
sudo -u postgres psql # 本地免密(trust)
psql -h 127.0.0.1 -p 5432 -U appuser -d mydb -W
# 列出数据库/用户
psql -c "\l" # 或 \l+ 看大小
psql -c "\du" # 用户列表
# 数据库管理 SQL
CREATE DATABASE testdb OWNER appuser ENCODING 'UTF8';
DROP DATABASE testdb;
\c testdb # 切换库
9.3 验证安装完整性的检查脚本
sql
-- 一套"体检"语句,装完必跑
SELECT version(); -- 版本
SHOW server_version; -- 简版版本
SELECT current_database(), current_user; -- 当前库和用户
SHOW listen_addresses; -- 监听配置
SHOW shared_buffers; -- 内存配置
SELECT pg_is_in_recovery(); -- 是否备库
SELECT count(*) FROM pg_stat_activity; -- 当前连接数
SELECT * FROM pg_stat_activity WHERE state = 'active'; -- 活跃会话
SELECT pg_current_wal_lsn(); -- 当前 WAL 位置
十、常见问题排查表(高频坑位)
| 症状 | 根因 | 解决 |
|---|---|---|
psql: could not connect to server: Connection refused |
服务没起 / 端口没监听 | systemctl status、查 5432 端口 |
No pg_hba.conf entry for host "x.x.x.x" |
pg_hba.conf 没放行该网段 | 加 host 行 + reload |
could not connect: Password authentication failed |
密码错 / 认证方式不匹配 | 检查用户密码和 pg_hba 认证方式 |
could not translate host name |
主机名解析不了 | 用 IP 连接或加 hosts 记录 |
| 远程连不上但本地可以 | listen_addresses 没改 |
改 * 后重启 |
pg_hba.conf 改完不生效 |
没 reload | SELECT pg_reload_conf(); 或重启(config 变更需重启) |
| 磁盘瞬间写满 | WAL 增长 / 未设 max_wal_size |
设合理 max_wal_size,及时清理归档 |
| 中文乱码 | locale 不对 / 客户端编码 | initdb 时用 --locale=en_US.UTF-8,客户端 SET client_encoding='UTF8' |
initdb: could not find suitable text search configuration |
缺少 libicu 等依赖 | 装 libicu、libicu-devel 再重跑 |
bash
# 万能排查起手式:三连
systemctl status postgresql-17
sudo -u postgres psql -c "SHOW listen_addresses;"
tail -f /var/lib/pgsql/17/data/log/*.log
十一、给 Oracle/SQL Server DBA 的迁移注意点
| 习惯 | Oracle/SQL Server | PostgreSQL |
|---|---|---|
| 默认实例 | 多个实例/库 | 一个集群多个数据库,无"实例"概念(单集群) |
| 超级用户 | sys/system/sa | postgres |
| 自增列 | SEQUENCE/IDENTITY | GENERATED BY DEFAULT AS IDENTITY 或 serial |
| 字符串拼接 | ` | |
| 分页 | OFFSET/FETCH | LIMIT n OFFSET m(最快) |
| 创建库 | CREATE DATABASE 无参数 |
注意指定 ENCODING 'UTF8' |
| 主从切换 | DG/RAC/AlwaysOn | pg_ctl promote 或 Patroni 自动 |
| 高可用工具 | OEM/SSMS | pgAdmin、Patroni、pgbackrest |
sql
-- Oracle 习惯 → PG 写法对照
-- 自增(PG 15+ 与 Oracle 相似)
CREATE TABLE emp (
id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name TEXT NOT NULL
);
-- 分页
SELECT * FROM emp ORDER BY id LIMIT 10 OFFSET 20;
-- 字符串拼接
SELECT '工号: ' || id || ' 姓名: ' || name FROM emp;
最大的认知差异:PG 是一个"集群 = 一套服务 + N 个库",没有 Oracle 的 CDB/PDB 那种多容器概念(多租户走扩展)。迁移时把"实例"思维换成"集群"思维,能少踩一半坑。
十二、安装完成后的安全清单
markdown
□ 1. 修改 postgres 超级用户密码(默认没有强密码策略)
□ 2. 业务程序使用独立账号,禁止直接用 postgres 连接
□ 3. pg_hba.conf 最小化放行:只放业务网段,认证用 scram-sha-256
□ 4. 生产环境开启 SSL(ssl=on)或至少内网隔离
□ 5. 设置 log_min_duration_statement 做慢 SQL 追踪
□ 6. 配置定时备份(pg_dump / pg_basebackup / pgbackrest)
□ 7. 第一次连接成功 → 做一次全量备份,把"第一天"的基线留下
□ 8. 防火墙只放 5432,不给数据库服务器公网映射
bash
# 一条命令完成 6:最简单的全库备份脚本
# crontab 里每天凌晨 2 点执行
0 2 * * * sudo -u postgres pg_dumpall -f /backup/pg_$(date +\%F).sql
DBA 夜话 :PostgreSQL 的安装没有 Oracle 那么多"平台准备 + 检查项无数"的花活,半小时能跑起来------但真正考验人的,是装完之后那三件事 :参数调没调、远程通不通、备份配没配。很多人装完 PG 就开始写业务 SQL,等某天磁盘报警或主库挂了,才发现
pg_hba.conf还停在 trust、备份还是空的。装库这件事,"能连上"只是起点,"敢上线"才算完成。愿你装完的每个 PG,都是加了保险丝的那种。今夜,稳压器常亮,5432 永不打盹。