如何解决Postgres在perfcollect中的未知符号解析问题?
解决Postgres postmaster进程perfcollect栈追踪中未知符号的问题
我正在为Citus开发一款新扩展,通过在集群上运行YCSB工作负载来收集并分析该扩展、Postgres、Citus及其他依赖库的栈追踪信息,使用perfcollect收集数据、PerfView查看栈追踪结果。但在postmaster进程的追踪数据里发现大量标注为"unknown"的模块,判断是未解析的Postgres符号。
已尝试的方法:
- 通过configure添加调试标志编译Postgres:使用
--enable-debug,并设置CFLAGS = -ggdb -O0 -g,从源码全量编译 - 使用yum包管理器编译Postgres:该方式会将调试符号与可执行文件分离存储,已尝试用
eu-unstrip命令将二者合并为单个文件 - 编译带调试符号的目标扩展
以上方法均未彻底解决perfcollect中的未知符号问题。不过改用Linux原生perf工具针对Postgres特定PID收集追踪数据,再用Firefox Profiler查看时,未知模块数量大幅减少,但仍有部分符号无法解析。
可行的排查与解决方法
1. 手动指定perfcollect的符号搜索路径
perfcollect默认不会自动扫描所有符号目录,需手动指定路径确保工具能找到调试符号:
- 收集数据时添加
--symbols-path参数,指向Postgres可执行文件和调试符号的存储目录:perfcollect collect -o trace.etl --symbols-path /usr/local/pgsql/bin:/usr/local/pgsql/lib/debug - 若调试符号与可执行文件分离,可将符号目录添加到系统符号搜索配置中:修改
/etc/ld.so.conf.d/postgres-debug.conf,写入符号目录路径后执行ldconfig生效
2. 检查Postgres编译的关键参数
Postgres部分编译选项会影响符号生成与导出,需确保以下配置:
- 编译时添加
-fno-omit-frame-pointer,该参数是栈追踪的核心要求,即使O0优化也不能省略:./configure --enable-debug CFLAGS="-ggdb -O0 -g -fno-omit-frame-pointer" - 禁用符号隐藏相关选项,确保所有函数符号正常导出:添加
--disable-rpath和--enable-dependency-tracking参数 - 对于Postgres 12+版本,避免启用额外的性能优化选项(如部分定制化profiling参数),防止符号被裁剪
3. 兼容PerfView的符号解析逻辑
PerfView对Linux生成的trace解析有特定要求,可通过以下方式适配:
- 先用原生
perf验证符号是否可解析:将trace转换为文本格式查看
若原生perf script -i trace.etl > trace.txtperf能正常解析但PerfView不行,尝试:- 更新PerfView到最新版本,旧版本对Linux符号支持不完善
- 用
perf report生成报告后导出为JSON格式,再导入PerfView绕过直接解析环节
4. 验证运行中进程的符号有效性
直接检查postmaster进程的符号表,确认符号本身生成正常:
- 用
nm查看可执行文件的导出符号:nm -D /usr/local/pgsql/bin/postmaster | grep -E "(T|t)" - 用
gdb附加到postmaster进程,检查符号是否可被识别:
若上述工具能正常列出函数,说明符号本身有效,问题出在perfcollect的解析配置gdb -p <postmaster-pid> (gdb) info functions
5. 处理动态库的符号缺失
Citus及系统依赖库的符号也可能导致"unknown"模块,需同步检查:
- 编译Citus时添加同样的调试参数:
CFLAGS="-ggdb -O0 -fno-omit-frame-pointer",禁用符号隐藏 - 安装系统依赖库的调试符号包,如
glibc-debuginfo、pthread-debuginfo等(根据发行版选择对应包名) - 用
ldd查看postmaster依赖的动态库路径,确保这些路径下的库都有对应的调试符号文件
内容的提问来源于stack exchange,提问作者unujjwal
相关产品推荐
相关产品推荐

