银河麒麟V10-ARM架构-postgresql安装与部署指南
最近在给单位机房里的几台国产化服务器做数据库选型,平台是银河麒麟V10(ARM架构,飞腾/鲲鹏那一类芯片),数据库要装PostgreSQL。说起来这事儿看着不复杂,网上教程也不少,但真到自己上手才发现,ARM架构 + 国产系统这套组合拳,坑比想象中多。我把整个从零开始的安装部署过程完整记录了一遍,包括方案选型的纠结、踩过的坑、最终敲定的步骤和配置,希望对正在搞国产化替代、信创项目,或者单纯想在ARM Linux上跑PG的朋友有点帮助。
先说结论:银河麒麟V10 ARM版装PostgreSQL,最稳的路子是源码编译安装,别指望直接用官方现成的二进制包。原因后面详细说。整个过程大概分四步走:准备环境、编译安装、初始化配置、安全加固。每条命令都是我在机器上一行行敲过、验证过能跑的,不是那种抄来抄去连路径都对不上的“复制粘贴教程”。如果你手头正好是Kylin V10 + 飞腾/鲲鹏的机器,照着操作基本一遍过;就算不是这两款芯片,只要摸清了ARM架构Linux的安装逻辑,也能顺利迁移过去。
1. 内容整体设计与思路拆解
1.1 为什么ARM架构下不能“无脑”装PostgreSQL
先说第一个问题:为什么不直接yum install postgresql-server或者去官网下载RPM包装就完事了?非要搞源码编译这一套?原因其实就三个字——不兼容。
银河麒麟V10虽然底层兼容CentOS的生态,很多命令都和RHEL系很像,但它在ARM架构下的软件仓库和x86_64体系是有差异的。具体到PostgreSQL,官方提供的RPM包是针对主流Linux发行版编译好的二进制,ARM版本也有,但挑系统环境。银河麒麟的glibc版本、内核头文件、openssl库和官方打包时假设的环境不一定完全匹配,经常出现两种情况:一种是装完以后initdb初始化时报动态链接库找不到;另一种是能装上,但运行一段时间就莫名其妙崩了,日志里全是段错误之类的问题。生产环境出这种幺蛾子,谁都兜不住。
还有一个很隐蔽的问题:ARM架构下,PostgreSQL的某些汇编优化并不通用。PostgreSQL底层为了性能,在x86和ARM上有不同的原子操作实现,如果直接用别的发行版编译好的二进制,可能就没有把ARM芯片的特性指令集利用起来(比如LSE原子指令),导致在高并发下性能掉得厉害。自己编译,这些都能根据本机CPU特性打开,性能上有保障。
所以,对于银河麒麟V10 ARM这种“定制化”环境,源码编译是最可控、最不容易踩坑的选择。编译参数自己定、依赖自己解决、安装路径自己规划,完全掌控在手里,排查问题也方便。对搞运维的人来说,多花个十几分钟编译,换后面几个月省心,这买卖划算。
1.2 安装方式与版本选型的取舍逻辑
PostgreSQL在Linux上的安装方式主要有四种:自带包管理器安装(yum/apt)、官方RPM仓库安装、Docker容器化安装、源码编译安装。在这个项目里,我最终放弃了前三种,选了源码编译安装,理由在1.1部分已经说了一部分,再补充几点。
Docker容器化安装IDE很想推荐,拉个镜像几分钟搞定,但有两个硬伤:一是很多政企内网环境,根本没有外网权限去拉镜像,需要离线交付;二是PostgreSQL在容器里的性能裸跑,在高并发下的IO延迟比物理机部署要高,而且管理运维复杂,对传统运维团队不是特别友好。当然,如果你在内网提前导入了镜像,Docker依然是个好方案,这里不做死推荐。
官方RPM仓库方案直接被毙,因为PostgreSQL官方没有针对银河麒麟V10 ARM做专门打包。虽然技术上可能有“兼容性很好,直接拿来用也能跑”的说法,但生产环境我不愿意赌这个万一。
版本选型上,我用的是PostgreSQL 14.x的当前补丁版本。为什么不选最新的16?一是兼容性考虑,PG14的编译依赖比较保守,对glibc、gcc版本要求不高,和银河麒麟V10默认自带的gcc 8.x搭配很好,不容易报编译错误;二是PG14上踩坑的人多,相关资料、内核参数优化案例都比较成熟,出了问题能在网上很快找到解决方案;三是新特性对当前业务没有特别大的吸引力,稳定压倒一切。建议你也别追新,选一个自己熟悉的、生态成熟的版本,这比追求几个新功能实在得多。
1.3 部署路径与关键前置条件梳理
整个部署流程里,有几个前置条件必须在动手前确认,不然中途容易卡住。
第一个是硬件架构确认。别光看CPU品牌,用uname -m看一下系统架构,输出是aarch64就对了,这是ARM 64位的标识。如果是x86_64,那是普通Intel/AMD平台,安装逻辑又不一样了。
第二个是系统版本确认。用cat /etc/os-release和nproc确认系统版本和CPU核数,后面编译参数里要用到核数,比如make -j8,如果CPU核数少,编译参数填太大了容易内存不足。
第三个是磁盘空间。
编译安装需要至少2GB临时空间,数据目录建议单独放一个分区,至少预留几十GB,看业务量定。我见过有人把数据目录直接放根分区,跑一段时间根分区满了,整个库直接变只读,这种事故很低级,尽量别犯。
第四个是网络权限。
编译过程中会下载一些依赖包(比如readline、zlib),如果内网环境没有yum源,需要提前把这些依赖包准备好,离线安装。我在2.2节会详细说怎么处理离线依赖。
2. 环境准备与依赖处理
2.1 系统信息确认与基础环境检查
准备工作先从确认系统信息开始,我习惯先敲这几条命令,把机器基本情况摸清楚,再决定后续操作:
cat /etc/os-release # 查看系统版本 uname -m # 查看芯片架构 nproc # 查看CPU核数 free -h # 查看内存 df -h / # 查看根分区磁盘空间 gcc --version # 查看gcc编译器版本我测试机上返回的结果大概是这样的:系统是Kylin V10 SP1或SP2,架构是aarch64,CPU核数16核,内存32GB。这只是测试机的配置,生产环境更高的配置当然更好,但编译参数要跟着调整。
确认完系统,还有一个很重要的检查项——确认系统里有没有安装PostgreSQL相关的旧包。如果有,要先卸载掉,避免端口、数据目录冲突:
rpm -qa | grep postgresql # 查看是否有旧包如果有输出,用rpm -e --nodeps 包名强制卸载。这一步虽然简单,但有时候会被忽略,导致后面初始化数据库时报“data directory exists”或者端口被占用的错,很烦人。
2.2 依赖包安装方法与离线环境处理
PostgreSQL源码编译需要几个基础依赖库:readline(命令行历史记录功能)、zlib(压缩支持)、gcc(编译器)、make(构建工具)、还有openssl(可选,SSL连接用)。
在有外网权限的环境里,直接用yum安装:
yum install -y readline readline-devel zlib zlib-devel gcc make openssl openssl-devel注意一点:一定要装xxx-devel版本,光有运行库没用,编译的时候需要头文件。我记得之前就有同事只装了readline没装readline-devel,configure阶段一直报找不到库,浪费了半小时。
如果是纯内网环境,没有外网也没有内网yum源,那就需要在一台能联网的同架构机器上把RPM包下载好,再拷贝过去。下载命令如下:
# 在联网机器上执行 yum install --downloadonly --downloaddir=/opt/pgdeps readline readline-devel zlib zlib-devel gcc make openssl openssl-devel把/opt/pgdeps目录打包拷到内网机器上,然后:
rpm -Uvh /opt/pgdeps/*.rpm这里有一个非常容易被坑的点:拷贝依赖包的时候,一定要确保源机器和目标机器的系统版本尽量一致。如果源机器是CentOS 8,目标机器是麒麟V10,rpm包勉强能装上,但如果源机器是CentOS 7,包的glibc要求可能和目标不匹配,强制装会破坏系统底层的依赖关系。这个问题处理起来很麻烦,严重的情况可能要重装系统。所以条件允许的话,最好的方式是在一台同系统版本、同架构的机器上准备好依赖包,再拿到目标机器上用。我不想吓唬人,但这种风险真实存在,提前说明有备无患。
2.3 新建运行用户与数据目录规划
PostgreSQL不能用root用户运行,这在官方文档里是明确警告过的。原因很简单,数据库进程需要控制文件权限、防止越权访问,用root跑会带来巨大的安全隐患。所以我们要创建一个专用用户。
groupadd postgres useradd -g postgres -m -s /bin/bash postgres创建数据目录。我的习惯是把数据目录放到独立的挂载点上,比如/data分区,专门用于数据库存储:
mkdir -p /data/pgdata chown -R postgres:postgres /data/pgdata chmod 700 /data/pgdatachmod 700这里为啥要单独提?因为PostgreSQL官方建议PGDATA目录权限必须是700,也就是只有属主能进,否则initdb会拒绝初始化。这是出于保护数据文件的考虑,目录权限太开放,任何用户都能读数据库文件,等于脱裤子。
安装目录我一般放在/usr/local/postgresql,也把它归属到postgres用户:
mkdir -p /usr/local/postgresql chown -R postgres:postgres /usr/local/postgresql别小看目录规划这一步。很多人在后面启动服务时报各种奇怪错误,根本原因就是目录权限不对。先规划好,后面省心。
3. 下载、编译与安装PostgreSQL的完整流程
3.1 PostgreSQL源码获取与校验
源码从官网下载,地址是https://www.postgresql.org/ftp/source/。因为我在隔离内网环境,所以提前在外面下载好,用U盘拷进去。选择版本号,比如v14.17这种具体的补丁版本号,别选v14这种大版本,补丁版本带了Bug修复,稳定性更好。
下载完以后,解压:
tar -zxvf postgresql-14.17.tar.gz cd postgresql-14.17这里我额外多做一步,校验文件完整性,这是很多教程都不会提的。PostgreSQL官网在源码包旁边提供了sha256校验文件,下载后算一下:
sha256sum postgresql-14.17.tar.gz和官网给出的校验值对比,一致才继续。为什么强调这个?源码包在传输过程中如果损坏,编译会报各种莫名其妙的错误,提前校验能排除这一点。另外,从安全角度讲,确认下载的源码没有被篡改,对生产环境部署而言也是一种基本保障。
3.2 configure参数详解与选择依据
解压完成后,进入源码目录,执行configure脚本。这里参数很关键,不是随便敲的。我当时的配置命令长这样:
./configure --prefix=/usr/local/postgresql \ --with-pgport=5432 \ --with-openssl \ --readline \ --zlib \ --with-perl \ --with-python参数含义拆开讲一下:
--prefix:指定安装路径,后续的所有二进制文件、库文件、头文件都会装到这个目录下。我习惯用/usr/local/postgresql,好记也方便卸载。
--with-pgport:指定数据库默认端口,不指定的话默认就是5432,用系统标准端口的话可以不写。但我建议你写,因为显式声明端口可以在初始化时就把配置文件里的端口写死,避免后面还要手动改。
--with-openssl:启用SSL加密连接支持。生产环境基本都要求数据库连接走SSL,现在不开启,后面业务要加密连接还得重新编译,费老劲了。
--with-perl和--with-python:启用PL/Perl和PL/Python存储过程语言支持。如果业务里用不到,可以不开启,减少依赖。我保留了,因为之前遇到过业务方要做数据清洗,写了自定义存储过程,没有这个支持直接报错。
还有一个可选参数--with-icu,启用ICU国际化支持,处理多语言排序、字符集比较时更准确。如果系统里没有ICU库,configure会报错,得先装libicu-devel。考虑到很多系统环境里字符集是GBK或UTF8,排序要求不高,我当时就没启用,反正够用。看你的实际需求取舍。
configure执行完,最后会输出一个配置摘要,检查一下有没有“WARNING”字样。某些依赖库没有找到时,即使configure成功了,也会以警告形式提示,比如“readline not found”,这时候编译出来的PG命令行工具就没有历史记录功能,虽然不影响主功能,但用起来很别扭。所以看到WARNING建议先解决掉再继续。
3.3 make编译过程与常见卡点
configure通过以后,开始编译:
make -j 8-j 8代表用8个线程并行编译。我机器是16核的,理论上-j 16更快,但我保守了一点,只用了8。为啥不拉满?因为我遇到过并行编译任务开太多导致内存撑爆的。编译PostgreSQL时GCC的预处理阶段特别吃内存,每个编译任务大约占1~2GB内存,如果机器只有16GB内存,开16个并行任务很容易把内存耗尽。到时候编译进程被内核杀掉,前功尽弃,还得重来。一般建议内存多少GB就用多少并行任务,比如32GB内存用8~16个任务,16GB内存用4~8个。
编译过程根据CPU性能不同,大约要5~15分钟。这一步出错比较少,如果报了错,90%的可能性是前置依赖没装全。常见的报错是找不到头文件,比如:
fatal error: zlib.h: No such file or directory这就是zlib-devel没装。回到2.2节,把依赖装全了重新编译。
编译完成后安装:
make install到这里,PostgreSQL软件本体就已经装好了。验证一下:
ls /usr/local/postgresql/bin/应该能看到initdb、postgres、psql、pg_ctl这些关键命令,到这里安装阶段完成。
注意:如果后面还要装PostGIS、pgvector这类扩展插件,源码目录先别删,很多扩展编译需要用到PG的源码头文件,删了还得重新下载。
3.4 配置环境变量
安装完成后,要把PostgreSQL的bin目录加进PATH,不然每次执行psql都要写完整路径,繁琐也容易输错。编辑postgres用户的~/.bashrc:
su - postgres vi ~/.bashrc在文件末尾追加:
export PATH=/usr/local/postgresql/bin:$PATH export PGDATA=/data/pgdata export LD_LIBRARY_PATH=/usr/local/postgresql/lib:$LD_LIBRARY_PATHLD_LIBRARY_PATH这里特别提醒一下:PostgreSQL的很多库文件不放在系统默认库路径下,不把这个目录加进去,启动服务时可能会报找不到libpq.so.5这类错误。这个变量是一定要加的。
改完以后让配置生效:
source ~/.bashrc which psql能输出/usr/local/postgresql/bin/psql,说明环境变量生效了。
顺便说一句,如果你习惯用root用户操作,那把这三个变量也加到root的~/.bashrc里,省得来回切换用户。数据库服务和数据文件归postgres用户管,但排查问题时经常要用root去看系统日志,两边都配好环境变量,操作起来顺手得多。
4. 初始化数据库与核心配置
4.1 initdb初始化与premote认证说明
这是整个部署流程里最容易出问题、也最需要谨慎对待的一步。初始化数据库一定要用postgres用户来跑:
su - postgres initdb -D /data/pgdata -E UTF8 --locale=en_US.UTF8 -U postgres参数解释:
-D:指定数据目录,必须和前面创建的一致。
-E UTF8:指定数据库默认编码为UTF8。这个很重要,现在业务数据基本都会涉及中文,UTF8是通用标准。如果默认编码设成SQL_ASCII或GBK,后面想转UTF8很麻烦,导出再导入太折腾,数据量大一点直接伤筋动骨。
--locale=en_US.UTF8:指定数据库的初始化区域设置。这里有个坑:如果系统里没有安装en_US.UTF8这个locale,initdb会报错。可以先执行locale -a查看系统支持的locale列表,没有的话用localedef生成:
localedef -i en_US -f UTF-8 en_US.UTF-8-U postgres:指定数据库超级用户名为postgres。这相当于MySQL里的root,是整个数据库实例权限最高的账号。
初始化完成以后,日志最后会有一段提示说“You can now start the database server”。先别急着启动,检查一个东西——认证配置文件pg_hba.conf。默认生成的配置在最底层有几行trust认证记录,意思是不需要密码就能连上数据库,这对于安全性要求高的生产环境是不可接受的。后面5.2节我会详细讲怎么改认证配置。
注意:initdb生成的初始密码是不是空的?是这样的,但这里的“空密码”不等于“无认证”。默认pg_hba.conf对本地连接配的是
trust认证,也就是本地任何用户都不用输入密码就能以任何数据库用户身份登录,这个是相当危险的。虽然默认只允许本地连接,服务器上只要有另一个账号被入侵,数据库整个就暴露了。所以“初始化完立即改认证方式和密码”是必须要做的。
4.2 postgresql.conf核心参数修改建议
初始化完成后,编辑/data/pgdata/postgresql.conf,这里是最核心的配置文件。我把关键参数的调整思路说明一下:
vi /data/pgdata/postgresql.conflisten_addresses:默认是localhost,只允许本机访问。如果要让其他机器连数据库,改成*或者指定IP。改成*表示监听所有网卡,配合防火墙白名单来限制访问。如果你只让特定客户端连接,写成具体IP,比如192.168.1.100。
port:端口号,默认5432,前面configure时已指定,不用改。如果系统里还跑着其他数据库(比如人大金仓的默认端口也是5432),记得错开。
max_connections:最大连接数,默认100。要根据业务并发量调,但也不是越大越好,每个连接都要消耗内存,连接数设置太高会导致内存吃紧。我一般按照“每连接额外消耗2MB内存左右”来估算。比如内存32GB,预留一部分给系统,max_connections设500左右比较合理。
shared_buffers:共享缓冲区,这是最影响性能的参数之一。PG官方建议设为物理内存的25%,比如32GB内存就设8GB。但要注意,4GB以上需要系统共享内存参数支持,如果系统内核参数没调,设置太高会导致数据库启动失败。如果设置后启动报错,可以先调回1GB,再查看系统/etc/sysctl.conf中kernel.shmmax参数并调大。
work_mem:单个排序操作可以使用的内存,默认4MB。这个参数不是越大越好,因为它是按操作分配的,并发高的场景下,几百个排序操作同时执行,每个4MB变成几百MB。一般先保留默认,等业务上线后通过慢查询日志和性能监控逐步调优。
effective_cache_size:这不是实际分配内存的参数,而是告诉优化器“系统大概有多少内存可以用于文件缓存”。一般设为物理内存的50%~75%,设太低了可能导致优化器低估索引扫描的效率,走全表扫描,性能差很多。这个参数不影响实际内存分配,设高一点没有风险。
wal_level:如果是生产环境做流复制,要改成replica;单机部署默认的replica即可。minimal级别虽然性能好一点,但很多灾备功能用不了,安全起见用replica。
我做完这些修改后,会先检查一遍文件内容,确认没有语法问题再启动。注意:PG配置文件是改一个生效一个?不是,大部分参数要重启数据库服务才生效,小部分通过pg_ctl reload就能热加载,比如max_connections要重启,shared_buffers要重启,work_mem可以热加载。不确定的参数改完统一重启服务。
4.3 配置systemd服务实现开机自启动
编译安装的PostgreSQL不会自动注册systemd服务,每次手动pg_ctl start效率太低,服务器重启后数据库也不会自动拉起来,这在生产环境是绝对不行的。我写了一个systemd服务配置文件,放到/etc/systemd/system/postgresql.service,内容如下:
[Unit] Description=PostgreSQL database server After=network.target [Service] Type=forking User=postgres Group=postgres PIDFile=/data/pgdata/postmaster.pid ExecStart=/usr/local/postgresql/bin/pg_ctl start -D /data/pgdata -l /data/pgdata/logfile ExecStop=/usr/local/postgresql/bin/pg_ctl stop -D /data/pgdata -m fast ExecReload=/usr/local/postgresql/bin/pg_ctl reload -D /data/pgdata TimeoutSec=600 [Install] WantedBy=multi-user.target配置说明:
Type=forking:postgres主进程启动后会fork出子进程,用这个类型systemd才能正确跟踪主进程状态。
PIDFile:指向postmaster.pid,这个文件由PostgreSQL自动生成,记录主进程PID。路径一定要和PGDATA一致,不一致会导致systemd认为服务启动失败。
ExecStop:用-m fast快速关闭模式,相当于SQL里的快速关机,拒绝新连接并等待正在执行的事务完成,然后再停。默认模式是smart,会一直等所有客户端断连才停,有长连接挂着可能等几个小时。运维中一般用fast比较合适。
WantedBy:让服务在系统进入多用户模式时自动启动。
配置文件写好以后:
systemctl daemon-reload systemctl enable postgresql systemctl start postgresql systemctl status postgresql看到active (running)说明服务启动成功了。
这里有一个编译安装最常见的坑:pg_ctl start启动时可能报找不到libpq.so.5这个动态库。虽然我们在3.4节配置了环境变量,但systemd启动服务时不会加载用户的环境变量,只加载系统环境。解决方式是创建一个库文件配置:
echo "/usr/local/postgresql/lib" > /etc/ld.so.conf.d/postgresql.conf ldconfig然后重启服务,这个问题就解决了。
5. 安全加固、远程连接与基础运维
5.1 设置超级用户密码并调整pg_hba.conf认证
初始化之后的第一件事,给postgres用户设置密码:
su - postgres psql -c "ALTER USER postgres WITH PASSWORD '你的强密码';"密码复杂度建议至少12位,包含大小写字母+数字+特殊字符。生产环境千万别用postgres、123456这种弱口令,现在的安全扫描工具很成熟,弱口令基本一抓一个准。
然后编辑/data/pgdata/pg_hba.conf。这个文件是PG的访问控制清单,决定谁能连、从哪连、怎么认证。我建议这样配置:
# 本地Unix套接字连接使用peer认证,即系统用户和数据库用户同名即可连接(仅限本地) local all all peer # 本机IPv4回环地址使用scram-sha-256加密认证 host all all 127.0.0.1/32 scram-sha-256 # 本机IPv6回环地址 host all all ::1/128 scram-sha-256 # 内网网段,按实际调整 host all all 192.168.0.0/16 scram-sha-256peer认证的含义是“系统用户名 == 数据库用户名”即通过认证,不需要密码。这个只对本地生效,安全性尚可(基于操作系统用户身份)。对于远程连接,全部用scram-sha-256密码加密认证。PostgreSQL 14里默认的密码加密方式就是scram-sha-256,比老的md5安全得多。
修改完pg_hba.conf以后,执行pg_ctl reload让配置生效,不需要重启数据库:
pg_ctl reload -D /data/pgdata注意:每次改完pg_hba.conf之前,建议先备份原文件。别问我为什么,改错一个参数导致数据库拒绝所有连接,然后手忙脚乱找回滚文件的经历,一次就长记性了。
5.2 防火墙与远程连接测试
远程连接数据库,除了PG侧的认证配置,还要过防火墙这一关。用firewalld的话:
firewall-cmd --permanent --add-port=5432/tcp firewall-cmd --reload如果是用iptables管理,自己加一条规则:
iptables -A INPUT -p tcp --dport 5432 -j ACCEPT这里说一个我踩过的坑:有些麒麟V10系统带了一个叫kysec的安全组件,它会额外拦截网络端口的访问,即使防火墙放行了也可能连不上。如果发现端口明明开着、数据库也在监听、防火墙也放行了,但就是连不上,第一反应看看是不是kysec的问题。这东西属于麒麟自带的强制访问控制机制,命中了会在/var/log/messages里留下记录,查看系统日志是一个很有效的排查路径。
配置完成后,在内网的另外一台机器上测试连接:
psql -h 192.168.1.10 -p 5432 -U postgres -d postgres输入密码能连上并进入psql交互界面,就说明整个链路是通的。提示一下:客户端也需要安装PostgreSQL的客户端工具包,如果在Windows上,可以用pgAdmin或者直接用psql命令行。
5.3 数据库日常启停、日志查看与备份命令
部署完成不代表结束,日常运维手段才是保障生产稳定性的关键。核心命令我整理了一份速查清单:
systemctl start postgresql # 启动数据库 systemctl stop postgresql # 停止数据库 systemctl restart postgresql # 重启数据库 systemctl status postgresql # 查看运行状态 pg_ctl reload -D /data/pgdata # 热加载配置,无需重启 tail -f /data/pgdata/logfile # 实时查看数据库日志日志这块,PG的默认配置是把日志输出到stderr,再转写到日志文件。我在postgresql.conf里还改了logging_collector为on,并设置log_directory = 'log',这样日志会统一放到PGDATA/log目录下,按天滚动,方便排查问题。生产环境建议将log_min_duration_statement设为1000ms,记录执行超过1秒的慢SQL,这是后续性能调优的重要依据。
备份是最不能忽视的环节。PG的单机备份最简单有效的方式是pg_dump:
# 备份单个数据库 pg_dump -h localhost -U postgres -d 你的数据库名 -F c -f /backup/库名.dump # 还原数据库 pg_restore -h localhost -U postgres -d 新库名 -c /backup/库名.dump-F c是自定义压缩格式,比纯SQL脚本体积小,也便于pg_restore选择性恢复。生产环境建议至少每天做一次全量备份,保留最近7天的备份文件,再用cron定时任务在凌晨自动执行。如果允许停机一小会儿,物理备份(pg_basebackup)是更完整的方案,可以配合WAL归档实现时间点恢复,那个功能更强大,这里篇幅有限不多展开。
5.4 常见问题排查与避坑经验整合
把我在这次部署中遇到的和网上反馈比较多的问题整理成一个速查表,方便直接对照排查:
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| configure阶段报错找不到zlib.h | 缺zlib-devel包 | yum install zlib-devel |
| 编译时报c compiler cannot create executables | gcc未装或版本不对 | yum install gcc make,确认gcc可用 |
| initdb报locale不存在 | 系统缺en_US.UTF8区域 | localedef -i en_US -f UTF-8 en_US.UTF-8 |
| 启动时报Permission denied | 目录权限不对 | chown postgres:postgres -R /data/pgdata |
| 启动时报could not identify version of libpq | LD_LIBRARY_PATH没有设置 | 添加export LD_LIBRARY_PATH=/usr/local/postgresql/lib:$LD_LIBRARY_PATH |
| systemd启动但是状态异常 | PIDFile路径或权限不对 | 检查postmaster.pid的属主和路径 |
| 远程连接超时 | 防火墙/kysec拦截 | 检查防火墙策略和/var/log/messages |
| 远程连接提示no pg_hba.conf entry | pg_hba.conf配置遗漏 | 按5.1节配置添加对应网段条目 |
| 提示password authentication failed | 密码错误或认证方式不匹配 | 检查pg_hba.conf用的认证方式和密码算法是否一致 |
| psql命令找不到 | PATH没有包含PG的bin目录 | 配置环境变量PATH,重新source |
| 服务器重启后数据库没起来 | systemd服务没有enable | systemctl enable postgresql |
以上每一条我都实际遇到过或验证过,按图索骥一般能解决大部分问题。如果你遇到的是表里没有的怪异错误,先看数据库日志文件,通常日志里会有明确的原因提示。我处理过太多“报错不看日志直接百度”的人了,最后绕了一圈回来发现日志里早就把原因写清楚了。学会看日志,是数据库运维的入门基本功。
6. 整体安全性补充:系统加固思路与扩展方向
6.1 ARM架构下的关键内核参数调优与内存管理
PostgreSQL在大内存机器上,有一些内核参数需要调一调,否则性能发挥不出来。编辑/etc/sysctl.conf:
kernel.shmall = 1073741824 kernel.shmmax = 274877906944 vm.overcommit_memory = 2 vm.overcommit_ratio = 90shmmax和shmall是System V共享内存的上限参数。PG的shared_buffers如果设置的比较大,就依赖这个参数。不调的话,shared_buffers设8GB可能启动报错,日志提示无法分配共享内存。
vm.overcommit_memory = 2表示系统执行严格的内存过载检查,配合vm.overcommit_ratio控制总内存分配比例。这个参数在PG社区里有一定争议,改完以后如果业务方有单独申请大内存的程序,可能被拒。我的建议:如果对Linux内存管理不够熟,只改shmmax和shmall就够了,overcommit这块保持默认,别上来就一顿乱调,反而搞出问题。
ARM架构下,还有一个特殊优化点:如果CPU支持LSE(Large System Extension)原子指令,编译时加上-march=armv8.1-a这个编译选项,可以让PostgreSQL在高并发下减少内核锁竞争,性能提升明显。但这个选项要求CPU必须支持ARMv8.1指令集,老一点的ARMv8.0芯片不支持,加了反而可能编译出非法指令。我的处理方式:先查lscpu里的Flags,看到有atomics字样就支持,加上;没有就不加,稳定优先。
6.2 升级、卸载与扩展插件的后续思路
部署完成以后,随着版本更新和业务扩展,“升级”和“卸载”这两件事早晚要遇到。这里把思路梳理一下。
PG的小版本升级很简单,下载新版源码,configure && make && make install,然后重启服务,数据目录不需要迁移。PG的小版本升级是兼容的,完全支持原地覆盖。大版本升级(比如从14升到15)要复杂一些,需要用pg_upgrade工具,这个工具要求新旧版本都装在同一台机器上,而且会锁库,需要配合业务停机窗口,操作前一定先把备份做扎实。
卸载的话,我一般不用make uninstall,因为编译安装在/usr/local/postgresql目录下非常集中,直接:
systemctl stop postgresql rm -rf /usr/local/postgresql rm -rf /data/pgdata userdel postgres干干净净,不留残余。这就是编译安装的好处,想卸就卸,不会像rpm包那样卸载时还要处理各种依赖关系。
扩展插件方面,如果你后面要装PostGIS(空间数据)、pgvector(向量检索)这类扩展,源码目录一定要保留。以pgvector为例,编译流程是:
cd /opt/pgvector-0.7.4 make PG_CONFIG=/usr/local/postgresql/bin/pg_config make install PG_CONFIG=/usr/local/postgresql/bin/pg_config因为扩展插件编译时要通过pg_config找到PostgreSQL的头文件和库文件,如果不指定PG_CONFIG路径,系统会在默认路径找,很可能找不到编译安装的PG,最后报一堆莫须有的错误。所以建议源码目录直接留在/opt下,别删。
6.3 从单机到主从复制的基本过渡方案
单机部署跑通以后,你很可能下一步会面临高可用问题——数据库挂了怎么办。这里简单说下从单机到主从复制的思路。
PG的主从复制非常简单,主库配置需要:
wal_level = replica max_wal_senders = 10 max_replication_slots = 10备库从主库做一个基础备份:
pg_basebackup -h 主库IP -p 5432 -U repuser -D /data/pgdata -F p -R然后在备库的standby.signal文件(-R参数自动生成)里就有standby_mode=on,再配置primary_conninfo指向主库IP即可。
整个过程比MySQL的主从简单不少,但需要注意两点:一是要创建专门的复制账号,不能直接用postgres超级用户;二是主从之间的网络延迟影响比较大,尽量在同一内网机房部署。
说回这次的完整部署过程。我在实际安装中最大的体会是:银河麒麟V10 ARM上的数据库部署,硬骨头不在PostgreSQL本身,而在环境适配。一旦把依赖管理、编译参数、系统服务这几个关节打通了,后面跑起来是非常稳的。我现在这套环境已经连续运行了几个月,没有出现过异常重启、数据损坏之类的问题,日常的备份、监控、慢查询日志都在正常工作。
如果你也在搞国产化环境下的数据库部署,希望这篇记录能帮你少走几个弯路。最后再分享一个习惯:每次部署完数据库,把操作系统版本、内核参数、PG版本、配置文件的关键选项都记到一个文档里。半年以后你要排查一个诡异问题,这个文档可能比搜索引擎都管用。祝顺利。