首页 / 资讯中心 / 文章详情

PostgreSQL 13源码编译安装实战:从configure到systemd全流程

PostgreSQL 13源码编译安装实战:从configure到systemd全流程 ★ FEATURED ARTICLE
PostgreSQL 13发布那阵子我正准备给某个内部数据平台换数据库底座。当时手里同时跑着好几个业务库既有老的9.6也有别人装好的10版本杂、管理乱加上刚好需要一台独立实例承接新的报表任务我就决定用源码方式重新部署一套。选择2021年3月这个时间点是因为当时13.2已经发布修复了不少前几个补丁版本的问题稳定性更适合直接进生产。这篇不是官方文档的复述而是把我从解压源码包到最终跑通业务的完整过程记录下来每一步为什么这么干、哪些坑我踩过、哪些参数值得你多看一眼。适合正在给团队搭测试环境、或者第一次从二进制包转向源码编译的运维和DBA阅读。1. 为什么在生产环境我仍坚持源码安装选型背后的考量1.1 二进制包真的不够用吗很多人会问明明yum install或者apt install一行搞定为什么非要从源码编译我的理由并不复杂主要集中在以下三点。第一可控性。发行版仓库里的PostgreSQL版本总是落后几个小版本并且某些Linux发行版的软件源还会打上自己的补丁行为表现会和官方发现场编译的存在细微差异。比如我之前遇到过系统自带版本默认禁用了某一类索引特性查了半天才发现是发行版编译参数跟我们业务预期不一致。源码安装则能让我明确知道当前实例的configure选项、编译器和补丁状态。第二多版本共存。测试环境经常需要同时在多个大版本之间比对行为差异比如验证从9.6迁移到13后执行计划的变化。发行版的二进制包通常会固定安装到一个系统路径很难做到同一台机器上多个大版本互不干扰。源码编译把每个版本装进独立的前缀目录切换使用环境只需调整PATH参数干净利落。第三排查问题的便利性。源码编译保留了完整的中间文件和符号信息一旦碰到疑似数据库本身的问题可以带调试符号重新编译甚至直接附加调试器查看内部状态。生产环境我一般不需要这么做但排查问题时这种能力确实可以成为关键时刻的救命稻草。当然源码安装也有代价编译时间、依赖准备、升级时需要重复操作这些都必须提前想清楚。我的经验是做增量部署时优先考虑源码但不排斥在生产环境使用官方提供的二进制包具体场景要具体分析。1.2 版本节奏与补丁时机的把控选择13这个版本而不是当时的14或者更旧的版本我是有明确理由的。2021年3月这个时间点PostgreSQL 14还在开发期13系列已经经历13.0和13.1两个版本13.2算是功能稳定、修复充分的成熟版本。我不建议在刚发布的大版本上直接跑核心业务通常等三四个月让社区把早期暴露的稳定性问题处理得差不多再考虑升级。源码安装还有一个额外好处日后补丁升级只需在旧源码目录基础上增量编译不需要重做initdb。比如从13.1升到13.2我的流程是先下载新源码包编译安装到同一前缀目录然后重启实例即可。数据目录不用动配置文件不用改整个升级窗口可以压缩到分钟级。这个特性在应急修复安全漏洞时非常有用。2. 编译前的基础准备依赖、用户与目录布局2.1 依赖安装阶段的常见遗漏源码编译依赖GCC、make、readline和zlib相关的开发包。不同发行版包名不完全相同我当时的环境是CentOS 7.8安装命令是yum install -y gcc gcc-c make readline-devel zlib-devel flex bison这里最容易漏掉的是flex和bison。前者在configure检查阶段不一定报错但编译到语法分析部分时会突然中断后者版本如果太旧可能无法正确处理新的语法文件。我的建议是顺手都装上别省这些功夫。另外如果你的环境需要SSL支持务必提前安装openssl-devel并在configure时加上--with-openssl参数。需要Python或Perl过程语言支持的还要提前装好对应的开发头文件。依赖装不全最麻烦的问题是排查过程曲折报错信息又不直观折腾一圈回头发现只是少了一个基础包。2.2 用户创建与目录规划生产环境操作数据库绝不建议用root直接跑。我习惯为每个独立的PG实例创建一个专用系统用户既便于权限隔离也方便通过systemd统一管理。当时我执行的命令是groupadd postgres useradd -g postgres -s /bin/bash postgres密码不需要设置默认也无法登录系统但后续所有数据库操作都在这个用户下执行。这里有个经验把用户shell指定为/bin/bash而不是/sbin/nologin可以在排查问题时方便地切换身份跑命令如果不放心安全边界生产环境可以改回nologin。目录规划方面我强烈建议把软件目录和数据目录彻底分开。软件目录通常放在/usr/local/pgsql13这种带版本号的位置数据目录则放在独立的数据盘挂载点上比如/data/pgsql13。这样升级软件时数据目录完全不受影响磁盘空间不足时也可以单独扩容数据目录而不用动软件。我实际的布局是这样mkdir -p /data/pgsql13/data mkdir -p /data/pgsql13/logs chown -R postgres:postgres /data/pgsql13日志单独放一个目录也很关键。因为PostgreSQL运行日志如果不加管理会无限增长导致磁盘写满。独立的日志目录方便接入日志轮转工具也方便日常巡检。2.3 configure前的编译选项取舍进入源码包目录后的第一步是configure这里的选择直接影响数据库编译出来的能力和性能。我当时用的完整命令是./configure --prefix/usr/local/pgsql13 --with-openssl --with-perl --with-python --with-pam --with-libxml --with-libxslt--prefix指定安装路径这是多版本共存的关键。--with-openssl启用SSL加密连接当前业务要求所有链路加密必须加。--with-perl和--with-python是为了后续可能用到PL/Perl和PL/Python写存储过程暂时用不到也可以先编译进去省得日后重新编译。有个参数需要特别提醒--with-pam。如果你需要通过操作系统账号来认证数据库用户这个选项就非常重要但启用后需要保证PAM配置文件正确。我当时因为没有这个需求所以没加如果你有LDAP或操作系统集成认证需求需要在configure阶段就计划好否则后续追加比较麻烦。另一个容易忽略的点是优化级别。默认configure会使用-O2优化对于生产环境是合理的选择。如果你需要更强的调试能力可以加--enable-debug但同时会牺牲部分性能。不建议在普通生产环境启用debug。3. configure / make / make install 逐步走完3.1 完整编译过程与耗时观察configure脚本跑完后输出信息里会有一段总结告诉你启用了哪些特性、禁用了哪些特性。我建议认真看一下这段总结确认需要的功能全部出现而不是直接滚屏跳过。接下来执行编译make -j 8-j参数指定并行编译作业数通常按CPU物理核心数或逻辑核心数的一半设置比较稳妥。我当时的机器是8核用-j8编译大约花了十二分钟。如果你用的是2核小机器就不要贪心直接make就好并行参数设置过高会导致系统卡顿甚至内存不足。编译是一个比较漫长的过程期间终端会滚动大量输出。我的建议是不要干等可以把编译日志重定向到文件比如make -j8 /tmp/make.log 21这样既能保留信息又避免终端内容刷屏。编译中断时查看日志末尾几百行往往就能定位到问题。3.2 安装阶段与目录结构验证编译完成后执行make install这一步相对快主要把可执行文件、库文件、头文件和支持文件复制到prefix目录。安装结束后建议验证一下目录结构ls -l /usr/local/pgsql13/binbin目录下应该有postgres、psql、pg_ctl、initdb、pg_dump等一组可执行文件。如果缺少某工具多半是configure阶段关了相关选项。比如pg_dump和pg_restore是与安装包一起编译的正常情况不会缺失。还有一步容易被忽略安装附加模块。PostgreSQL源码包contrib目录下有大量实用扩展比如pg_stat_statements这是性能监控的神器。需要这些扩展时不能只make install还要额外编译contrib部分cd contrib make -j 8 make install我建议即使是初始安装也把contrib编译安装上因为pg_stat_statements这类功能往往等业务上线后发现需要时才开始配置届时还得重新编译或改配置重启不如一次性备好。4. initdb初始化与配置文件的三个核心改动4.1 initdb参数逐一拆解环境变量和PATH配置好之后用postgres用户执行initdbsu - postgres export PATH/usr/local/pgsql13/bin:$PATH initdb -D /data/pgsql13/data -U postgres -E UTF8 --localeen_US.UTF-8 --authscram-sha-256-D指定数据目录-U指定超级用户名称我沿用默认的postgres。-E UTF8指定数据库集群默认字符集只要不是特殊业务要求UTF8就是最稳妥的选择。--locale指定区域设置这个参数其实需要仔细掂量。如果你的操作系统环境locale是en_US.UTF-8那么数据库也用它最省心。只有在需要中文排序规则等特殊场景下才考虑用zh_CN类的locale。locale选择在initdb之后就不能随意更改所以这一步要想清楚再执行。--authscram-sha-256设置了初始认证方式。默认情况下PostgreSQL使用trust认证也就是本地连接不需要密码这在自己开发机没什么问题但放到生产环境无论如何都说不过去。scram-sha-256是目前最安全的密码认证方式建议从一开始就习惯它。4.2 postgresql.conf改动点初始化完成后需要登录服务器修改postgresql.conf。我需要改的主要是以下几项listen_addresses localhost port 5432 max_connections 200 shared_buffers 1GBlisten_addresses默认只监听localhost意味着只能本机连接。如果业务需要远程访问这里要改成应用服务器的IP或网段。安全起见不要直接设置为*尽量缩小监听范围。shared_buffers是PostgreSQL最重要的内存参数之一决定共享缓冲区大小。经验上说设置为系统物理内存的25%左右是起步推荐需要结合total memory和实际负载综合评估。我那个测试机是8GB内存设置为2GB如果内存紧张1GB也够基础业务使用。max_connections同样需要预估业务规模。默认100有时不够用但也不要盲目调大因为每个连接都会占用一定内存设置过大可能导致内存超分配。Pool层有连接池的话数据库端连接数可以适当压缩。wal_level建议设置为replica这是开启流复制的基础配置即使当前是单机也应该提前预留这个可能性。fsync默认开启不必动它。4.3 环境变量与PATH配置为了让日常维护命令更顺手我习惯在postgres用户的bash配置文件里写入以下内容export PATH/usr/local/pgsql13/bin:$PATH export LD_LIBRARY_PATH/usr/local/pgsql13/lib:$LD_LIBRARY_PATH export PGDATA/data/pgsql13/dataPATH解决了命令找不到的问题。LD_LIBRARY_PATH很多人会漏掉如果不设置psql等客户端工具运行时可能因找不到libpq.so.5而报错。PGDATA可以减少手动输入-D参数的频率。这三行配置写好后后续维护会轻松得多。5. 让PostgreSQL像系统服务一样被管理systemd注册5.1 为什么不用直接pg_ctl来启动早期我图省事曾直接借助pg_ctl启动数据库进程确实能正常运行一旦服务器重启就无法自动拉起而且进程崩溃后也没有自动恢复机制。生产环境必须依赖系统服务管理器来守护进程在主流Linux发行版上这套工具就是systemd。手动方式适合临时验证服务注册则决定运维自动化能力。使用systemd统一管理数据库实例后可以取得几个现实的便利开机自动启动、coredump交给系统统一处理、日志通过journald归集、其他服务可以声明依赖关系等。这些能力对于生产部署都很有价值。5.2 服务单元文件的关键配置我在/etc/systemd/system/下创建了postgresql-13.service文件内容如下[Unit] DescriptionPostgreSQL 13 database server Afternetwork.target [Service] Typenotify Userpostgres Grouppostgres ExecStart/usr/local/pgsql13/bin/postgres -D /data/pgsql13/data ExecReload/bin/kill -HUP $MAINPID KillModemixed KillSignalSIGINT TimeoutSec300 [Install] WantedBymulti-user.targetTypenotify是关键项。PostgreSQL在启动完成后会向systemd发送通知systemd据此判断服务是否真正可用而不是简单认为进程fork出来就算成功。这也是postgres推荐的运行方式配置这个选项后systemctl status里能看到更准确的状态。KillModemixed配合SIGINT信号能让数据库在停止时优雅关闭先让主进程处理完事务再终止剩余进程。TimeoutSec300表示等待数据库关闭的时限大事务回滚时这个时间可能比较长别设置得太短导致强杀数据库。还需要注意PID文件。默认PostgreSQL会把PID写到数据目录的postmaster.pid里。systemd不需要手动指定PIDFile也能工作但如果你需要精确的进程状态显示可以在[Service]里加一行PIDFile/data/pgsql13/data/postmaster.pid同时确认postgresql.conf里没有把unix_socket_directories改到奇怪的位置。5.3 服务启停与开机自启验证配置文件写好后执行systemctl daemon-reload systemctl start postgresql-13 systemctl enable postgresql-13enable之后整机重启时数据库会自动启动。我建议养成一个习惯每次修改服务文件后先执行daemon-reload否则systemd可能还在使用旧的配置缓存。启动完成后可以用systemctl status postgresql-13查看状态输出一般会包含进程号、内存占用和最近日志。如果启动失败用journalctl -u postgresql-13 -n 50查看最近五十行日志信息绝大多数问题能在这里找到线索。6. 实际部署中的三个经典报错与排查链路6.1 configure阶段报缺readline库我这次编译还算顺利但在另一台干净的最小化系统上configure阶段碰到了经典的readline缺失问题。报错信息类似configure: error: readline.h not found这个报错的含义很简单readline开发头文件没有安装。普通的readline运行时库可能已经存在但编译还需要头文件所以必须安装readline-devel。这个问题通常只需yum install -y readline-devel然后重新运行configure即可。值得注意的是如果之前配置过程已经执行到一半重新运行前最好清理一下缓存的检查结果直接删除源码目录并重新解压避免旧的环境缓存干扰判断。6.2 psql运行时找不到libpq.so.5编译安装完成后我曾在另一台机器的SSH会话里直接执行psql未加载环境变量结果提示psql: error while loading shared libraries: libpq.so.5: cannot open shared object file这个问题的根源是动态链接器没有在默认路径下找到PostgreSQL自带的libpq库。源码安装到/usr/local/pgsql13后该目录不在ld默认搜索路径中。解决方案有三个设置LD_LIBRARY_PATH环境变量最简单但只对当前shell生效在/etc/ld.so.conf.d/下新建一个postgresql13.conf文件写入/usr/local/pgsql13/lib然后执行ldconfig系统级生效编译时使用--with-pgport等参数时顺带配置rpath我推荐第二种因为用户在交互式shell里可以靠LD_LIBRARY_PATH解决但定时任务、脚本等非交互环境经常不加载该变量只有ldconfig才能真正一劳永逸。6.3 启动时数据目录权限被拒绝还有一次我在普通用户下执行pg_ctl start结果日志显示FATAL: data directory /data/pgsql13/data has invalid permissions这是因为data目录的属主或权限位不对。PostgreSQL的data目录权限要求是700并且只能由数据库服务用户访问。用root解压或创建目录后再切换给postgres用户经常会出现权限位变成755或属主错误的情况。解决方式很简单chown -R postgres:postgres /data/pgsql13 chmod 700 /data/pgsql13/data顺便提醒一点PostgreSQL对data目录的安全非常敏感除了属主本人任何其他用户包括root组都不应具备访问权限。如果发现目录权限异常通常优先怀疑安装脚本或者备份恢复时使用了root操作。6.4 端口占用与防火墙拦截初始化完成后第一次尝试远程连接时发现连接超时本地psql却能正常登录。检查systemctl状态一切正常并没有报错排除了服务问题后怀疑方向主要是防火墙。CentOS 7默认使用firewalld需要放行端口才允许外部访问firewall-cmd --permanent --add-port5432/tcp firewall-cmd --reload如果是在云平台环境还需要到安全组里出方向放行对应规则。这些网络层的坑在本地虚拟机里通常不会遇到一旦部署到云上就容易踩最好是提前规划好端口清单在部署前就把防火墙规则一次性配置完毕。7. 初始化后的验证与日常管理清单7.1 确认安装信息数据库启动完成后第一件事是确认版本信息psql -U postgres -c SELECT version();正常输出的version函数会返回类似PostgreSQL 13.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5的完整信息。这里建议同时检查configure参数是否包含预期特性pg_config --configurepg_config会输出编译时的完整配置参数方便日后升级时参考。我记得当时使用pg_config确认了--with-openssl和--with-perl均成功启用。7.2 常用维护操作速查初始化完成后的日常管理命令我整理一个速查表供参考操作命令启动数据库systemctl start postgresql-13停止数据库systemctl stop postgresql-13重启数据库systemctl restart postgresql-13查看运行状态systemctl status postgresql-13加载配置不重启systemctl reload postgresql-13查看最近日志journalctl -u postgresql-13 -n 100如果修改了postgresql.conf里不影响实例运行的参数用reload即可不需要重启。修改端口、listen_addresses这类网络参数则需要完整重启。7.3 本轮源码安装的最终体会从2021年3月做这次13.2源码安装到现在中间经历过几次小版本升级都是同样的套路下载新源码包、configure、make、make install、重启实例数据目录始终没有动过。源码安装虽然首次部署比二进制包多花半小时但它带来的版本控制力和排障灵活性在后来的运维中体现出了实实在在的价值。如果你也想走这条路记得把这套流程整理成脚本或文档留在团队内部半年后再次部署时你会感谢当初认真记录的自己。
阅读完成 · 觉得有帮助?
咨询建站