PostgreSQL 教程: 记录函数内错误的调用栈

六月 17, 2024

摘要:在本教程中,您将学习如何记录在指定函数内发生错误时的调用栈。

目录

PostgreSQL backtrace_functions 简介

backtrace_functions 选项是一个供开发人员使用的选项,它是在 PostgreSQL 13 中引入的。backtrace_functions是一个配置参数,用于指定一个内部 C 函数的列表,当这些函数调用ereport()elog()时,要为其生成调用栈信息。

您可以指定一个内部 C 函数名称的列表,以逗号进行分隔,如果服务器产生错误,并且与给定列表中的任何 C 函数匹配,则会将函数调用栈信息记录到服务器日志中。这对于调试源文件中某些特定范围的代码非常有用,尤其是在错误随机出现的时候。正如文档中还提到的,此选项并非在所有平台上都可用,调用栈信息的质量依赖于编译选项。

PostgreSQL backtrace_functions 示例

让我们来看看 PostgreSQL 调用栈的日志是什么样子。我们将尝试使用不存在的类型,来创建一个表。假设我们知道 “type does not exist” 的错误来自于源代码中的 typenameType()。因此,我们可以这样做:

SET backtrace_functions = 'typenameType';

CREATE TABLE tab (id invalidtype);
ERROR:  type "invalidtype" does not exist
LINE 1: CREATE TABLE tab (id invalidtype);

上面的语句引发了一个错误,以下是服务器日志中的一段内容:

2023-07-28 20:17:01.482 UTC [25220] ERROR:  type "invalidtype" does not exist at character 22
2023-07-28 20:17:01.482 UTC [25220] BACKTRACE:
    postgres: redrock postgres [local] CREATE TABLE(typenameType+0xa4) [0xaaaaafcd2ac4]
    postgres: redrock postgres [local] CREATE TABLE(+0x20f550) [0xaaaaafcd4550]
    postgres: redrock postgres [local] CREATE TABLE(transformCreateStmt+0x53c) [0xaaaaafcd7a10]
    postgres: redrock postgres [local] CREATE TABLE(+0x44df20) [0xaaaaaff12f20]
    postgres: redrock postgres [local] CREATE TABLE(standard_ProcessUtility+0x16c) [0xaaaaaff1225c]
    postgres: redrock postgres [local] CREATE TABLE(+0x44a4e4) [0xaaaaaff0f4e4]
    postgres: redrock postgres [local] CREATE TABLE(+0x44af88) [0xaaaaaff0ff88]
    postgres: redrock postgres [local] CREATE TABLE(PortalRun+0x198) [0xaaaaaff10ed8]
    postgres: redrock postgres [local] CREATE TABLE(+0x44764c) [0xaaaaaff0c64c]
    postgres: redrock postgres [local] CREATE TABLE(PostgresMain+0x970) [0xaaaaaff0d3d4]
    postgres: redrock postgres [local] CREATE TABLE(+0x3b3be4) [0xaaaaafe78be4]
    postgres: redrock postgres [local] CREATE TABLE(PostmasterMain+0xdc0) [0xaaaaafe79b70]
    postgres: redrock postgres [local] CREATE TABLE(main+0x480) [0xaaaaafb82510]
    /lib/aarch64-linux-gnu/libc.so.6(__libc_start_main+0xe0) [0xffffaac956e0]
    postgres: redrock postgres [local] CREATE TABLE(+0xbd5d8) [0xaaaaafb825d8]
2023-07-28 20:17:01.482 UTC [25220] STATEMENT:  CREATE TABLE tab (id invalidtype);

调用栈的每一行都有函数名称、函数的偏移地址,以及调用帧的返回地址。

对于某些调用栈帧,没有函数名称;但是,却有函数地址。这些是静态函数。对于此类函数,函数名称并没有公开出来。但是,我们还可以在 addr2line 命令行工具的帮助下,用它们的地址来获取它们的名字:

$ addr2line 0x20f550 -f -e `which postgres`
transformColumnDefinition
parse_utilcmd.c:?

在这里,选项-f用于显示函数名称以及源文件和行号,-e用于指定用来转译地址的可执行文件的名称。在输出中,没有显示行号。要获取行号和文件名,您可以在构建 PostgreSQL 时,将选项-ggdb添加到编译参数CFLAGS中。

总结

本教程讨论了 PostgreSQL 13 中引入的一项对开发人员非常有用的功能。它在帮助我们快速定位错误原因时,会非常有用,尤其对于一些随机发生的问题。