PostgreSQL 13源码安装部署实战:从编译到调优全指南

发布时间:2026/10/19 17:46:52
PostgreSQL 13源码安装部署实战:从编译到调优全指南 1. 环境准备与依赖安装1.1 为什么要用源码安装这两年接触到不少生产环境的部署需求很多团队在选型时直接拎一个二进制包或系统包管理器装完就跑确实省事但到了真正需要调优、加插件、定制特性的时候就有种被卡住脖子的感觉了。PostgreSQL 13 源码安装这条路看着多花了两三个小时实际上是把后续的主动权攥在自己手里比如编译期就启用--with-icu支持国际化的排序规则、--with-llvm开启 JIT 加速能力或者把默认的页面大小、块大小按业务存储特性重新编一遍这种深度定制的空间包管理器很难给你。我的建议是如果你的服务器要做到线上支撑、长期演进哪怕是一次性的内部系统也值得走上源码编译这条路。这不是为了显得“专业”而是源码方式能让你对整个软件的构成和依赖关系有更清晰的掌握出去排查问题时心里更有底。而且 PostgreSQL 13 作为当时比较新的版本线官方文档也建议源码方式用于具备一定维护能力的团队社区里大量高可用方案和扩展插件也需要对应版本头文件和编译接口。1.2 操作系统层面需要摸清的底细我在实际操作中主要用的发行版是 CentOS 7.x 和 Rocky Linux 8.x这两个系统在编译 PostgreSQL 13 时思路大体一致但依赖包的命名和版本略有差异。建议拿到新机器后先确认三件事操作系统版本、CPU 架构、可用内存因为这三项直接决定你要装哪些依赖包以及后面的编译参数怎么选。cat /etc/redhat-release uname -m free -hPostgreSQL 13 源码编译对系统的要求其实不苛刻内存 2GB 以上就足够完成make全量构建但如果要并行编译-j参数建议 4GB 以上更稳。磁盘方面源码包加编译产物大约需要 2GB 左右临时空间别把临时目录塞得太满。需要额外提醒的是PostgreSQL 源码编译会用到 GNU make并且明确要求gmake而不是系统里可能默认存在的 BSD make。CentOS/RHEL 系列默认安装的是 GNU make直接执行make没问题但如果你在一台有一定历史的系统上操作建议先用make --version确认一下避免后续出现诡异报错。1.3 依赖包清单与安装过程这是最容易卡壳的第一关很多编译中途失败都是因为缺了某个开发库。PostgreSQL 13 编译的基础依赖包括编译器、系统工具、开发头文件、以及几个可选特性的支持库。yum install -y gcc gcc-c make readline-devel zlib-develreadline-devel 和 zlib-devel 基本上可以说是编译 PostgreSQL 的刚需readline 是为了命令行历史记录和编辑功能zlib 则是数据压缩能力的基础比如 pg_dump 的压缩导出就依赖它。如果你需要更完整的扩展能力还有几个包建议一起装上它们的名字容易漏yum install -y libxml2-devel libxslt-devel openssl-devellibxml2-devel和libxslt-devel提供 XML 处理能力配套pgxmlerrors等模块要用openssl-devel是为了 SSL 加密连接的支持。现在信息安全要求越来越高数据库链接不加密基本是过不了评审的所以 SSL 支持我建议默认就带上不要等后面被安全扫描出问题再加。另外有些场景需要依赖 ICU 库来实现更完整的 Unicode 排序规则支持yum install -y icu libicu-develICU 这个库在 PostgreSQL 12 之后已经被官方支持用作默认的排序规则库如果你的业务需要处理多语言排序、Emoji 这类特殊字符--with-icu非常值得打开。我见过不少人在这一步图省事只装了前三个基础包后面编译到contrib模块时才冒出来一堆报错来回折腾半天。多花两分钟把依赖一次装齐是过来人的经验。2. 源码获取与编译参数设计2.1 下载源码包与完整性校验下载源码时我建议不要直接用浏览器保存而是用 wget 拉取这样可以通过 md5 或 sha256 做一遍完整性校验。PostgreSQL 官方会把源码包和对应的校验值文件放在同一个目录下稳妥的做法是把包和校验文件都拉下来一起比对。wget https://ftp.postgresql.org/pub/source/v13.3/postgresql-13.3.tar.gz wget https://ftp.postgresql.org/pub/source/v13.3/postgresql-13.3.tar.gz.md5 md5sum -c postgresql-13.3.tar.gz.md5为什么选 13.3 而不是修改基调比较大的 13.0其实到了 13.x 系列小版本主要是修复 bug 和安全性漏洞直接用稳定版是最省心的。这里插一句官网的下载目录并没有固定版本会持续更新所以下载前先去官网确认一下最新的小版本号。我把源码包放在/usr/local/src目录这个目录专门存放需要自己编译的第三方源码方便日后追溯版本和补丁。如果你的团队有统一的软件发布目录按团队规范走即可。2.2 configure 参数设计的实际考量解开源码包后就进入配置环节了tar -zxvf postgresql-13.3.tar.gz cd postgresql-13.3这个步骤核心是./configure它决定 PostgreSQL 将要被编译成什么样也直接影响后期能力边界。我常用的配置参数如下./configure --prefix/usr/local/pgsql \ --with-pgport5432 \ --with-openssl \ --with-icu \ --with-libxml \ --with-libxslt \ --with-readline \ --with-zlib \ --enable-thread-safety每个参数背后都有对应的实际需求--prefix指定安装根目录。这里选/usr/local/pgsql是社区很常见的路径简单且不易与其他软件冲突--with-pgport设置默认监听端口不设置的话默认就是 5432。写在这里的好处是后续启动、连接都不用额外指端口--with-openssl开启 SSL编译出支持加密连接的服务端和客户端--with-icu启用国际语言排序规则库--with-libxml和--with-libxsltXML/XLST 处理支持配套 contrib 模块会用到比如 PostgreSQL 的 XML 函数--enable-thread-safety让 libpq 在多线程客户端程序里更安全并发连接场景这个挺重要。其实官方默认是线程安全的但手动写出来更明确也方便后来维护的人看到预期行为。假如你确认某些功能不需要可以去掉对应参数来减小体积和依赖但我的原则是多带不用而不是需要时找不到。2.3 make 编译扛坑指南配置成功后会提示你继续运行make这一步在旧机器上可能需要十几分钟可以用并行参数加速make -j 4-j 4表示四个编译任务并行具体数字建议和 CPU 核心数保持一致或略少于核心数。别贪心把-j开到 16 或者更大内存不够的情况下反而会拖慢编译甚至出现编译器进程被杀掉的情况。如果中途出现报错会提示具体的源文件和错误原因这时候先别慌多数情况是缺头文件或者版本不匹配带着报错去搜索引擎查会非常快。编译无误后执行安装make install这一步会把可执行文件、库文件、头文件、文档等内容依次复制到--prefix指定的目录下。安装完成后再编译安装 contrib 扩展模块cd contrib make -j 4 make install这里必须提醒contrib 不是可选项级别的东西既有pg_stat_statements性能诊断神器、pageinspect数据页内窥镜这种分析工具也有postgres_fdw外部数据源连接、dblink这类跨库操作模块。默认 PostgreSQL 核心功能是克制的大量实用能力都跑到 contrib 里去了所以编译完主体后一定顺手把 contrib 也装上。3. 数据库初始化与服务配置3.1 创建专用用户与目录规划编译完成只是第一步接下来要解决“以什么身份、在哪片地盘上运行数据库”这个问题。我强烈建议创建一个操作系统级别的专用账号来跑 PostgreSQL不允许它做普通用户该干的其他事情这样即使数据库层面被攻破攻击者能拿到的也只是受限的系统权限。useradd postgres mkdir -p /data/pgdata chown -R postgres:postgres /data/pgdata数据目录放在/data/pgdata是从经验里得出的选择。早期我图省事把数据目录建在/home/postgres下结果有一次/home分区写满整个数据库服务直接挂掉。把数据目录独立放在/data下既减少与系统盘的空间争抢也在备份时容易通过挂载点做快照或者直接打包。3.2 初始化数据库实例用 postgres 用户来执行数据库初始化su - postgres /usr/local/pgsql/bin/initdb -D /data/pgdata -U postgres --encodingUTF8 --localeC.UTF-8-D指定数据目录-U postgres指定超级用户名--encoding设置字符集为 UTF8这个几乎必须国际化系统都离不开它。--localeC.UTF-8值得讲一下locale 会影响数据排序、字符串比较的行为。在生产环境选 locale 要谨慎因为改 locale 基本意味着需要pg_dump重放数据代价极大。C.UTF-8 的好处是排序规则相对干净、可预测性强也能覆盖大多数字符集C 系列的选择对性能也相对友好。如果你想完全跟随系统默认区域设置直接省略这个参数即可但跨环境迁移时可能会出现排序不一致的坑所以我的习惯是显式指定。3.3 关键参数初调postgresql.conf 不要全默认初始化完成后先不要急着启动把postgresql.conf里几个核心参数过一遍listen_addresses * port 5432 max_connections 200 shared_buffers 1GBlisten_addresses默认只监听本机改成*才允许外部连接但生产环境更稳妥的做法是改成实际业务网卡 IP 而不是全世界max_connections默认 100在一般互联网场景够用但并发较高的业务 200 是常见起步值。注意这个值和下面共享内存参数是联动的共享内存太小而连接数很大可能启动都会成问题shared_buffersPostgreSQL 自己管理的共享内存池一般建议设为物理内存的四分之一。这是一个经验值不是数学最优解比如内存 16GB 的机器给 4GB 就比较合理。设置过大反而可能因为系统页缓存管理方式的差异性能反而下降。修改配置后先校验一下是否正常:/usr/local/pgsql/bin/pg_ctl -D /data/pgdata -l /data/pgdata/logfile start-l指定日志文件路径启动过程中出现的任何错误都会记录在里面。如果成功启动会提示server started此时可以用psql快速验证/usr/local/pgsql/bin/psql -U postgres -p 5432 -c select version();看到 PostgreSQL 13.x 的版本信息就说明这一步已经扎实了。3.4 注册成系统服务手动启动只能管当前会话重启机器后 PostgreSQL 不会自己起来这不符合生产要求。注册成 systemd 服务才是正途。我习惯创建/etc/systemd/system/postgresql-13.service内容如下[Unit] DescriptionPostgreSQL 13 database server Afternetwork.target [Service] Typesimple Userpostgres Grouppostgres ExecStart/usr/local/pgsql/bin/postgres -D /data/pgdata ExecReload/usr/local/pgsql/bin/pg_ctl -D /data/pgdata reload TimeoutSec600 [Install] WantedBymulti-user.target解释一下这里为什么不调用pg_ctl启动而是直接跑 postgres 二进制systemd 内直接用主进程管理日志统一交给 journald 收集方便集中管理和排查问题状态管理也更干净。Typesimple表示系统把 ExecStart 拉起的进程视作主进程这正是我们想要的。配置好以后systemctl daemon-reload systemctl enable postgresql-13 systemctl start postgresql-13若在启动或 enable 过程中报错大概率是目录权限或配置文件里的路径不对按提示检查即可。4. 常见问题与排查技巧实录4.1 编译阶段的高频报错对照表我在指导同事部署和社区答疑时经常见到下面这几类问题报错表现根本原因解决方式readline/readline.h: No such file or directory缺少 readline-devel安装 readline-devel 后再执行 configurezlib.h: No such file or directory缺少 zlib-devel安装 zlib-develcould not find a usable perl缺少 Perl 或版本不兼容安装 perl 和 perl-devel并确认 PATHconfigure: error: ICU library not found缺少 ICU 或版本过旧安装 libicu-devel并确保版本不低于 4.2make: *** No rule to make target源码目录不完整或架构不匹配重新解压完整源码包确认 CMAKE/目录结构没有残留一个非常容易忽视的问题老系统上的 Perl 版本可能是 5.10 甚至更低PostgreSQL 13 对 Perl 最低要求是 5.8.1理论上够但配套模块可能需要更新一点的版本。如果碰到莫名其妙的符号错误优先升级 Perl 到 5.16 以上再重新编译。另外提一句编译前的“洁癖行动”如果之前有编译失败的半成品源码目录务必make distclean清理后再重新 configure不清理干净反而会因为旧的编译缓存造成稀奇古怪的错误。4.2 初始化失败的一个罕见但高发的坑执行 initdb 时有一类报错几乎每个群友都问过initdb: error: invalid locale settings; check LANG and LC_* environment variables其实 initdb 默认继承你当前 shell 的区域设置如果这些环境变量乱掉甚至没有一个明确可用的 locale就会直接罢工。最简单可靠的解决方案是在 initdb 时显式传入 localeexport LANGC.UTF-8 /usr/local/pgsql/bin/initdb -D /data/pgdata -U postgres --encodingUTF8 --localeC.UTF-8还有一种情况系统本来就缺少C.UTF-8这个 localeCentOS 7 上如果没安装过glibc-all-langpacks就可能出现找不到的情况。检查一下locale -a | grep C.UTF-8没有的话临时方案是退回去用--localeC或系统已有的 en_US.UTF-8但要清楚排序行为会和 C.UTF-8 有细微区别。这一点上千万不能随便妥协数据库的排序规则一经初始化就很难改。4.3 启动失败与日志定位技巧源码安装的服务和包管理器装的服务在日志路径上有很大差异很多人用惯了系统包的日志路径转到源码安装就不知所措。源码安装方式下没有意外的话日志就是你自己指定的-l路径或者 journald。我在生产环境长期使用 journald 来管理日志比如用journalctl -u postgresql-13查看服务日志查询启动失败原因时的效率和体验比翻文件好很多。不过注意如果你在环境变量或 service 文件中自己指定了 logging collector那么日志默认行为会和 journald 有冲突两处都写可能造成重复记录。建议源码安装时保持简单直接让 postgres 进程把 stderr/stdout 交给 systemd依赖 journald 收集。一个常见启动失败案例是端口被占用ss -tlnp | grep 5432查出占用进程后要么停掉它要么改配置换端口。另一个常见案例是数据目录权限问题启动用户不是 postgres系统直接拒绝打开目录。这个排查起来很快ls -ld /data/pgdata chown -R postgres:postgres /data/pgdata如果报错信息是could not create lock file类型的优先检查/tmp目录的权限和磁盘空间PostgreSQL 运行时会在这里创建共享内存锁文件和 Unix socket 文件。4.4 pg_stat_statements 等你需要的 contrib 插件所有扩展插件都必须先执行对应的 SQL 安装脚本才能生效否则它只是躺在磁盘上的一个编译好的库文件不会被数据库加载进内存。比如性能调优神器pg_stat_statementsCREATE EXTENSION pg_stat_statements;这条语句执行完成后还需要把pg_stat_statements加进shared_preload_libraries参数并重启数据库否则无法记录查询统计信息。早期版本中这里有一个很隐蔽的坑如果你只执行了CREATE EXTENSION却忘了修改 shared_preload_libraries重启后这个插件并不会自动加载查询视图时还会报错。另外一个我极力推荐安装的 contrib 模块是pg_repack当然它是独立于官方 contrib 的第三方工具但对付表膨胀问题非常出色。数据库运行久了频繁 UPDATE/DELETE 的表会膨胀传统VACUUM FULL会锁表阻塞业务而pg_repack可以在不长时间锁表的情况下完成重整。这个工具虽然不属于 PostgreSQL 13 源码包但要配合对应版本的编译环境使用这就要求你在源码编译时保留好pg_config和头文件否则编译第三方插件时会各种缺东西。这也是我前面强调源码安装方式保留主动权的主要原因。5. 性能验证与后续调优建议5.1 首次启动后的健康检查清单完成服务注册和启动后用下列一组命令做健康检查确认这台数据库能支撑实际业务/usr/local/pgsql/bin/pg_isready -h 127.0.0.1 -p 5432 /usr/local/pgsql/bin/psql -U postgres -h 127.0.0.1 -p 5432 -c show server_version; /usr/local/pgsql/bin/psql -U postgres -h 127.0.0.1 -p 5432 -c select name, setting from pg_settings where name in (shared_buffers,max_connections,listen_addresses);pg_isready输出accepting connections说明服务正常监听。之后再用pg_settings视图核对关键参数生效值防止配置文件写错但进程没读到的假象。完成以上基础检查后可以顺手创建一个简单的压测库比如用pgbench初始化并做一轮基本测试/usr/local/pgsql/bin/createdb -U postgres bench /usr/local/pgsql/bin/pgbench -U postgres -i bench /usr/local/pgsql/bin/pgbench -U postgres -c 10 -j 2 -T 60 bench-c 10是并发客户端数量-j 2是线程数-T 60表示测试持续 60 秒。跑完后观察 TPS每秒事务数和延迟分布如果 TPS 明显偏低先检查shared_buffers和数据目录所在磁盘类型如果是机械盘顺序写性能会成为瓶颈只能靠调大wal_buffers、checkpoint_timeout这类参数缓解但仍需尽早规划换 SSD。5.2 wal 参数与检查点行为的实用建议PostgreSQL 默认wal_level是 replica一般业务其实不用动需要开启流复制时主库把wal_level改为 logical 可以支持逻辑复制但代价是 WAL 日志内容变多因此非必要不开启。我特别想强调的是checkpoint_timeout和max_wal_size这两个参数checkpoint_timeout 15min max_wal_size 4GB min_wal_size 1GB很多新手以为 checkpoint 越频繁越安全其实 checkpoint 本质是把脏页写回磁盘做一次全量落盘的成本是不低的。频繁的 checkpoint 会让磁盘 I/O 出现周期性峰值用户感知是“时不时的卡顿一下”。把间隔拉长到 15 到 30 分钟配合足够大的 WAL 容量日志落盘的顺序写和刷盘的大块写可以错峰整体体验更平滑。这里补充一个老鸟才注意到的细节设置max_wal_size后不要把它理解为硬上限。在实际运行中PostgreSQL 会在 checkpoint 间隔期间动态估计合适的 WAL 总量因此实际使用量可能略高于设置的max_wal_size。提前知道这个行为查询监控面板时就不会被瞬时超出值吓到。5.3 内存和存储选型要一起规划shared_buffers设为内存的四分之一再往上提其实收益不大因为 PostgreSQL 还有操作系统页缓存这一层。更大内存时effective_cache_size这个计划器参数的作用就出来了它告诉优化器系统剩余可用缓存大概有多大影响优化器选索引扫描还是顺序扫描。一般建议设为物理内存的一半到 75%比如 32GB 物理内存的机器可以设成 16GB 到 24GB 之间effective_cache_size 20GB存储方面数据目录所在位置对整体体验影响极大。同样一套默认配置放机械盘和 NVMe 盘上TPS 可能就是两倍以上差距。从架构上考虑如果条件允许WAL 日志单独放到一块独立 SSD 或高性能盘上能在高并发写入时有质的改观。不过这是讲硬件规划的范畴对于单纯做源码安装部署来说先确保数据目录在可靠、独立的分区上即可。6. 几条基于实战的补充体会最后聊几句这次源码安装过程中的个人感受不一定全在官方文档里写得明明白白但实际踩过之后特别想让后来的朋友少走弯路。第一postgres 操作系统的用户密码我建议直接把登录 shell 设为/sbin/nologin也就是禁用该用户直接登录。所有操作通过su或密钥跳转去执行即可这能减少黑客在拿到 postgres 用户后扩充权限的可能。有些教程为了省事直接设置成可登录生产环境很不推荐。第二源码编译完成后/usr/local/pgsql/bin这个路径要加入系统的 PATH 环境中或者直接在各个调用位置写全路径。很多人喜欢创建软链到/usr/local/bin下但如果后续升级版本软链要记得同步更新不然后患不少。我更喜欢在/etc/profile.d/pgsql.sh中写入export PATH/usr/local/pgsql/bin:$PATH这样每次登录 shell 都有可用的 psql、pg_dump 等工具不用到处补路径。第三要保持一个习惯每次改完postgresql.conf在重启前用pg_ctl reload做一次热加载测试。有些参数支持 reload比如大多数内存和日志类参数有些则需要重启比如 shared_preload_libraries提前用pg_settings上下文判断一下能省去不必要的业务中断时间。判断参数是否需要重启的方法是SELECT name, context FROM pg_settings WHERE name shared_preload_libraries;如果 context 显示为postmaster那么这个参数必须重启数据库才能生效。PostgreSQL 13 的源码安装过程本质上并不复杂但它是一个需要耐心的系统工程从依赖准备、编译参数、初始化配置到系统服务每个环节都环环相扣。只要按部就班地把环境梳理清楚后续的维护和扩展会非常顺手。希望这篇笔记能帮你在部署 PostgreSQL 时少踩几个坑尤其是那些看起来不起眼却能卡住你半天的细节。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询