Kylin服务器上PostgreSQL 16源码编译实战:从依赖陷阱到高可用部署
最近在几个国产化项目里,我频繁遇到需要在Kylin服务器上部署PostgreSQL的场景。说实话,第一次在Kylin V10 SP2上手动编译PostgreSQL 16时,踩的坑比预想的多得多——从ICU库版本冲突到systemd服务配置的权限问题,每一步都可能让你卡上半天。如果你也正准备在Kylin环境下部署PostgreSQL,特别是需要通过源码编译来满足特定定制需求或离线环境部署,这篇文章或许能帮你省下不少调试时间。
不同于简单的apt或yum安装,源码编译能让你完全掌控PostgreSQL的编译选项、安装路径和功能模块。对于需要在特定国产化平台上进行深度定制或性能优化的团队来说,这是绕不开的技术路径。但Kylin作为基于Linux的国产操作系统,其软件源、库文件版本和系统配置与常见的CentOS或Ubuntu存在微妙差异,这些差异往往会在编译过程中突然“跳出来”给你制造麻烦。
1. 环境准备与依赖库的精准处理
在Kylin上编译PostgreSQL,第一步不是急着下载源码,而是彻底搞清楚你的系统环境。我遇到过不止一次这样的情况:按照某个“通用”教程安装依赖,结果编译时还是报错,最后发现是某个库的版本不匹配。
1.1 系统环境确认
首先,你需要明确你的Kylin具体版本。不同版本的Kylin,其默认的gcc版本、glibc版本和基础库可能存在差异。执行以下命令获取详细信息:
# 查看Kylin版本信息
cat /etc/kylin-release
uname -a
# 检查gcc版本
gcc --version
# 检查glibc版本
ldd --version | head -n 1
在我的经验中,Kylin V10 SP2通常搭载gcc 7.3或8.3,而SP3可能升级到gcc 9.x。PostgreSQL 16对gcc的最低要求是4.8,但为了更好的优化效果,建议使用gcc 7.0或更高版本。如果系统自带的gcc版本过低,你需要先升级编译器。
1.2 依赖库的完整清单与安装策略
PostgreSQL编译依赖的库文件比想象中要多,而且有些库在Kylin的默认源中可能名称略有不同。下面这个表格是我在实际项目中整理的完整依赖清单,涵盖了编译PostgreSQL 16所需的所有核心库:
| 依赖包名称 | 主要用途 | Kylin中的包名(可能变体) | 是否必需 |
|---|---|---|---|
| readline-devel | 命令行编辑和历史记录支持 | readline-devel | 强烈推荐 |
| zlib-devel | 压缩支持 | zlib-devel | 必需 |
| openssl-devel | SSL加密连接 | openssl-devel | 可选但推荐 |
| libxml2-devel | XML支持 | libxml2-devel | 可选 |
| libxslt-devel | XSLT转换支持 | libxslt-devel | 可选 |
| pam-devel | PAM认证支持 | pam-devel | 可选 |
| openldap-devel | LDAP认证支持 | openldap-devel | 可选 |
| python-devel | PL/Python支持 | python3-devel | 可选 |
| perl-ExtUtils-Embed | PL/Perl支持 | perl-ExtUtils-Embed | 可选 |
| systemd-devel | systemd集成 | systemd-devel | 可选但推荐 |
| libicu-devel | ICU国际化支持 | libicu-devel | 必需(PostgreSQL 16默认需要) |
| gcc-c++ | C++编译器 | gcc-c++ | 必需 |
| make | 构建工具 | make | 必需 |
| bison | 语法分析器生成器 | bison | 必需 |
| flex | 词法分析器生成器 | flex | 必需 |
注意:Kylin的软件源有时会使用不同的包名格式。如果你发现某个包找不到,可以尝试使用
yum search或dnf search来查找正确的包名。例如,libicu-devel在某些版本中可能被命名为icu-devel。
安装这些依赖的命令看起来简单,但顺序和版本控制很重要:
# 首先更新系统(如果网络允许)
yum update -y
# 安装核心编译工具和依赖
yum install -y gcc gcc-c++ make bison flex readline-devel zlib-devel
# 安装ICU库(PostgreSQL 16的默认字符集处理依赖ICU)
yum install -y libicu libicu-devel
# 安装可选但推荐的功能支持
yum install -y openssl-devel libxml2-devel libxslt-devel systemd-devel
# 如果需要特定语言支持
yum install -y perl-ExtUtils-Embed python3-devel
这里有个关键点:ICU库的版本兼容性。PostgreSQL 16要求ICU版本不低于60,而某些较老的Kylin版本可能默认安装的是ICU 50.x。你可以通过以下命令检查:
icu-config --version
如果版本过低,你需要手动编译安装新版本的ICU,或者寻找Kylin的高版本ICU包。我遇到过ICU 58导致编译失败的情况,错误信息并不直观,只是提示某些Unicode转换函数未定义。
1.3 离线环境的依赖处理策略
在不能连接外网的Kylin服务器上,依赖安装是个挑战。我的做法是:
-
在一台相同版本的可联网Kylin服务器上,使用
yum downloadonly或dnf download下载所有依赖包:mkdir -p /tmp/pg-deps cd /tmp/pg-deps # 下载所有依赖包但不安装 yum install --downloadonly --downloaddir=. \ gcc gcc-c++ make bison flex \ readline-devel zlib-devel libicu libicu-devel \ openssl-devel libxml2-devel libxslt-devel systemd-devel -
将下载的rpm包拷贝到目标服务器,然后使用本地安装:
# 在目标服务器上 cd /path/to/rpm/packages rpm -ivh *.rpm --nodeps --force -
处理依赖关系:如果某些包有复杂的依赖关系,你可能需要创建一个本地yum仓库。这虽然麻烦,但在严格的离线环境中是必要的。
2. PostgreSQL 16源码编译的深度配置
下载和解压源码只是开始,真正的技术含量在于configure阶段的参数选择和编译优化。
2.1 源码获取与验证
从官方源获取PostgreSQL 16的最新稳定版本:
# 创建工作目录
mkdir -p /opt/src/postgresql
cd /opt/src/postgresql
# 下载源码(以16.3为例)
wget https://ftp.postgresql.org/pub/source/v16.3/postgresql-16.3.tar.gz
# 验证文件完整性(推荐)
wget https://ftp.postgresql.org/pub/source/v16.3/postgresql-16.3.tar.gz.sha256
sha256sum -c postgresql-16.3.tar.gz.sha256
# 解压
tar -zxvf postgresql-16.3.tar.gz
cd postgresql-16.3
提示:对于生产环境,我强烈建议从PostgreSQL官方镜像站下载,并验证SHA256校验和。这能避免源码被篡改或下载不完整的问题。
2.2 configure参数的艺术
./configure是编译前最重要的步骤,它决定了PostgreSQL将包含哪些功能、安装到哪里以及如何优化。在Kylin环境下,有些参数需要特别注意。
基础配置示例:
./configure \
--prefix=/usr/local/pgsql/16 \
--with-pgport=5432 \
--with-openssl \
--with-libxml \
--with-libxslt \
--with-systemd \
--with-icu \
--enable-nls \
--with-perl \
--with-python \
--with-tcl \
--with-pam \
--with-ldap
让我解释几个关键参数在Kylin环境下的特殊考虑:
-
--prefix=/usr/local/pgsql/16:我习惯将不同版本的PostgreSQL安装到不同目录,这样便于多版本共存和管理。你也可以选择/opt/pgsql/16或其他目录,但要确保有足够的磁盘空间。 -
--with-systemd:如果你计划使用systemd管理PostgreSQL服务(Kylin V10默认使用systemd),这个选项必须开启。它会生成systemd需要的服务文件。 -
--with-icu:PostgreSQL 16默认使用ICU进行字符集处理,这个选项通常应该开启。但如果你的ICU版本有问题,可以尝试--without-icu,不过这会限制某些国际化功能。 -
--enable-nls:启用本地化支持,让错误消息可以显示为中文等本地语言。这需要系统已安装相应的locale数据。
性能优化参数:
对于生产环境,你可能还需要考虑这些性能相关的参数:
./configure \
# ... 基础参数同上 ...
--with-blocksize=32 \
--with-wal-segsize=64 \
--with-wal-blocksize=32
--with-blocksize=32:将数据块大小从默认的8KB增加到32KB。这对于数据仓库或分析型应用可能有益,但会减少缓存效率。需要根据实际负载测试。--with-wal-segsize=64:将WAL段大小从16MB增加到64MB,减少WAL文件数量,适合高写入负载。--with-wal-blocksize=32:WAL块大小调整,与数据块大小保持一致。
Kylin特定问题处理:
在Kylin上运行configure时,可能会遇到以下问题:
-
Python路径问题:如果configure报告找不到Python,可能需要明确指定Python3路径:
export PYTHON=/usr/bin/python3 ./configure --with-python ... -
Perl路径问题:类似地,Perl也可能需要明确路径:
export PERL=/usr/bin/perl -
readline库冲突:如果系统同时安装了libedit和readline,configure可能会选择libedit。要强制使用readline:
./configure --with-readline --without-libedit-preferred ...
configure完成后,仔细查看输出信息,确认所有需要的功能都已检测到并启用。特别关注是否有警告信息,如"XXX development package not found"。
2.3 编译与安装的优化技巧
配置完成后,开始编译:
# 使用多核编译加速(根据你的CPU核心数调整)
make -j $(nproc) world
make world会编译主程序和所有contrib模块。如果你不需要某些contrib模块,可以使用make all只编译核心部分。
编译过程中可能遇到的常见问题:
-
内存不足:编译PostgreSQL需要较多内存,如果内存不足,可以减少并行编译任务数:
make -j 2 # 只使用2个并行任务 -
ICU版本不兼容:如果遇到ICU相关错误,可以尝试:
# 临时禁用ICU支持重新configure ./configure --without-icu ... make clean make -j $(nproc) -
Python扩展编译失败:如果PL/Python编译失败,可以跳过:
# 重新configure时不包含Python支持 ./configure --without-python ...
编译成功后,进行安装:
# 安装到configure指定的prefix目录
make install-world
install-world会安装所有编译好的组件,包括contrib模块。安装完成后,检查目标目录:
ls -la /usr/local/pgsql/16/
你应该看到类似这样的目录结构:
bin/ # 可执行文件
include/ # 头文件
lib/ # 库文件
share/ # 共享文件
3. 数据库初始化与系统集成
PostgreSQL编译安装完成后,还需要进行数据库初始化、用户配置和系统服务集成。
3.1 专用用户与目录权限管理
为PostgreSQL创建专用系统用户是安全最佳实践:
# 创建postgres组和用户
groupadd postgres
useradd -g postgres -m -s /bin/bash postgres
# 设置密码
passwd postgres
创建数据目录并设置正确的权限:
# 创建数据目录(我习惯将数据与程序分离)
mkdir -p /data/pgsql/16/data
mkdir -p /data/pgsql/16/logs
mkdir -p /data/pgsql/16/archive # 用于WAL归档
# 设置所有权
chown -R postgres:postgres /data/pgsql
chmod 750 /data/pgsql/16/data
# 设置SELinux上下文(如果Kylin启用了SELinux)
semanage fcontext -a -t postgresql_db_t "/data/pgsql/16/data(/.*)?"
restorecon -Rv /data/pgsql/16/data
注意:Kylin可能使用不同于CentOS的SELinux策略。如果遇到权限问题,可以临时将SELinux设置为permissive模式调试:
setenforce 0但生产环境应该配置正确的SELinux策略。
3.2 环境变量配置
为postgres用户配置环境变量,简化日常操作:
# 切换到postgres用户
su - postgres
# 编辑.bash_profile
vi ~/.bash_profile
添加以下内容:
# PostgreSQL环境变量
export PGHOME=/usr/local/pgsql/16
export PGDATA=/data/pgsql/16/data
export PATH=$PGHOME/bin:$PATH
export LD_LIBRARY_PATH=$PGHOME/lib:$LD_LIBRARY_PATH
export MANPATH=$PGHOME/share/man:$MANPATH
# 可选:设置默认连接参数
export PGPORT=5432
export PGUSER=postgres
使配置生效:
source ~/.bash_profile
3.3 数据库集群初始化
现在可以初始化数据库集群了:
# 确保当前用户是postgres
whoami # 应该显示postgres
# 初始化数据库集群
initdb -D $PGDATA \
--encoding=UTF8 \
--locale=en_US.UTF-8 \
--lc-collate=en_US.UTF-8 \
--lc-ctype=en_US.UTF-8 \
--data-checksums
关键参数说明:
--encoding=UTF8:设置数据库默认编码为UTF-8,支持多语言。--locale和--lc-*参数:设置区域设置,影响排序、大小写敏感等行为。--data-checksums:启用数据页校验和,增加数据完整性保护,但有轻微性能开销。
初始化完成后,检查生成的文件:
ls -la $PGDATA/
你应该看到postgresql.conf、pg_hba.conf等配置文件。
3.4 基础配置调整
在启动数据库前,需要调整一些基本配置:
# 编辑主配置文件
vi $PGDATA/postgresql.conf
以下是生产环境推荐的最小配置调整:
# 连接设置
listen_addresses = 'localhost' # 初始只监听本地,安全后再改
port = 5432 # 默认端口
max_connections = 100 # 根据实际需求调整
# 内存设置(根据服务器内存调整)
shared_buffers = 128MB # 起步值,通常设为内存的25%
work_mem = 4MB # 每个操作的内存
maintenance_work_mem = 64MB # 维护操作的内存
# 日志设置
logging_collector = on
log_directory = '/data/pgsql/16/logs'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_rotation_age = 1d
log_rotation_size = 100MB
log_min_duration_statement = 1000 # 记录执行超过1秒的语句
# 性能相关
synchronous_commit = on # 数据安全与性能的平衡
wal_level = replica # 复制所需的最低WAL级别
max_wal_senders = 10 # 最大WAL发送进程数
接下来配置客户端认证:
vi $PGDATA/pg_hba.conf
在文件末尾添加:
# 允许本地所有连接(初始配置)
local all all trust
host all all 127.0.0.1/32 trust
# 允许特定IP段的密码连接(根据实际需求调整)
# host all all 192.168.1.0/24 md5
安全提醒:
trust认证方式意味着不需要密码,仅适用于初始配置或完全信任的环境。生产环境应该使用md5或scram-sha-256等更安全的认证方式。
4. systemd服务集成与生产环境优化
将PostgreSQL集成到systemd,可以享受自动启动、服务管理和日志集成等便利。
4.1 创建systemd服务文件
在Kylin上,我们可以手动创建systemd服务文件:
# 切换回root用户
exit
# 创建服务文件
vi /etc/systemd/system/postgresql-16.service
添加以下内容:
[Unit]
Description=PostgreSQL 16 Database Server
Documentation=https://www.postgresql.org/docs/16/
After=network.target
After=syslog.target
[Service]
Type=notify
User=postgres
Group=postgres
# 环境变量
Environment=PGDATA=/data/pgsql/16/data
Environment=PGLOG=/data/pgsql/16/logs
# 执行命令
ExecStart=/usr/local/pgsql/16/bin/postgres -D ${PGDATA}
ExecReload=/bin/kill -HUP $MAINPID
KillMode=mixed
KillSignal=SIGINT
TimeoutSec=0
# 资源限制(根据实际情况调整)
LimitNOFILE=65536
LimitNPROC=65536
# 安全设置
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
NoNewPrivileges=true
# 工作目录
WorkingDirectory=/data/pgsql/16/data
# 标准输出/错误重定向到系统日志
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=postgresql-16
# 重启策略
Restart=on-failure
RestartSec=5s
TimeoutStartSec=300
TimeoutStopSec=300
[Install]
WantedBy=multi-user.target
这个服务文件做了几件重要的事情:
- 使用Type=notify:PostgreSQL支持systemd通知协议,可以更好地集成。
- 设置资源限制:提高文件描述符和进程数限制。
- 安全加固:通过PrivateTmp、ProtectSystem等选项限制服务权限。
- 日志集成:将输出重定向到系统日志,便于集中管理。
4.2 服务管理与测试
启用并启动服务:
# 重新加载systemd配置
systemctl daemon-reload
# 启用开机自启
systemctl enable postgresql-16
# 启动服务
systemctl start postgresql-16
# 检查状态
systemctl status postgresql-16
# 查看日志
journalctl -u postgresql-16 -f
如果服务启动失败,查看详细日志:
journalctl -u postgresql-16 --no-pager -n 50
常见启动问题及解决方案:
- 权限问题:确保
/data/pgsql/16/data目录的所有者是postgres用户,且权限正确。 - 端口冲突:检查5432端口是否被其他进程占用:
ss -tlnp | grep :5432 - SELinux阻止:如果启用了SELinux,可能需要调整策略:
# 查看SELinux日志 ausearch -m avc -ts recent # 临时解决方案(生产环境应配置正确策略) setenforce 0
4.3 基础功能测试
服务启动后,进行基本功能测试:
# 切换到postgres用户
su - postgres
# 连接数据库
psql -c "SELECT version();"
# 创建测试数据库和用户
psql -c "CREATE USER testuser WITH PASSWORD 'TestPass123';"
psql -c "CREATE DATABASE testdb OWNER testuser;"
# 测试新用户连接
PGPASSWORD='TestPass123' psql -U testuser -d testdb -c "SELECT current_user, current_database();"
4.4 性能调优与监控
对于生产环境,还需要进行性能调优和监控配置。以下是一些关键调整:
内存优化配置(在postgresql.conf中):
# 根据服务器内存调整(假设服务器有16GB内存)
shared_buffers = 4GB # 内存的25%
work_mem = 16MB # 每个排序/哈希操作的内存
maintenance_work_mem = 1GB # 维护操作(VACUUM等)的内存
effective_cache_size = 12GB # 操作系统和PostgreSQL的缓存估计
# WAL设置
wal_buffers = 16MB
min_wal_size = 1GB
max_wal_size = 4GB
# 检查点优化
checkpoint_completion_target = 0.9
checkpoint_timeout = 15min
# 并行查询设置
max_parallel_workers_per_gather = 4
max_parallel_workers = 8
max_parallel_maintenance_workers = 4
安装常用扩展:
PostgreSQL的contrib模块包含许多有用的扩展。编译时如果使用了make world,这些扩展已经编译好了,只需要在数据库中创建:
-- 连接到数据库
\c testdb
-- 安装常用扩展
CREATE EXTENSION IF NOT EXISTS pg_stat_statements; -- SQL性能监控
CREATE EXTENSION IF NOT EXISTS pgcrypto; -- 加密函数
CREATE EXTENSION IF NOT EXISTS hstore; -- 键值对存储
CREATE EXTENSION IF NOT EXISTS btree_gin; -- GIN索引支持
配置pg_stat_statements(在postgresql.conf中):
shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.max = 10000
pg_stat_statements.track = all
pg_stat_statements.save = on
重启服务后,可以查询执行统计:
SELECT query, calls, total_exec_time, mean_exec_time
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
4.5 备份与恢复策略
即使是新安装的数据库,也应该立即建立备份策略。以下是一个简单的脚本示例:
#!/bin/bash
# /usr/local/bin/pg_backup.sh
BACKUP_DIR="/data/pgsql/backups"
DATE=$(date +%Y%m%d_%H%M%S)
PGUSER="postgres"
PGPORT="5432"
# 创建备份目录
mkdir -p $BACKUP_DIR/$DATE
# 执行逻辑备份(所有数据库)
pg_dumpall -U $PGUSER -p $PGPORT | gzip > $BACKUP_DIR/$DATE/full_backup.sql.gz
# 也可以使用物理备份(需要配置归档)
# pg_basebackup -D $BACKUP_DIR/$DATE -Ft -z -U $PGUSER -p $PGPORT
# 清理7天前的备份
find $BACKUP_DIR -type d -mtime +7 -exec rm -rf {} \;
echo "Backup completed: $BACKUP_DIR/$DATE"
设置定时任务:
# 编辑crontab
crontab -e
# 添加每天凌晨2点执行备份
0 2 * * * /usr/local/bin/pg_backup.sh >> /var/log/pg_backup.log 2>&1
4.6 安全加固建议
最后,不要忽视安全配置:
-
修改默认密码:
ALTER USER postgres WITH PASSWORD 'StrongPassword123!'; -
限制连接:根据实际需求调整
pg_hba.conf,只允许必要的IP连接。 -
启用SSL(如果编译时包含openssl支持):
# 在postgresql.conf中 ssl = on ssl_cert_file = 'server.crt' ssl_key_file = 'server.key' -
定期更新:关注PostgreSQL安全公告,及时应用安全更新。
-
审计日志:启用详细日志记录可疑活动:
log_statement = 'ddl' # 记录所有DDL语句 log_connections = on # 记录所有连接尝试 log_disconnections = on # 记录所有断开连接 log_hostname = on # 记录客户端主机名
在Kylin上手动编译PostgreSQL 16确实比直接安装二进制包复杂,但这种控制力带来的好处也是显而易见的——你可以根据硬件特性优化编译参数,只包含需要的功能模块,深度集成到系统管理框架中。整个过程最耗时的往往不是编译本身,而是解决那些因环境差异导致的依赖问题和配置调整。一旦你成功走通这个流程,后续在类似环境下的部署就会顺利得多。
我自己的经验是,第一次在Kylin V10 SP2上完成全套部署花了将近一天时间,其中大部分时间都在调试ICU库版本和systemd权限问题。但有了这次经验后,最近一次在类似环境下的部署只用了不到两小时。关键是把每个步骤的细节和可能的问题都记录下来,形成自己的检查清单。
329



被折叠的 条评论
为什么被折叠?



