最近帮一位同事排查数据库服务器连上去一看他居然把 Postgres 装在 Windows 上跑生产还抱怨“启动好慢、连接一多就卡”。我当场就建议他换 Linux 环境重装一版结果他又问我要一份详细的安装步骤。这题我熟因为光是 PostgreSQL 安装这几年我在各种机器上折腾过不下几十次从编译到二进制包再到 Docker踩坑无数也攒了不少经验。这次干脆把“基础之安装”这件事一次讲清楚覆盖源码编译、发行版仓库、Docker、Windows 安装器这几种主流路子并重点拆解 Linux 源码安装的全过程从依赖准备、参数配置到数据库初始化每步都说清“为什么这么做”最后集中整理安装阶段最常遇到的报错和排查方法给新手朋友一份可以照着做、碰到问题也能翻答案的实战笔记。安装 PostgreSQL 看起来简单无非下载、编译、初始化、启动但真正操作起来版本选择、目录规划、配置文件这些细节会直接影响后续的使用体验。本文适合刚接触 Postgres 的新手也适合正在服务器上部署、想搞懂每个步骤原理的运维和开发者来看读完你可以独立完成一次干净、合规、可维护的安装。1. 安装前必须想清楚的几件事1.1 三个问题装什么、装哪里、怎么装我见过很多人直接apt install postgresql然后什么都不管最后数据目录丢在系统盘版本也跟着系统走后面升级、迁移都麻烦。所以安装前先花三分钟回答三个问题。第一个问题是“装哪个版本”。PostgreSQL 每年发布一个大版本官方维护周期一般是五年左右。如果你是新项目选当前最新的稳定大版本是最省心的选择比如目前的 16 或更高版本如果是要兼容老项目的现有库那就选与生产环境一致的大版本避免版本差异引入行为变化。这里有个小技巧大版本升级不是原地无缝的通常要借助pg_upgrade或 dump 恢复所以选版本时别太激进也别太保守跟着官方支持节奏走即可。第二个问题是“装在哪里”。这里包含两层一是操作系统二是在系统里的目录位置。PostgreSQL 对 Linux 的支持最好Windows 虽然可用但建议只用于开发测试不要跑重要生产。目录方面一定要把“程序目录”和“数据目录”分开数据目录也就是 PGDATA建议放在独立的数据盘上权限收紧沉淀的业务数据不会因为系统盘重装或空间不足而受到影响。第三个问题是“安装方式选哪种”。不同方式有各自的适用场景下面开一张表对比。1.2 安装方式横向对比安装方式优点缺点适合场景Linux 发行版仓库apt/yum命令简单、自动处理依赖、有系统服务脚本版本可能偏旧、目录分散、定制性弱个人开发环境、不追求高度定制的生产环境源码编译安装版本可由自己指定、目录集中可控、编译参数可定制步骤多、耗时较长、需要手动管理服务生产环境、需要定制功能的场景Docker 容器部署一键启动、隔离环境、方便迁移数据持久化需要挂载卷、网络配置需要理解容器网络微服务环境、快速测试、CI/CDWindows 安装器图形化界面、引导式安装、自带初始化仅限 Windows、生产环境不推荐Windows 本地开发、学习练习在我个人看来如果你要在服务器上认真跑数据库源码编译或官方提供的可重定位二进制包是首选不是因为它“显得专业”而是因为目录结构可控参数可以按需调整后续做备份、迁移、升级都更顺手。本文会把源码编译这条最完整的路线讲透其他方式作为补充方案也会给到步骤。提示如果你的机器内存很小预算紧张建议安装前看一眼官方文档对内存的基础要求。数据库这玩意内存小确实能跑但连接一多立刻露馅别指望靠调参数救回来。2. 环境准备三步走依赖、用户、目录2.1 装好编译依赖少走弯路源码编译前先确认系统里有没有需要的库和工具。PostgreSQL 编译最基础的依赖包括编译器gcc、make、系统头文件以及几个可选但推荐安装的库readline命令行历史功能、zlib压缩支持、opensslSSL 连接、libxml2XML 解析、gettext多语言支持。这些库缺失时不一定立刻失败但要么功能受限要么在 configure 阶段直接报错。在 Ubuntu/Debian 系的系统上可以这样一次性装齐sudo apt update sudo apt install -y build-essential libreadline-dev zlib1g-dev \ libssl-dev libxml2-dev libgettextpo-dev flex bison在 CentOS/Rocky 这类 Red Hat 系系统上需要用 yumsudo yum install -y readline-devel zlib-devel openssl-devel \ libxml2-devel gettext-devel flex bison gcc make这里有个很容易被忽视的点编译库和运行库是两份东西。只装运行库比如 libreadline 本体不装-dev或-devel开发包configure 一样找不到头文件。新手报错“readline library not found”时八成不是真的没有 readline而是没装开发包。2.2 创建专用用户让数据库住在自己的房间里PostgreSQL 极度不建议直接用 root 运行。原因很简单数据库进程一旦被利用如果以 root 权限运行攻击者就有可能拿到系统最高权限而且 root 的所有者是系统管理员数据库产生的文件、日志混在一起也不安全。所以一定要创建一个专用系统用户。sudo useradd -m postgres sudo passwd postgres这个用户不需要有登录 shell 之外的特殊权限甚至可以不设密码。很多配置文档直接sudo su - postgres切换过去使用密码就省了。我在生产环境中一般还会顺手把postgres用户的家目录放到/home/postgres方便放备份脚本和归档文件。2.3 目录规划程序目录与数据目录分开这是我从早期踩坑总结出来的铁律程序目录、数据目录、日志目录、归档目录至少数据目录要单独设置。假设我们把 PostgreSQL 安装到/usr/local/pgsql数据目录放在独立的/data/pgsql那么创建目录并授权的方式如下sudo mkdir -p /usr/local/pgsql sudo mkdir -p /data/pgsql sudo chown -R postgres:postgres /usr/local/pgsql sudo chown -R postgres:postgres /data/pgsql为什么单独强调 chown后面用initdb初始化时当前用户必须是数据目录和程序目录的属主如果不是 root 创建的默认属主会直接报权限错误。我见过有人反手chmod 777解决问题那是非常不可取的相当于把数据库的保险柜门卸了改成玻璃门。3. 手把手源码编译安装configure、make、initdb 全流程3.1 下载源码并解压源码包可以从 PostgreSQL 官网指定下载地址获取也可以到国内镜像下载。这里以一篇虚构的最新稳定版本为例# 切换到 postgres 用户 sudo su - postgres cd /home/postgres wget https://example.com/postgresql-16.4.tar.bz2 tar -xjf postgresql-16.4.tar.bz2 cd postgresql-16.4实际使用时最好核对一下下载文件的校验和防止文件不完整或下载过程中被篡改。之前我在某镜像站下载过一次包不大但编译出来老出诡异问题后来才发现是压缩包被截断了。校验这一步不是浪费时间十分钟的编译不值得用一次随机失败去赌。3.2 configure 参数每个选项都想清楚再填configure 是编译安装里信息量最大的一步它决定了一大批编译期行为。这里列几个最常用的参数及含义参数作用我的建议--prefix/usr/local/pgsql指定程序安装位置推荐集中管理--with-pgport5432设置默认端口不用改除非 5432 被占用--with-openssl启用 SSL 支持推荐生产需要加密连接--with-libxml支持 XML 数据如无需要可不加--with-perl/--with-python支持 PL/Perl、PL/Python 存储过程语言按业务需要--enable-debug保留调试信息生产不加源码学习可加--with-data-checksums启用数据页校验重要强烈推荐见下方解释--with-data-checksums这个参数是在initdb阶段生效的也可以在初始化时加-k开启。它的作用是给每个数据页计算校验和一旦磁盘出现损坏或内存问题PostgreSQL 能提前发现并报错而不是默默读出污染数据。这个能力一旦开启后续如果没开想要补开必须停机整库走走一遍相当麻烦。我建议从一开始就带上它虽然会稍微增加 CPU 开销但对数据安全完全是值得的。一个完整的 configure 命令大致是./configure --prefix/usr/local/pgsql \ --with-pgport5432 \ --with-openssl \ --with-libxml \ --with-perl \ --with-python \ --with-data-checksums如果你对某些选项没把握先跑一遍./configure --help查看说明再决定加不加。configure 阶段如果报缺少库直接看错误信息去装对应的-dev包即可不用重新解压源码。3.3 编译安装make 的小知识配置完成后开始编译make -j4-j4表示同时用 4 个并行任务如果你的机器核数是 8 或 16可以写成-j8、-j16能明显缩短编译时间。但也不要贪心把核数全占满会导致机器卡到连 ssh 都反应慢尤其是还在跑业务的机器。我一般保守一点用物理核数的一半左右。编译完成后执行安装make install这时候如果看到类似 “PostgreSQL installation complete.” 的信息就说明编译安装成功了。装完后/usr/local/pgsql/bin下会有一堆可执行文件包括后面要用到的initdb、psql、pg_ctl、pg_dump等等。3.4 环境变量配置让命令随处可用安装完程序后需要把 bin 目录加入 PATH同时设置 PGDATA 环境变量这样日常操作会方便很多。在postgres用户的.bashrc或.bash_profile里加上export PATH/usr/local/pgsql/bin:$PATH export PGDATA/data/pgsql加完后执行source ~/.bashrc生效。这里解释一下为什么单独设置PGDATAPostgreSQL 一堆命令都默认从环境变量里读数据目录比如pg_ctl start时不带-D参数它就会去找$PGDATA。设好之后日常启停就少打好多字也降低搞错目录的风险。3.5 初始化数据目录initdb 是关键动作数据库程序装好了不等于数据库就存在了还需要用initdb在目标目录中初始化一套初始数据。这一步经常被新手漏掉或者不知道初始化参数怎么选。sudo su - postgres initdb -D /data/pgsql \ --encodingUTF8 \ --localeen_US.UTF-8 \ --data-checksums这里三个参数值得解释--encodingUTF8指定数据库集群的默认编码。既然业务数据大多数情况要存中文UTF8 是首选否则可能出现乱码或后续迁移编码转换的麻烦。--localeen_US.UTF-8指定排序规则和语言环境。不要小看这个参数它影响字符串的排序结果和大小写比较行为。如果选错了 locale后面发现 order by 结果不对改起来相当麻烦。--data-checksums对应前面 configure 阶段的选项明确开启数据页校验。如果 initdb 进程执行成功会看到类似 “Success. You can now start the database server” 的输出此时/data/pgsql下生成了PG_VERSION、postgresql.conf、pg_hba.conf、base/等结构和文件。3.6 修改核心配置postgresql.conf 与 pg_hba.conf初始化完毕后在启动之前通常会先动两个文件postgresql.conf和pg_hba.conf。先看postgresql.conf里几个关键参数listen_addresses localhost port 5432 max_connections 100 shared_buffers 128MBlisten_addresses决定数据库监听哪些网络接口。默认localhost只允许本机连接这在测试环境没问题如果允许其他机器连接要改成*或具体 IP。注意这里改了之后防火墙和安全组也要同步放行否则看起来“配置了但连不上”。max_connections默认 100对大部分中小型应用够用。它跟shared_buffers、系统内存互相制约不是想调多高就调多高每个连接都要占内存。shared_buffers这是共享内存池大小默认 128MB 比较保守。经验公式大概是内存的 1/4比如 16GB 内存的机器可以设 4GB但不能超过系统可用内存。改完要重启生效。再来看pg_hba.conf这是客户端认证控制文件决定哪些 IP 用什么方式登录。我经常见到“连接被拒绝”“密码认证失败”的问题一半以上是这里的规则写错了或顺序不对。一个常见的基础配置# 类型 数据库 用户 地址 方法 local all all peer host all all 127.0.0.1/32 scram-sha-256 host all all 0.0.0.0/0 scram-sha-256这里说几点第一行local控制本机 Unix socket 连接一般用peer认证意思是操作系统用户与数据库用户名一致就放行。第二行host控制本机 TCP/IP 连接scram-sha-256比md5安全得多新版本默认支持推荐使用。第三行是允许任意地址连接生产环境务必不要这样裸奔应该改成具体网段比如10.10.0.0/24。pg_hba.conf的规则是自上而下匹配的匹配到第一条就不再往下看所以更严格的规则放在前面。比如想拒绝某个 IP 同时允许整个网段就要把拒绝那条放在允许那条前面顺序反了等于规则失效。3.7 启动、停止与状态查看配置改完后启动服务pg_ctl -D /data/pgsql start启动成功后可以用pg_isready检查端口是否就绪pg_isready -h 127.0.0.1 -p 5432如果返回 “accepting connections”说明数据库已经正常监听。停止服务用pg_ctl -D /data/pgsql stop-D如果已经在环境变量里设了PGDATA可以省掉。但我实际经验是在脚本多、切换环境多的情况下显式写-D更稳妥不容易出现脚本引用了错误目录的情况。3.8 注册 systemd 服务让数据库开机自启源码编译安装不会自动生成系统服务这意味着重启机器之后数据库不会自动起来。我在生产环境上一定会写一个 systemd unit 文件放到/etc/systemd/system/postgresql.service[Unit] DescriptionPostgreSQL database server Afternetwork.target [Service] Userpostgres Typeforking ExecStart/usr/local/pgsql/bin/pg_ctl -D /data/pgsql start ExecStop/usr/local/pgsql/bin/pg_ctl -D /data/pgsql stop ExecReload/usr/local/pgsql/bin/pg_ctl -D /data/pgsql reload PIDFile/data/pgsql/postmaster.pid [Install] WantedBymulti-user.target然后依次执行sudo systemctl daemon-reload sudo systemctl enable postgresql sudo systemctl start postgresql注意区分enable和start只start不enable重启后还是会停。很多人在源码安装后忘记这步重启机器就一脸蒙地问“数据库怎么没了”。4. 几种替代安装路径仓库包、Docker、Windows4.1 系统仓库安装三分钟跑起来如果你不是要深度定制只是本地测试或开发用系统包管理器是最快的。在 Ubuntu 上sudo apt install postgresql postgresql-contrib安装完成后系统会自动创建postgres用户并初始化一个数据目录还会自动注册 systemd 服务。直接运行sudo systemctl status postgresql就能看到服务状态。此时连接数据库sudo su - postgres psql这种安装方式最大优点是省事缺点是比较难定制初始参数而且各个发行版的 PostgreSQL 版本有差异。我这里提醒一下仓库包的安装时间长了apt upgrade 的时候可能直接给你的 PostgreSQL 做大版本升级这是有风险的操作生产环境要谨慎对待别让包管理器在你不经意间升级了数据库。4.2 Docker 部署一条命令包含全套环境Docker 方式在开发、测试、以及容器化生产环境里越来越常见。拉取镜像并启动docker pull postgres:16 docker run -d \ --name pg16 \ -e POSTGRES_PASSWORDmypassword \ -p 5432:5432 \ -v pgdata:/var/lib/postgresql/data \ postgres:16这里-v pgdata:/var/lib/postgresql/data是数据持久化的关键。如果不挂载卷容器一删数据就全没了前面跑的东西全部归零。POSTGRES_PASSWORD是镜像初始化时给超级用户设置的密码首次启动时必须给否则容器起不来。Docker 方式最大的优势是环境一致性本机和服务器可以做到一模一样。但也有一个新坑容器里的 Postgres 默认只监听容器内的5432-p映射只解决主机到容器的转发如果还需要跨主机访问还得配合网络插件、防火墙规则等复杂度比裸机部署反而高一些。所以我个人的习惯是测试和 CI 用容器长期跑数据的库还是放在裸机上管理起来直接明了。4.3 Windows 安装器给不想碰 Linux 的人Windows 下的官方安装器实际上是一个图形化向导双击运行后一路点 Next选数据目录、设超级用户密码、选端口最后点击完成服务就自动装好并启动了。整个过程大约五分钟几乎不会有意外。但我也要说句实话PostgreSQL 在 Windows 上的整体体验比 Linux 上差一大截文件句柄限制、内存分配模型、路径大小写敏感度各种环境差异会在高负载下露出马脚。Windows 装一个做个人开发、做本地测试完全没问题但别把它作为核心生产环境。真要跑线上老老实实上 Linux 服务器才是正路。5. 安装成功后的验证与基础保养5.1 验证安装连接并执行第一句 SQL启动完成后花两分钟做一次基本体检。先看进程ps -ef | grep postgres正常情况下会看到postmaster主进程、checkpointer、background writer、walwriter、autovacuum launcher等一堆后台进程这说明数据库的各个子系统都正常拉起。然后连库执行一句 SQLpsql -h 127.0.0.1 -U postgres -d postgres # 执行 SELECT version();如果返回 PostgreSQL 版本信息说明客户端连接链路正常服务端版本正常库也能正常访问。此时可以建一个测试表插入几条数据再查出来确认读写路径没有问题。5.2 设置超级用户口令initdb 初始化时不会设置密码此时本地 peer 认证可以登录postgres用户但远程连接还不行。建议立刻给超级用户设置密码ALTER USER postgres WITH PASSWORD 强密码;设置后记得重启或 reload 使pg_hba.conf中新的认证方式生效。这里再强调一次不要在生产库上用trust认证那等于公开裸奔也不要继续用 md5新的scram-sha-256在防抓包破解方面更可靠新版本默认就是这个。5.3 配置归档与基础备份习惯安装完成后不要就以为万事大吉。下一步就是开启 WAL 归档和定期备份这是数据库跑上生产前就该做好的功课。至少要在postgresql.conf里开启wal_level replica archive_mode on archive_command cp %p /data/pgsql_archive/%f max_wal_senders 10归档目录要提前建好并授权给 postgres 用户否则归档命令执行会失败导致 WAL 不断堆积。备份策略建议采用“全量基础备份 WAL 归档”的组合定期跑全量pg_basebackup平时靠归档日志滚动恢复这样即使磁盘损坏也能把数据恢复到最近的时间点。5.4 修改监听与防火墙让数据库可以被业务机器连接如果你的数据库需要接受来自其他服务器的连接除了前面改listen_addresses和pg_hba.conf之外防火墙很可能是一堵隐形的墙。Ubuntu 上如果开了 ufw需要放行端口sudo ufw allow 5432/tcpCentOS 上用 firewalld 的话sudo firewall-cmd --permanent --add-port5432/tcp sudo firewall-cmd --reload以及云服务器安全组也需要放行对应入方向规则。这一步排查起来常让人抓狂明明数据库监听正常、认证配置正确就是连不上最后发现是防火墙规则没放行。建议安装完成后直接用远程机器测试一次连接别等到业务上线才发现连不通。6. 常见报错排查实录6.1 编译阶段报错缺库、缺依赖、configure 失败报错信息原因解决方式configure: error: readline library not found缺 readline 开发包安装 libreadline-dev / readline-develconfigure: error: zlib library not found缺 zlib 开发包安装 zlib1g-dev / zlib-develmake: command not found没装编译工具链安装 build-essential / gcc makeflex: command not found或bison: command not found缺词法/语法分析器安装 flex 和 bison这类问题通常看错误提示就明白了装好对应包重跑 configure。这里建议依赖包一次装全避免反复 configure 浪费时间。我常用的判断口诀是configure 阶段报错先补-dev/-develmake 阶段报错多数还是缺头文件或编译工具不是代码的问题。6.2 initdb 阶段报错权限、编码、目录报错信息原因解决方式initdb: error: could not create directory ... Permission denied当前用户无权操作目标目录确认使用 postgres 用户且目录属主正确initdb: error: invalid locale namelocale 参数写错或系统未生成对应 locale用locale -a查看已有 locale或安装对应语言包initdb: error: file system is not allowed as data directory数据目录所在文件系统不允许落盘检查挂载选项或换目录这里特别提一下 locale 问题。很多新手在 Debian 系统上发现en_US.UTF-8不存在因为系统默认只生成了C或POSIX这种最小 locale。解决办法是安装locales包并生成对应 locale或者直接用initdb --localeC.UTF-8。另外提醒集群初始化后 locale 不能随意更改所以提前想好避免办完才发现排序行为不符合预期。6.3 启动阶段报错端口、目录、权限报错信息原因解决方式could not create listen socket for ... Address already in use5432 端口被占用netstat -tlnp查占用进程换端口或停掉占用data directory /data/pgsql has invalid permissions数据目录权限过宽或属主不对数据目录应为 700属主为 postgrespostmaster.pid exists ... removing stale pid file上次异常退出留下旧 pid先确认没有残留进程再手动删 pid 文件或用pg_ctl正常启动FATAL: could not open file ... No such file or directory数据目录缺失或损坏检查 PGDATA 路径是否正确必要时从备份恢复启动类问题中“端口被占用”是最常见的。尤其是机器上装了多个数据库实例或者另一个进程恰好用了 5432都会导致 Postgres 启动失败。不要一上来就换端口先看是谁占用的如果是 MySQL、其他 PostgreSQL 实例要规划好端口分配。必要时用ss -tlnp看清监听进程再决定下一步。6.4 连接阶段报错认证、监听、防火墙报错信息原因解决方式FATAL: password authentication failed for user postgres密码不对或认证类型设置不对检查pg_hba.conf方法用正确密码FATAL: pg_hba.conf rejects connection ...HBA 规则匹配拒绝编辑pg_hba.conf添加对应地址规则并 reloadpsql: could not connect to server: Connection refused数据库没启动或监听地址不对检查启动状态、listen_addresses配置、端口psql: FATAL: database abc does not exist目标库不存在用\l查看数据库列表创建所需库连接阶段的坑往往不在 Postgres 本身而在客户端参数。我在排查时通常按这个顺序走一遍先pg_isready看服务是否在听再psql -h 127.0.0.1测试本机连接最后换远程 IP 测试外部连接逐步缩小范围。把简单问题复杂化的常见原因是改完postgresql.conf后没有重启或改完pg_hba.conf后没有 reload。这两个参数文件虽在同一个目录生效方式完全不一样前者需要 restart后者只需要 reload。6.5 数据目录损坏与校验和报错如果你按本文开启了数据页校验启动或查询时可能遇到WARNING: page verification failed, calculated checksum does not match stored checksum这意味着某个数据页的校验和不一致大概率是硬件层出了问题磁盘坏道、内存故障、文件被外部修改都可能导致这种情况。此时要马上停止对这个实例的写入立刻准备备份恢复并根据备份时间点做 PITR时间点恢复不要抱着侥幸心理直接重启继续跑。数据页损坏如果不及时处理小则单条记录读不出来大则索引结构损坏、整个表不可用。这个警告背后的价值就体现在这里没有开启校验和的时候这类损坏可能要等很晚才暴露出来。7. 最后再分享几个我自己的实操习惯安装这种事情次数多了自然就会总结出一套顺手流程。我现在每次装 PostgreSQL不管装在哪台机器都会固定做这样几件事。第一安装完成后立刻在本地写一个README文件记录安装时间、版本、数据目录、编译参数、初始端口、超级用户名等信息。这个习惯救过我很多次。数据库迁维护、换人接手时一份安装记录比任何口头交接都可靠省去大量考古时间。第二配置完成后主动跑一轮压测脚本模拟比日常高两三倍的连接数观察系统资源占用和连接排队情况。不要等到业务高峰期让数据库在线上“裸考”先在自己可控的范围内暴露瓶颈。实测下来很多性能问题在压测阶段就能发现并解决尤其 shared_buffers 和连接数配置是否合理压一压最直观。第三安装文档里提到的检查和排查手段我建议你自己亲手做一遍比如把配置故意改错看报错信息长什么样再做一遍修复。这个“故意踩坑”的练习法比背十遍文档都管用。因为报错信息在紧张时是找问题的线索而不是干扰项你见过一次、修过一次记忆就非常深刻。PostgreSQL 的安装只是万里长征第一步后面还有备份、监控、高可用、性能调优等一堆活。但地基打得好不好直接决定上面盖的楼稳不稳。把今天的安装步骤吃透数据和配置都规划到位后面的路会顺很多。
阅读完成 · 觉得有帮助?