news 2026/10/19 10:48:56

PostgreSQL 13源码安装实战:从configure到systemd全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PostgreSQL 13源码安装实战:从configure到systemd全解析

PostgreSQL 13 正式发布之后,我一直在犹豫要不要把生产环境的数据库从老版本迁过来。2021 年初终于下定决心做一轮基础环境升级,选定的方式就是源码安装,而不是直接用发行版自带的 yum 或 apt。原因很简单:我需要在一台服务器上同时管理多个实例,还要按业务场景裁剪编译参数,包管理器给不了这种灵活度。这篇文章记录的就是 2021 年 3 月这次 PostgreSQL 13 源码安装的完整过程,包括依赖准备、configure 参数取舍、initdb 初始化和排障实录。如果你也想搞明白源码安装背后每一步的原因,或者正准备动手编译一次,这篇文章可以直接拿来当参考。

1. 为什么选源码安装:先想清楚再动手

1.1 包管理与源码编译的取舍

很多人一听源码安装就觉得麻烦,其实要先问自己一个问题:你到底需要什么?如果只是本地开发跑一下,包管理器一条命令装完完全够用。但一旦涉及下面这些场景,源码安装的优势就出来了:

  • 版本精度要求高。发行版仓库里的 PostgreSQL 经常滞后一到两个大版本,而且小版本更新节奏也不可控。我要用 13.x 的特定小版本时,包管理器给不了。
  • 多实例共存。同一台机器上要跑两个以上不同版本的 PG,只有源码安装能保证每个版本完全隔离,互不干扰。
  • 编译参数定制。比如我要用--with-openssl开启 SSL 支持、--with-perl做 pl/perl 开发、调整--with-segsize这类底层的页面段大小,这些只能通过源码编译阶段注入。
  • 目录布局自主可控。生产环境里我习惯把程序和数据彻底分开,程序放/usr/local/pgsql13,数据放独立的/var/lib/pgdata,包管理器装出来的布局很难完全按我的规范来。
对比项包管理器安装源码安装
安装速度快,几分钟较慢,编译时间取决于机器性能
版本控制受仓库限制完全自定义
参数定制基本固定configure 阶段全可控
多版本共存较麻烦天然支持
维护成本低,yum/apt 直接管理需要自己管理升级和 service 文件

当然,源码安装的代价也很实在:编译要花时间,依赖要手动补齐,升级要自己处理。所以做这个决定之前,先把需求列清楚,别为了“显得专业”而盲目编译。

1.2 环境确认:系统信息与编译工具链

这次安装的目标机器是一台 CentOS 7.9 服务器,内核版本比较老,但 PostgreSQL 13 对操作系统的要求并不苛刻,Linux 3.x 内核以上都能跑。动手之前先确认三件事:系统版本、可用内存和磁盘空间。

cat /etc/centos-release uname -r free -h df -h /usr/local /var/lib

编译 PostgreSQL 13 对内存和磁盘的要求不高,2G 内存、10G 可用磁盘就足够了,但如果你要make -j并行编译,内存建议至少 4G,否则容易把机器压到 swap。磁盘方面,源码解压后约 1GB 左右,编译中间文件会再占一部分,我一般至少预留 5GB 保险。

工具链检查也不能省。PostgreSQL 13 对编译器版本有硬性要求:GCC 6 以上,因为代码用到了 C99 标准的一部分特性。CentOS 7 自带的是 GCC 4.8.5,直接编译会报错,必须先把 devtoolset 升级上去。这一步很多人踩坑,我后面会专门讲。

2. 编译安装核心流程:每一步都要知道为什么

2.1 依赖准备:缺一个库都过不了

源码安装最烦的就是依赖,但也是有规律可循的。PostgreSQL 13 编译需要以下几类依赖,我按照必装和可选分开列:

必装依赖:

  • gcc、make:编译器和构建工具
  • readline-devel:命令行交互支持,没有它 psql 进去你会发现编辑功能像残废一样
  • zlib-devel:压缩支持,pg_dump 备份压缩和 WAL 日志的某些功能依赖它

可选依赖(按需安装):

  • openssl-devel:启用 SSL 连接,生产环境强烈建议装
  • libxml2-devel、libxslt-devel:XML 和 XSLT 相关功能,用不到可以不装
  • perl-devel、python3-devel:pl/perl、pl/python 存储过程支持
  • bison、flex:生成 SQL 语法分析器,PostgreSQL 14 之后才不再依赖 bison,13 必须要装

CentOS 7 上我执行的安装命令是这样的:

yum install -y gcc make readline-devel zlib-devel openssl-devel yum install -y bison flex yum install -y perl-ExtUtils-Embed python3-devel

注意一个问题:如果直接跑,bison 装出来可能是 2.7 版本,PostgreSQL 13 要求 bison 2.3 以上就够,所以这块问题不大。真正麻烦的是 GCC 太老,我单独处理:

yum install -y centos-release-scl yum install -y devtoolset-7-gcc devtoolset-7-gcc-c++ scl enable devtoolset-7 bash gcc --version

执行scl enable后当前 shell 就切到了 GCC 7,gcc --version显示 7.x 才算通过。这里有个细节:scl enable只在当前终端会话生效,如果你关掉终端再开,还得重新执行。我建议直接把编译那一步和这个命令放在同一个脚本里,避免后面忘了环境导致编译失败。

2.2 下载源码与校验:别跳过这一步

PostgreSQL 官方源码包可以从官网下载,国内也有镜像站。我下载的是 13.2 版本,文件名是postgresql-13.2.tar.gz。下载完成之后一定先做校验,这是我吃过亏才养成的习惯:有一次下载文件不完整,configure 阶段报了各种莫名其妙的错,最后才发现是包损坏。

wget https://ftp.postgresql.org/pub/source/v13.2/postgresql-13.2.tar.gz sha256sum postgresql-13.2.tar.gz

校验值去官网对照,确认一致再继续。如果你用的是公司内部源或镜像,同样要校验,只是对照的校验值来源不同。这一步花不了 30 秒,但能帮你省掉后面几个小时的排查时间。

解压并进入目录:

tar -zxvf postgresql-13.2.tar.gz cd postgresql-13.2

2.3 configure 参数详解:定制从这里开始

configure 是整个源码安装的灵魂,它的作用是检查系统环境、生成 Makefile,并把你要启用的功能标记进去。我这次用的完整参数是:

./configure \ --prefix=/usr/local/pgsql13 \ --with-openssl \ --with-perl \ --with-python \ --with-libxml \ --with-systemd

逐个解释这些参数背后的原因:

--prefix=/usr/local/pgsql13:指定安装目录。编译安装默认是/usr/local/pgsql,但我要在机器上跑两个版本,所以把版本号写进目录名做区分。目录名定下来之后,后面的 PATH、systemd 服务文件都会跟它绑定,提前想清楚很关键。

--with-openssl:启用 SSL 支持,数据库层面对外的加密连接依赖这个选项。生产环境不管现在用不用得到,建议都加上,后面想开 SSL 就不用重编译了。

--with-perl和--with-python:启用存储过程语言支持。即使暂时不用 pl/perl 和 pl/python,编译进去的成本很低,后面业务提需求时你直接能用。

--with-libxml:XML 数据处理功能,PostgreSQL 的 XML 类型和 xpath 查询依赖它。

--with-systemd:这个参数很实用,它让 PostgreSQL 原生支持 systemd 通知机制。配合 systemd 管理服务时,start/stop 状态同步会更准确,不会出现“进程其实挂了但 systemctl 还显示 active”的尴尬情况。

还有个参数需要单独说明,--with-pgport=5432。如果你默认端口就是 5432 可以不指定,但多实例场景下我习惯第二个实例用 5433,编译时就把默认端口定好,后面 initdb 和 psql 都不用每次加-p参数了。

configure 执行完后,记得看一眼输出末尾有没有configure: error之类的信息,常见的错误就是某个依赖库找不到。比如readline library not found,就是 readline-devel 没装好。这一步没报错不代表万事大吉,但它至少表明基础环境是通的。

2.4 编译与安装:耐心等待别乱来

configure 通过之后就是编译,这一步没什么技术含量,但有几个细节值得说。

make -j4

-j4表示用 4 个线程并行编译,可以显著缩短时间。线程数怎么选?我一般是看 CPU 核数,比核数少一个左右比较稳妥。比如 8 核机器用-j7,如果同时还有其他服务在跑,适度调低到-j4,避免编译把机器卡死。实测在 4 核的虚拟机里,不用-j编译 PostgreSQL 13 大概要 15 分钟,开了-j4能压到 6 分钟以内,差距非常明显。

编译过程如果中途报错,别急着重复make -j。先看报错信息,90% 的情况是两种:提示缺头文件(某个 -devel 包没装)、提示编译器版本不够(GCC 太老)。针对性地处理完,再重新编译。这里有个小技巧:make失败后的重跑,一般不需要make clean,直接再make会从断点继续。但如果 configure 之后改动过参数,才需要make distclean全部重来。

编译完成后执行安装:

make install

安装过程很快,把二进制文件拷贝到/usr/local/pgsql13/bin和共享文件到对应目录。安装完可以先看看关键的几个文件是否完整:

ls /usr/local/pgsql13/bin/

正常情况下应该能看到postgres、initdb、pg_ctl、psql这些核心工具。看到它们就说明编译安装的主流程已经走通了。这一步还有一个易忽略的辅助安装:make install默认不装一些附加模块,比如contrib目录下的扩展,如果你需要某些扩展,记得回到源码目录再用make contrib install补上。常见的高性能扩展pg_stat_statements就在 contrib 里,缺了它后面做性能诊断会很疼。

3. 初始化数据库与运行配置:装好不代表能跑

3.1 创建专用用户与数据目录

二进制装好了,但 PostgreSQL 有一个硬性安全要求:禁止用 root 用户运行数据库服务。这跟 MySQL 还不太一样,PG 的设计理念就是“数据库操作必须用独立用户”,避免权限混乱。所以第一步是创建系统用户:

useradd -m postgres

然后规划数据目录。我习惯把数据放在独立分区,这样系统盘挂了数据还在,备份和扩容也方便:

mkdir -p /var/lib/pgdata chown -R postgres:postgres /var/lib/pgdata chmod 700 /var/lib/pgdata

chmod 700很关键,PG 对数据目录权限敏感,如果目录权限是 755 或者其他用户可读的状态,initdb 会拒绝执行。这个安全机制在 MySQL 那边用--initialize-insecure可能碰不到,但 PG 是强制的,目录只能属于 postgres 用户且权限只能是 700。

3.2 initdb 初始化:字符集和区域设置

初始化数据库实例用的是initdb,这一步的任务是创建基础系统库(template1、postgres)、生成配置文件和控制文件。我用的是:

su - postgres /usr/local/pgsql13/bin/initdb -D /var/lib/pgdata \ -E UTF8 \ --locale=en_US.UTF-8 \ -U postgres \ --pwfile=/tmp/pgpass_init

逐项拆解:

-D /var/lib/pgdata:指定数据目录,必须和前面创建的目录一致,目录属主也必须是 postgres 用户。

-E UTF8:指定数据库默认字符集。国内环境基本都选 UTF8,避免中文字符乱码。这个参数写进 template1,后面建库如果不指定,默认就用 UTF8。

--locale=en_US.UTF-8:区域设置。这里有个常见的坑:如果系统没装 en_US.UTF-8 locale,initdb 会直接报错。装系统语言包可以用localedef -i en_US -f UTF-8 en_US.UTF-8解决。另外,如果你确定所有业务都是中文环境,也可以直接--locale=zh_CN.UTF-8,但要先确认系统有这个 locale。

-U postgres:指定超级用户名。默认是当前系统用户名,因为我用su - postgres执行的 initdb,默认超级用户就是 postgres,写出来更明确。

--pwfile=/tmp/pgpass_init:从文件读取超级用户密码,避免密码出现在 shell 历史里。文件内容就是一行密码文本,用完后删掉就行。注意超级用户密码迟早要设的,不在这里设,后面也要ALTER USER补上。

初始化成功后输出末尾会出现“Success. You can now start the database server”的字样,看到这句话说明基础数据库已经建好了。这时候如果不报错也别急着启动,还要改两个配置文件。

3.3 调整 postgresql.conf 与 pg_hba.conf

初始化生成的配置文件在数据目录下,两个核心文件是postgresql.conf和pg_hba.conf。先看连接相关的配置:

vi /var/lib/pgdata/postgresql.conf

需要改的参数,按重要程度排:

listen_addresses = 'localhost' # 默认就够,仅本机访问 port = 5432 # 跟上文 --with-pgport 保持一致 max_connections = 100 # 默认 100,小业务够用 shared_buffers = 1GB # 典型经验值是物理内存的 1/4 min_wal_size = 1GB max_wal_size = 4GB

shared_buffers这个参数很多人一上来就调得很大,其实是误区。它不是越大越好,因为 PG 的共享缓冲和操作系统页缓存是两套体系,设得太大反而容易造成双缓存,白白浪费内存。我的经验值:总内存 16GB 的机器设 4GB 是安全的,超过物理内存 1/3 就要小心了。云服务器如果只有 2G 内存,建议先保持默认 128MB,别折腾。

然后是pg_hba.conf,这个文件控制访问权限,默认配置非常保守,只有本地 Unix Socket 连接。如果你像我一样需要远程连接,就要加一行:

host all all 0.0.0.0/0 scram-sha-256

这里要特别提醒:0.0.0.0/0表示允许所有地址访问,如果是生产环境且没有专门的防火墙管控,这个配置极其危险。我实际部署时会先限制到业务网段,比如10.0.0.0/8,等确认没问题再放开,或者干脆只留内网连接。密码认证方式建议用scram-sha-256,不要用老的md5,13 版本已经默认支持 SCRAM 认证,安全性更高。

配置改完,记得用pg_ctl reload或重启实例让参数生效。注意:shared_buffers、max_connections这类参数改了必须重启才能生效,listen_addresses也一样。而pg_hba.conf支持热加载,pg_ctl reload就够了。

3.4 启动实例与注册 systemd 服务

第一次启动直接用pg_ctl就可以了:

/usr/local/pgsql13/bin/pg_ctl -D /var/lib/pgdata -l /var/lib/pgdata/server.log start

-l指定日志文件,这是排查问题的重要入口。启动成功后验证一下:

/usr/local/pgsql13/bin/psql -U postgres -d postgres

能正常进入 psql 交互界面,说明实例通了。不过在su - postgres环境下,psql 走的是 Unix Socket 连接,默认认证是trust(即不用密码),所以能直接进来是正常的。

要让 PostgreSQL 开机自启并纳入系统体系管理,我建议写 systemd 服务文件。虽然手动运行没问题,但服务器一旦重启,手动启动的进程不会自动恢复,这是个隐患。我的服务配置文件/etc/systemd/system/postgresql-13.service内容如下:

[Unit] Description=PostgreSQL 13 database server After=network.target [Service] Type=notify User=postgres Group=postgres ExecStart=/usr/local/pgsql13/bin/postgres -D /var/lib/pgdata ExecReload=/bin/kill -HUP $MAINPID KillMode=mixed KillSignal=SIGINT TimeoutSec=300 [Install] WantedBy=multi-user.target

关键点有两个。第一,Type=notify对应的是 configure 阶段我加的--with-systemd,postgres 启动完成会主动向 systemd 发送通知,服务状态判断更准确。第二,ExecStart直接指向 postgres 可执行文件,而不是 pg_ctl,因为 pg_ctl 的启动模式和 notify 类型在 systemd 下有兼容性问题。这个坑我一开始没注意,用 pg_ctl 写进 service,结果 systemctl status 永远显示 activating,查了半天,换成直接 exec postgres 就好了。

注册并启动:

systemctl daemon-reload systemctl enable postgresql-13 systemctl start postgresql-13 systemctl status postgresql-13

看到active (running)就干净了。这里有个验证的小习惯:systemctl status之后我还会再跑一次 psql 连接做双确认,毕竟 status 显示 active 也不能保证端口真的在听。

4. 常见问题与排查技巧实录

4.1 编译阶段的高频报错

源码安装过程中,90% 的问题集中在编译阶段。我实际遇到过的报错和解决办法整理如下:

报错:configure: error: readline library not found

这个最简单,就是 readline-devel 没装。PostgreSQL 的 psql 依赖 readline 做行编辑,没有它 configure 直接拦下。解决:

yum install -y readline-devel

然后重跑 configure。这里有个经验:报错信息明确提示了什么,就先补什么,不要盲目卸载重装,浪费时间。

报错:cc: error: unrecognized command line option -std=gnu99

这个基本就是 GCC 太老的锅。PostgreSQL 12 之前对 GCC 要求不高,13 开始要求 GCC 6+,CentOS 7 自带 4.8.5 一定会踩。要么用 devtoolset 升级 GCC,要么换个支持新 GCC 的系统,我前面已经给出了 devtoolset-7 的安装命令,不再赘述。

报错:make: bison: Command not found

bison 没装,或者装了但不在当前 PATH。检查:

which bison yum install -y bison

注意,如果你用的是 devtoolset 的 GCC,bison 一定要装在同一环境或系统全局路径下,否则编译时 PATH 混乱,一会儿能找到一会儿找不到,很难受。

4.2 初始化阶段报错

报错:initdb: error: could not create directory "/var/lib/pgdata": Permission denied

就是目录属主或权限不对。检查命令:

ls -ld /var/lib/pgdata

如果不是postgres postgres且权限 700,直接用 root 改:

chown -R postgres:postgres /var/lib/pgdata chmod 700 /var/lib/pgdata

这个报错还有一个变体:你明明用了su - postgres,但还是 Permission denied。原因多半是目录上层路径的某个中间目录,比如/var/lib的属主权限有问题,PG 对整条路径都要可进入。新用户常忽略这点。

报错:initdb: error: could not find suitable encoding "UTF8"

系统没有 UTF8 locale,或者 locale 相关的环境变量没设置。可以先跑locale -a查看可用 locale,如果没有 en_US.UTF-8:

localedef -i en_US -f UTF-8 en_US.UTF-8

设置完之后重新 initdb 即可。

4.3 连接阶段的报错

报错:psql: FATAL: role "root" does not exist

这个最经典。你在 root 用户下执行 psql,但数据库里没有 root 这个账号。解决要么用-U postgres指定超级用户,要么用su - postgres切换到 postgres 系统用户再连。我一般习惯直接psql -U postgres,这样不管是哪个系统用户执行都能连。

报错:psql: could not connect to server: No such file or directory

两个可能:一是实例没启动,二是 Socket 文件路径不对。默认 Socket 在/tmp下,如果你的临时目录被系统清理过,Socket 没了,但进程还在。这种情况用 TCP 连接试试:

psql -h 127.0.0.1 -p 5432 -U postgres

能连上就说明问题是 Socket 路径,可以改 postgresql.conf 里的unix_socket_directories来固定路径。

报错:FATAL: password authentication failed for user "postgres"

这个一般是密码错了,或者 pg_hba.conf 里的认证方式不匹配。先看 pg_hba.conf 当前生效的是哪种认证方式,再用ALTER USER postgres PASSWORD '...'重置密码。注意改了 pg_hba.conf 要pg_ctl reload才生效。

4.4 问题排查速查表

问题现象最常见原因排查命令解决思路
configure 报 readline 缺失缺 readline-develrpm -qa | grep readlineyum 安装后重跑 configure
编译报 GNU99 错误GCC 版本太老gcc --versiondevtoolset 升级 GCC
initdb 权限错误目录属主/权限不对ls -ld /var/lib/pgdatachown postgres + chmod 700
initdb 编码错误无对应 localelocale -alocaledef 生成 locale
psql 连不上实例未启动pg_ctl status / ss -lntp启动实例并检查日志
password authentication failed密码或认证方式不对cat pg_hba.conf重置密码或调整认证

排查的通用思路:先看日志,再改配置。PostgreSQL 的 server log 里几乎会记录所有的连接失败、认证失败原因,比你瞎猜快得多。日志默认输出到 stderr,用 pg_ctl 启动时-l指定的文件就是它,我记得有一次排查远程连接不上的问题,就是因为 listen_addresses 改错了没重启,日志一眼就看出来了。

最后再分享一点个人心得

这次源码安装整个过程下来,我的感受是:源码安装本身不复杂,复杂的是理解每一个参数在决定什么。如果你只是照抄命令,装完遇到问题还是会一头雾水。我建议先把 configure 参数根据自己需求想清楚,再动手编译,别为了图省事全默认,也别盲目堆参数。另外,生产环境装之前一定要先在测试机上完整跑一遍,把踩过的坑和系统版本记录下来,这样真正上线时就从容很多。如果你打算在同一台机器上再跑第二个 PG 13 实例,只需要把数据目录换一个,端口改成 5433,systemd 服务文件复制一份改改就行,二进制是可以共用一份的。这次记录算是这套系列笔记的第一篇,后面实例化、备份、性能调优的坑,我会陆续整理出来。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/19 10:48:19

Qt多级表头实现:基于QHeaderView自绘树形表头方案

简介:面向QT开发者的多级表头实现示例,直接针对QTableView默认单层表头无法展示复杂分组结构的问题。资源以完整可编译工程形式给出,核心思路是继承QHeaderView并重写paintSection、sectionSizeFromContents等方法,自行绘制各层级…

作者头像 李华
网站建设 2026/10/19 10:47:40

F²SLAM:将前馈几何紧耦合进SLAM优化器的架构设计与实践

1. 为什么把前馈几何当外挂,是SLAM系统里最别扭的设计做视觉SLAM的人大概都有过这种体验:系统里明明已经有一个能端到端输出深度和点云的3D基础模型,推理速度也不慢,但真正要把它塞进SLAM框架时,却只能把它当成一个&qu…

作者头像 李华
网站建设 2026/10/19 10:46:59

手写IoU:目标检测与语义分割中的交并比实现与避坑指南

1. IoU的第一性原理:为什么所有评测都绕不开这个比值 先说一个我在带新手时经常遇到的场面:很多人看目标检测论文,一上来就盯着mAP、mIoU这些花哨指标,结果发现代码改来改去精度就是上不去,最后排查了半天,…

作者头像 李华
网站建设 2026/10/19 10:46:21

Android扫码开发:基于Zxing源码移植实现仿微信扫码界面

简介:面向安卓开发者的二维码与条形码扫描资源,基于 Google 的 ZXing 开源库,整体交互参考微信扫码界面。资料重点解决相机预览、图像帧解码、取景框动画、闪光灯控制、相机切换和扫描结果处理等核心问题,适合有一定安卓基础、希望…

作者头像 李华
网站建设 2026/10/19 10:44:21

FC DevPod+Llama-Factory:一杯咖啡时间完成多模态LoRA微调

1. 从“微调很贵”到“咖啡还没凉就训练完了”先给你一个结论:多模态模型微调的门槛,已经从“必须租一台大机器、折腾一整天环境”降到了“开个云开发容器、拉一份框架、喂一小批图文数据,剩下时间够你冲杯咖啡再喝完”。这套组合就是 FC Dev…

作者头像 李华
网站建设 2026/10/19 10:43:56

XXL-Job适配Oracle改造指南:从建表到Mapper SQL迁移

如果你在一个数据库选型被“历史包袱”卡死的环境里做开发,对“XXL-Job 支持 Oracle 的改造过程及注意事项”这个题目一定不陌生。XXL-Job 这套分布式任务调度平台本身很好用,但官方默认只提供了 MySQL 建表脚本和一套面向 MySQL 方言的 Mapper SQL。真到…

作者头像 李华