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 的最新版本所以要先装 EPELExtra 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/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 macOSHomebrew 一条命令搞定macOS 上最省心的方式是 Homebrew。前提是你已经装好了 Homebrew 本身然后执行brew install postgresql16Homebrew 装完会提示你执行的一些初始化命令其中最关键的是数据库目录的初始化。新版 Homebrew 的做法通常是这样# 如果之前没有初始化过先执行这条 initdb --localeC -E UTF-8 /usr/local/var/postgresql16 # 启动服务并设置开机自启 brew services start postgresql16这里解释一下initdb的--localeC -E UTF-8参数--localeC表示使用 C 语言环境避免因系统 locale 不同导致排序规则异常-E UTF-8显式指定数据库内码为 UTF-8。这两个参数在日常开发中几乎是必加的不加的话之后创建数据库如果默认 locale 不是 UTF-8存储中文时会出现乱码或排序错乱的问题。Homebrew 方式安装的 PostgreSQL默认数据目录在/usr/local/var/postgresql16或/opt/homebrew/var/postgresql16取决于 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归属数据库为appdbCREATE 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改成*或具体 IPlisten_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 --encodingUTF8 --localeC.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 的开发者都抽出半小时把安装后的基础配置和验证流程完整走一遍。