Linux 环境 libpq加载异常导致psql 连接 PostgreSQL 库失败失败案例
文章目录
- 局点现象
- 定位结论
- 局点环境
- 补充知识点如下
- 库文件加载顺序
- 关键事实:
- 您系统中的证据:
- 优先级对比表:
- 解决方案强化:
- 最终检查:
- 本局点解决方法
局点现象
- 数据库 mdm 升级失败
- 检查日志, 发现是由于 psql 连接数据库报错,
psql: symbol lookup error: psql: undefined sybol : PQmblenBounded
定位结论
通常表示 psql
可执行文件所依赖的 libpq 动态库版本与编译时版本不一致或不兼容,即运行时找不到它需要的某个函数(PQmblenBounded
)。
web 界面升级, 使用的 shell 非普通 sh xxx.sh 中的shell 环境, 加载的环境变量没那么全, 局点环境中 psql 在运行过程中, 会加载系统自带的库文件缓存路径, 局点默认的缓存为
[root@localhost ~]# ldconfig -p |grep libpq.so.5libpq.so.5 (libc6,x86-64) => /usr/local/lib/libpq.so.5libpq.so.5 (libc6,x86-64) => /usr/lib64/libpq.so.5[root@localhost ~]# nm -D /usr/local/lib/libpq.so.5 | grep PQmblenBounded
[root@localhost ~]# nm -D /usr/lib64/libpq.so.5 | grep PQmblenBounded
000000000001b010 T PQmblenBounded@@RHPG_14[root@localhost ~]# nm -D /program/lib/libpq.so.5 | grep PQmblenBounded
000000000001a8c0 T PQmblenBounded
可以看到 /usr/local/lib下 与 /usr/lib64 下的 库文件中, 没有 PQmblenBounded 函数, 而 我们产品的库文件路径/program/lib 下的 libpq.so.5中是有的
局点环境
[root@localhost lxm]# ldd /program/bin/psql |grep libpqlibpq.so.5 => /program/lib/libpq.so.5 (0x00007f9a02984000)
[root@localhost lxm]#
[root@localhost lxm]# echo $LD_LIBRARY_PATH
/program/lib:/usr/local/fuse/lib:/usr/lib64:/usr/local/lib:/lib:/lib64:/driverfile/lib
[root@localhost lxm]#
[root@localhost lxm]# ldconfig -p |grep libpqlibpqwalreceiver.so (libc6,x86-64) => /usr/local/lib/libpqwalreceiver.solibpq.so.5 (libc6,x86-64) => /usr/local/lib/libpq.so.5libpq.so.5 (libc6,x86-64) => /usr/lib64/libpq.so.5
[root@localhost lxm]#
[root@localhost lxm]#
[root@localhost lxm]# /program/bin/psql -U postgres -c "\c ras; " -c "select current_database()"
You are now connected to database "ras" as user "postgres".current_database
------------------ras
(1 row)
补充知识点如下
库文件加载顺序
- LD_LIBRARY_PATH 指向的路径
- /etc/ld.so.conf.d/xxx.conf
按照字母排序 - ldconfig 缓存的标准系统路径 /lib /lib64 /usr/lib /usr/lib64 等
关键事实:
-
默认标准路径:
- 在大多数 Linux 发行版中,
/etc/ld.so.conf
文件默认包含以下路径:include /etc/ld.so.conf.d/*.conf /usr/local/lib # 这是标准本地软件安装路径 /usr/lib /lib
- 这意味着
/usr/local/lib
总是会被ldconfig
扫描并加入缓存
- 在大多数 Linux 发行版中,
-
验证方法:
# 1. 检查默认配置 cat /etc/ld.so.conf# 典型输出(RHEL/CentOS): include ld.so.conf.d/*.conf /usr/local/lib # 明确列出的标准路径 /usr/lib /lib# 2. 查看缓存中的路径 ldconfig -v | grep -A1 "search dir"
-
优先级特性:
- 由于在
/etc/ld.so.conf
中直接定义(而非通过.d
目录) - 它的加载顺序早于
/etc/ld.so.conf.d/
中的配置文件 - 因此有较高优先级
- 由于在
您系统中的证据:
[root@localhost ~]# ldconfig -p |grep libpqlibpq.so.5 (libc6,x86-64) => /usr/local/lib/libpq.so.5 # 来自标准路径libpq.so.5 (libc6,x86-64) => /usr/lib64/libpq.so.5 # 来自标准路径
优先级对比表:
路径类型 | 示例 | 优先级来源 | 典型优先级 |
---|---|---|---|
主配置文件路径 | /usr/local/lib | /etc/ld.so.conf | 最高 |
.d目录早期文件 | /etc/ld.so.conf.d/00-*.conf | 文件名排序 | 高 |
.d目录后期文件 | /etc/ld.so.conf.d/99-*.conf | 文件名排序 | 低 |
LD_LIBRARY_PATH | 任何自定义路径 | 环境变量 | 最高(但受限制) |
解决方案强化:
# 创建超高级别配置文件(00前缀)
sudo tee /etc/ld.so.conf.d/00-pg.conf <<< "/program/lib"# 重建缓存(确保新路径最先加载)
sudo ldconfig# 验证缓存顺序(/program/lib 应该在最前面)
ldconfig -p | grep libpq.so.5
最终检查:
# 查看实际加载的库
LD_DEBUG=libs psql -c "SELECT 1" 2>&1 | grep libpq.so# 预期输出:
# find library=libpq.so.5 [0]; searching
# trying file=/program/lib/libpq.so.5 # 应该先尝试这个
# trying file=/usr/local/lib/libpq.so.5 # 后尝试这个
✅ 结论:
/usr/local/lib
确实是标准路径且优先级较高,但通过创建00-pg.conf
文件,您可以强制系统优先使用/program/lib
中的新版库,完美解决符号缺失问题。
本局点解决方法
echo '/program/lib' > /etc/ld.so.conf.d/00-pg.conf && ldconfig[root@localhost ~]# cat /etc/ld.so.conf.d/00-pg.conf
/program/lib
[root@localhost ~]# ldconfig
[root@localhost ~]# ldconfig -p |grep libpqlibpqwalreceiver.so (libc6,x86-64) => /program/lib/libpqwalreceiver.solibpqwalreceiver.so (libc6,x86-64) => /usr/local/lib/libpqwalreceiver.solibpq.so.5 (libc6,x86-64) => /program/lib/libpq.so.5libpq.so.5 (libc6,x86-64) => /usr/local/lib/libpq.so.5libpq.so.5 (libc6,x86-64) => /usr/lib64/libpq.so.5libpq.so (libc6,x86-64) => /program/lib/libpq.so
[root@localhost ~]#
[root@localhost ~]# ldd /program/bin/psql |grep libpqlibpq.so.5 => /program/lib/libpq.so.5 (0x00007f5b60bfc000)
可以看到, 现在 /program/lib/libpq.so.5 位于最高优先级了