第六十二章. pg_options

注意:Massimo Dal Zotto 提供
参数文件 data/pg_options 包含被后端用于控制跟踪信息和其他可调节参数的运行时选项.当后端收到一个 SIGHUP 信号后会重新读取这个文件的信息.这就让我们可以更改 Postgres 的运行时参数而不需要重新启动它.在这个文件中声明的选项可能是被追踪包使用的调试标志 (backend/utils/misc/trace.c)或者是后端用于控制其特性的一些数字参数.新的选项和参数必须在backend/utils/misc/trace.cbackend/include/utils/trace.h 里定义.

例如,假设我们想在文件 foo.c 里加入一个条件跟踪信息和一个可调节的数字参数.我们所要做的是向文件 backend/include/utils/trace.h 里增加常量 TRACE_FOO 和 OPT_FOO_PARAM:

/* file trace.h */
enum pg_option_enum {
    ...
    TRACE_FOO,                  /* trace foo functions */
    OPT_FOO_PARAM,              /* foo tunable parameter */

    NUM_PG_OPTIONS              /* must be the last item of enum */
};
和文件 backend/utils/misc/trace.c 里对应的行:
/* file trace.c */
static char *opt_names[] = {
    ...
    "foo",                      /* trace foo functions */
    "fooparam"                  /* foo tunable parameter */
};
两个文件里的选项必须严格地按相同顺序排列.在源文件 foo 里我们现在可以用下面的代码代表新的标志:
/* file foo.c */
#include "trace.h"
#define foo_param pg_options[OPT_FOO_PARAM]

int
foo_function(int x, int y)
{
    TPRINTF(TRACE_FOO, "entering foo_function, foo_param=%d", foo_param);
    if (foo_param > 10) {
        do_more_foo(x, y);
    }
}
现有的要使用私有跟踪标志的文件只须加入下面代码就完成了修改:
#include "trace.h"
/* int my_own_flag = 0; -- removed */
#define my_own_flag pg_options[OPT_MY_OWN_FLAG]
在后端启动的时候所有 pg_options 都初始化为零.如果我们需要一个不同的初始值,我们必须在 PostgresMain 开头的地方增加一些初始化代码.现在我们可以设置 foo_param 参数并且可以通过向文件 data/pg_options 里写数值来打开 foo 追踪:
# file pg_options
...
foo=1
fooparam=17
新的选项将被所有新启动的后端读取.要令选项的更改对所有正在运行的后端都起做用,我们要向postmaster 发送一个 SIGHUP 信号.该信号将自动发送给所有后端.我们也可以通过给指定的后端发送 SIGHUUP 信号的方法来让更改只对某个后端生效.

pg_options 同样可以使用 Postgres 的 -T 开关:

postgres options -T "verbose=2,query,hostlookup-"
这样,用于打印错误和调试信息的函数就可以利用 syslog(2) 功能了.向标准输出(stdout)或标准错误(stderr)打印的信息是带有时标和后端进程号前缀的字串:
#timestamp          #pid    #message
980127.17:52:14.173 [29271] StartTransactionCommand
980127.17:52:14.174 [29271] ProcessUtility: drop table t;
980127.17:52:14.186 [29271] SIIncNumEntries: table is 70% full
980127.17:52:14.186 [29286] Async_NotifyHandler
980127.17:52:14.186 [29286] Waking up sleeping backend process
980127.19:52:14.292 [29286] Async_NotifyFrontEnd
980127.19:52:14.413 [29286] Async_NotifyFrontEnd done
980127.19:52:14.466 [29286] Async_NotifyHandler done
这种格式改善了日志的可读性并且让人们可以弄明白某后端何时在做何事.同样这也让我们很容易写出简单的监控日志的 awk 或 perl 脚本来跟踪数据库错误或问题,或者计算交易时间统计数据.

向 syslog (系统日志)打印的信息使用了日志工具 LOG_LOCAL0.syslog的使用可以由 syslog 的 pg_option 控制.不幸的是,许多函数调用直接用 printf() 把它们的信息输出到标准输出(stdout)或标准错误(stderr)中去了,这样的输出不能重定向到 syslog 而且也不会有时标.我们的建议是所有对printf的调用都用宏 PRINTF 代替,所有向标准错误(stderr)的输出都用 EPRINTF 替换,这样我们就可以将所有输出都控制在统一的方法下.

使用新 pg_options 的机制比定义新的后端开关的方法更方便是因为:

pg_options 文件的格式如下:
# comment
option=integer_value  # set value for option
option                # set option = 1
option+               # set option = 1
option-               # set option = 0
注意 keyword 可以是定义在 backend/utils/misc/trace.c 里的选项名的缩写.

请参考管理员手册中关于运行时选项的章节获取目前支持的选项的完整列表。

有一些现在正使用私有变量和选项开关的代码已经修改为利用 pg_options 特性了,主要是在 postgres.c 里.我们建议可以把所有现存的代码都改成这样,所以我们可以去掉很多 Postgres 命令行上的开关而且我们可以有更容易调节的选项 --这些选项都是在同一个位置存放的.