Skip to content

源码编译安装 ​

当包管理器提供的版本不满足要求(例如需要尝鲜开发版、需要打自定义补丁、或发行版仓库太旧)时,源码编译是唯一的选择。本节讲解从源码构建 PostgreSQL 18 的完整流程:依赖准备、configure 参数、编译安装、contrib 扩展,以及它与包管理器安装的取舍。

前置知识

阅读本节前,建议先了解:Docker 安装

基础概念 ​

源码编译(Build from Source)指用 C 编译器把 PostgreSQL 的源代码编译成可执行文件,再安装到指定目录。理解几个名词:

  • 构建系统(Build System):PostgreSQL 传统上使用 GNU Autoconf 生成的 configure 脚本;PostgreSQL 16 起可选用 Meson + Ninja 构建,18 中 Meson 已经相当成熟
  • 前缀(Prefix):--prefix 指定的安装根目录,默认 /usr/local/pgsql,所有 bin / lib / share 都基于它
  • 构建依赖(Build Dependency):编译期需要、运行期不一定需要的库,如 readline、zlib
  • 可选项(Feature):通过 --with-xxx / --without-xxx 显式启用或关闭的功能模块
  • contrib:官方随源码分发的扩展合集(如 pg_stat_statements、pgcrypto、postgres_fdw),需单独编译安装
  • 编译工具链(Toolchain):gcc / clang、make、pkg-config,以及各库的开发头文件包
安装方式版本灵活性升级维护编译耗时适用场景
包管理器(apt / dnf)低,跟随仓库简单无绝大多数生产环境
官方二进制安装包中简单无不想加第三方源时
Docker 镜像中简单无开发、CI、测试
源码编译高,任意版本复杂10~30 分钟尝鲜、打补丁、裁剪、嵌入式
源码 + 打包成 RPM/DEB高可控长大规模集群统一交付

版本说明

PostgreSQL 18 起,官方同时推荐 Autoconf 与 Meson 两种构建方式。Meson 构建更快、增量编译体验更好,但仍需 Autoconf 才能生成 configure 脚本(源码发行包 postgresql-18.x.tar.bz2 已包含 configure,无需自行执行 autoconf)。

安装与配置 ​

一、准备依赖包 ​

编译 PostgreSQL 本身只需要 C 编译器和 make,但不带可选库会让功能严重残缺(例如没有 readline 就没有命令历史与补全)。推荐一次性装齐。

bash
# Debian / Ubuntu:安装编译器与各开发库(-dev 包才是头文件)
sudo apt update
sudo apt install -y build-essential make pkg-config \
  libreadline-dev zlib1g-dev libssl-dev libxml2-dev libxslt1-dev \
  libperl-dev python3-dev tcl-dev libicu-dev libldap2-dev \
  libpam0g-dev libselinux1-dev libkrb5-dev liblz4-dev libzstd-dev \
  bison flex

# RHEL / Rocky / AlmaLinux:包名通常以 -devel 结尾
sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y readline-devel zlib-devel openssl-devel libxml2-devel \
  libxslt-devel perl-devel python3-devel tcl-devel libicu-devel \
  openldap-devel pam-devel libselinux-devel krb5-devel lz4-devel libzstd-devel \
  bison flex
依赖库对应 configure 选项缺少后的后果是否推荐
readline自动探测psql 无命令历史、无 Tab 补全强烈推荐
zlib--with-zlib无法使用 gzip 压缩的备份,pg_dump -Z 失效强烈推荐
OpenSSL--with-openssl无法使用 SSL/TLS 加密连接生产必装
libxml2--with-libxml无 XML 类型与 xpath() 函数按需
libxslt--with-libxslt无 xml2 contrib 的 XSLT 能力按需
ICU--with-icu无 ICU 排序规则,多语言排序弱推荐
LZ4--with-lz4无法使用 lz4 压缩 TOAST 与 WAL推荐
Zstandard--with-zstd无法使用 zstd 压缩推荐
Perl--with-perl无法编写 PL/Perl 函数与部分构建脚本按需
Python--with-python无法编写 PL/Python 函数按需
Tcl--with-tcl无法运行部分回归测试按需
OpenLDAP--with-ldap无法用 LDAP 做认证按需
PAM--with-pam无法用 PAM 认证按需
bison / flex——源码仓库构建必需;发行包可省视情况

二、下载源码 ​

bash
# 方式 A:官方发行包(推荐,已含 configure 脚本)
cd /usr/local/src
sudo curl -LO https://ftp.postgresql.org/pub/source/v18.0/postgresql-18.0.tar.bz2
sudo curl -LO https://ftp.postgresql.org/pub/source/v18.0/postgresql-18.0.tar.bz2.sha256
# 校验完整性,避免下载被篡改或截断
sudo sha256sum -c postgresql-18.0.tar.bz2.sha256

sudo tar -xjf postgresql-18.0.tar.bz2
cd postgresql-18.0

# 方式 B:Git 仓库(仅尝鲜开发版时需要,必须自行执行 configure 生成)
# git clone --depth 1 --branch REL_18_STABLE \
#   https://git.postgresql.org/git/postgresql.git
# cd postgresql && ./configure   # 由 autoconf 生成,故需要 bison/flex

三、configure 参数详解 ​

configure 决定了编译出什么样的 PostgreSQL。核心原则:功能只加不减,路径尽量固定。

bash
# 完整示例:生产可用的编译配置
./configure \
  --prefix=/usr/local/pgsql-18 \
  --with-openssl \
  --with-zlib \
  --with-lz4 \
  --with-zstd \
  --with-icu \
  --with-libxml \
  --with-pam \
  --with-ldap \
  --with-perl \
  --with-python \
  --enable-thread-safety \
  --enable-nls \
  --enable-depend \
  --with-systemd \
  --with-extra-version=" (MyCorp Build)"
参数类型默认值说明
--prefix=DIR路径/usr/local/pgsql安装根目录;多版本并存时务必带版本号
--with-openssl开关关闭启用 SSL/TLS 加密连接
--with-zlib开关关闭支持 zlib 压缩备份
--with-lz4 / --with-zstd开关关闭支持 lz4 / zstd 压缩 WAL、TOAST
--with-icu开关关闭使用 ICU 排序规则,替代部分 OS locale 依赖
--with-libxml开关关闭提供 xml 类型与 XML 函数
--with-perl / --with-python开关关闭提供 PL/Perl、PL/Python 过程语言
--with-pam / --with-ldap / --with-kerberos开关关闭提供对应认证方式
--with-systemd开关关闭编译 systemd 服务通知支持(sd_notify)
--enable-thread-safety开关18 中默认开启客户端库线程安全;老版本需显式开启
--enable-nls开关关闭多语言错误消息,需 gettext
--enable-depend开关关闭自动跟踪头文件依赖,增量编译更准
--enable-debug开关关闭带调试符号编译,排障用,生产勿开
--enable-cassert开关关闭开启断言检查,极慢,仅开发用
--with-extra-version="TEXT"字符串空附加版本串,SELECT version() 可区分自编译版本

关于 --enable-cassert

--enable-cassert 会插入大量运行时断言,性能可下降数倍。它只在测试新功能或排查内核级 bug 时有价值,任何生产与性能测试环境都必须关闭。

configure 结束前会打印一份摘要,务必逐行确认可选功能是否真的启用:

text
PostgreSQL configuration:
  EXEC_BACKEND .................. no
  LDFLAGS ....................... -Wl,-rpath,'/usr/local/pgsql-18/lib'
  with ICU ...................... yes
  with LZ4 ...................... yes
  with OpenSSL .................. yes
  with systemd .................. yes
  with zlib ..................... yes
  ...

四、编译与安装 ​

bash
# 1. 编译。并行度建议为 CPU 核数,内存小的机器适当调低
make -j"$(nproc)"

# 2. 回归测试(可选但强烈建议,能验证编译结果是否可用)
make check

# 3. 安装到 --prefix 指定目录
sudo make install

# 4. 可选:安装文档(man 手册与 HTML 文档)
sudo make install-docs

编译产物分布如下(以 --prefix=/usr/local/pgsql-18 为例):

text
/usr/local/pgsql-18/
├── bin/          # postgres、initdb、pg_ctl、psql、pg_dump 等全部可执行文件
├── include/      # 服务端与客户端头文件
├── lib/          # libpq 及扩展 .so 动态库
├── share/        # 时区数据、扩展 SQL 脚本、示例配置
└── doc/          # 安装文档时才有

五、编译 contrib 扩展 ​

contrib 扩展不会随 make install 一起安装,需要单独进入 contrib 目录编译:

bash
cd contrib

# 查看可编译的扩展列表
ls -d */

# 全量编译安装(简单,但可能引入用不到的扩展)
make -j"$(nproc)"
sudo make install

# 只编译指定扩展(更可控,推荐)
for ext in pg_stat_statements pgcrypto postgres_fdw hstore citext; do
  make -C "$ext" -j"$(nproc)" && sudo make -C "$ext" install
done

Meson 构建(PostgreSQL 16+)

若偏好更现代的构建方式,可用 Meson 替代 configure + make:

bash
# 需要 meson >= 0.54 与 ninja
meson setup build --prefix=/usr/local/pgsql-18 \
  -Dssl=openssl -Dzlib=enabled -Dicu=enabled -Dlz4=enabled
ninja -C build
sudo ninja -C build install

详细说明 ​

可执行文件与 PATH ​

源码安装不会自动把二进制加入 PATH,也不会创建 postgres 用户与 systemd 服务。这些都要手动补上。

bash
# 全局引入可执行文件与动态库(/etc/profile.d 下的脚本对所有登录用户生效)
sudo tee /etc/profile.d/pgsql18.sh >/dev/null <<'EOF'
export PGHOME=/usr/local/pgsql-18
export PATH=$PGHOME/bin:$PATH
export LD_LIBRARY_PATH=$PGHOME/lib:$LD_LIBRARY_PATH
export MANPATH=$PGHOME/share/man:$MANPATH
EOF

# 让新配置立即在当前会话生效
source /etc/profile.d/pgsql18.sh

# 验证:应输出 /usr/local/pgsql-18/bin/psql
which psql
psql --version
text
psql (PostgreSQL) 18.0 (MyCorp Build)

创建 postgres 运行用户 ​

PostgreSQL 服务不允许以 root 身份运行,必须使用普通用户。

bash
# 创建专用系统用户与同名组,不创建家目录(数据目录另行指定)
sudo groupadd -r postgres
sudo useradd -r -g postgres -d /var/lib/pgsql -s /bin/bash postgres

# 数据目录规划:与程序目录分离,便于单独挂盘与备份
sudo mkdir -p /var/lib/pgsql/18/data /var/log/pgsql
sudo chown -R postgres:postgres /var/lib/pgsql /var/log/pgsql
sudo chmod 700 /var/lib/pgsql/18/data   # 数据目录必须仅属主可读

为 systemd 编译的额外支持 ​

--with-systemd 会让 PostgreSQL 在启动就绪后通过 sd_notify 通知 systemd,使 systemctl start 能准确判断「服务已可用」而非「进程已启动」。若不需要,可省略该参数。

bash
# 若希望使用 systemd 的 Type=notify,需确保编译时带 --with-systemd
/usr/local/pgsql-18/bin/postgres --version
# 检查二进制是否链接了 libsystemd
ldd /usr/local/pgsql-18/bin/postgres | grep -i systemd

实战示例 ​

下面是在 Ubuntu 24.04 上,从零编译一套带常用扩展的 PostgreSQL 18,并以 systemd 托管的完整流程。

bash
# ---------- 步骤 1:安装依赖 ----------
sudo apt update
sudo apt install -y build-essential pkg-config libreadline-dev zlib1g-dev \
  libssl-dev libicu-dev liblz4-dev libzstd-dev libxml2-dev

# ---------- 步骤 2:下载并校验源码 ----------
cd /usr/local/src
curl -LO https://ftp.postgresql.org/pub/source/v18.0/postgresql-18.0.tar.bz2
curl -LO https://ftp.postgresql.org/pub/source/v18.0/postgresql-18.0.tar.bz2.sha256
sha256sum -c postgresql-18.0.tar.bz2.sha256
tar -xjf postgresql-18.0.tar.bz2 && cd postgresql-18.0

# ---------- 步骤 3:配置 ----------
./configure --prefix=/usr/local/pgsql-18 \
  --with-openssl --with-zlib --with-lz4 --with-zstd --with-icu \
  --with-libxml --enable-nls --enable-depend --with-systemd

# ---------- 步骤 4:编译并安装 ----------
make -j"$(nproc)"
sudo make install
cd contrib && make -j"$(nproc)" && sudo make install && cd ..

# ---------- 步骤 5:创建用户与数据目录 ----------
sudo groupadd -r postgres || true
sudo useradd -r -g postgres -d /var/lib/pgsql -s /bin/bash postgres || true
sudo mkdir -p /var/lib/pgsql/18/data /var/log/pgsql
sudo chown -R postgres:postgres /var/lib/pgsql /var/log/pgsql
sudo chmod 700 /var/lib/pgsql/18/data

# ---------- 步骤 6:初始化数据库集群 ----------
sudo -u postgres /usr/local/pgsql-18/bin/initdb \
  -D /var/lib/pgsql/18/data -E UTF8 --locale=C.UTF-8 -U postgres

# ---------- 步骤 7:启动并验证 ----------
sudo -u postgres /usr/local/pgsql-18/bin/pg_ctl \
  -D /var/lib/pgsql/18/data \
  -l /var/log/pgsql/pg18.log start

/usr/local/pgsql-18/bin/pg_isready -h 127.0.0.1 -p 5432
/usr/local/pgsql-18/bin/psql -U postgres -c "SELECT version();"
text
127.0.0.1:5432 - accepting connections

                                                  version
-----------------------------------------------------------------------------------------------------------
 PostgreSQL 18.0 (MyCorp Build) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0, 64-bit
(1 row)
ini
# /etc/systemd/system/postgresql-18.service
# 由源码编译安装时,官方不会提供 unit 文件,需要自行编写
[Unit]
Description=PostgreSQL 18 database server (source build)
Documentation=https://www.postgresql.org/docs/18/
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
User=postgres
Group=postgres
# 数据目录通过 -D 传给 postgres 进程
Environment=PGDATA=/var/lib/pgsql/18/data
ExecStart=/usr/local/pgsql-18/bin/postgres -D ${PGDATA}
ExecReload=/bin/kill -HUP $MAINPID
# 优雅停止:SIGINT 等价于 pg_ctl stop -m fast
KillMode=mixed
KillSignal=SIGINT
TimeoutSec=300
# 数据目录不存在时由 systemd 自动创建
RuntimeDirectory=postgresql
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
bash
# 重新加载 unit、设为开机自启并启动
sudo systemctl daemon-reload
sudo systemctl enable --now postgresql-18
systemctl status postgresql-18 --no-pager

升级与卸载 ​

bash
# 同一大版本内升级(例如 18.0 → 18.1):重新编译后 make install 即可
cd /usr/local/src/postgresql-18.1
./configure --prefix=/usr/local/pgsql-18 [原有参数...]
make -j"$(nproc)" && sudo make install
sudo systemctl restart postgresql-18
# 注意:小节升级不需要 pg_upgrade,数据目录兼容

# 卸载:源码安装没有卸载脚本,只能手工删除
sudo systemctl stop postgresql-18
sudo rm -rf /usr/local/pgsql-18          # 程序目录
sudo rm -f /etc/profile.d/pgsql18.sh     # 环境变量
sudo rm -f /etc/systemd/system/postgresql-18.service
sudo systemctl daemon-reload
# 数据目录请自行确认后再删:sudo rm -rf /var/lib/pgsql

注意事项 ​

  • 源码安装没有任何包管理器依赖记录,将来无法用 apt remove 卸载,必须有清晰的安装清单文档
  • --prefix 强烈建议带大版本号(pgsql-18),否则将来装 19 会直接覆盖 18 的二进制,造成不可逆混乱
  • 服务进程不能以 root 运行;用 sudo make install 安装程序,但务必用 sudo -u postgres 运行 initdb 与 postgres
  • 数据目录权限必须是 700 且属主为运行用户,否则 initdb 与启动都会直接拒绝
  • 编译缺库不会报错中断,只是静默关闭该功能;务必回看 configure 摘要,否则可能上线后才发现没有 SSL
  • make check 需要能在非 root 用户下运行,且不能在 root 身份下跑;它消耗几分钟但能提前发现工具链问题
  • 大版本升级(18 → 19)不能直接沿用数据目录,必须使用 pg_upgrade 或逻辑导出导入
  • 修改 ./configure 参数后应执行 make clean 或直接解压全新源码树,避免旧对象文件混入导致怪异行为
  • 生产环境不要开启 --enable-cassert,也不建议开启 --enable-debug
  • 从 Git 仓库构建需要 bison、flex,且必须先运行 ./configure 生成构建脚本
  • 缺少 LD_LIBRARY_PATH 或 rpath 配置时,libpq 可能链接到系统里的旧版本,出现难以排查的版本错乱

最佳实践 ​

  • 优先选择包管理器安装;只有确实需要特定版本、自定义补丁或特殊裁剪时才走源码编译
  • 把整套编译命令写成可执行的构建脚本并纳入版本控制,保证任意机器可复现同一份二进制
  • 固定依赖库版本,并在 --with-extra-version 中写入公司/环境标识,方便 SELECT version() 溯源
  • 大规模集群建议「编译一次,打成 RPM/DEB 包」,再用包管理器分发,兼顾可控性与可维护性
  • 程序目录与数据目录彻底分离:数据目录放在独立数据盘,便于扩容、快照与备份
  • 使用 --with-icu 而非依赖 OS locale,减少容器/主机环境差异导致的排序规则不一致
  • 启用 --with-systemd 并配置 Type=notify,让 systemd 正确感知服务就绪状态
  • 编译后立即执行 make check,并把 configure 摘要与构建日志归档保存
  • 用 ldd 检查关键二进制(postgres、psql)的动态库来源,确认没有误链系统旧版 libpq
  • 升级策略固定为「同一大版本内重新编译覆盖,大版本变更走 pg_upgrade」,并提前演练

下一节

继续学习:初始化数据库集群(initdb)

参考链接 ​