GUC介绍
在守护进程 Postmaster 初始化内存环境之后,需要配置 Postmaster 运行时所需的各种参数。GUC(Grand UnifedConfiguralion) 模块实现了多种数据类型(目前有 boolean、int、real、string、enum 五种)的变量配置。这些参数可能会由不同的进程在不同的时机进行配置,系统会根据既定的优先权来确定什么情况下的配置可以生效。
GUC 参数类型
参数共有七种类型,并且只能在合适的环境下进行配置。
typedef enum
{
PGC_INTERNAL,
PGC_POSTMASTER,
PGC_SIGHUP,
PGC_SU_BACKEND,
PGC_BACKEND,
PGC_SUSET,
PGC_USERSET
} GucContext;
const char *const GucContext_Names[] =
{
/* PGC_INTERNAL */ "internal",
/* PGC_POSTMASTER */ "postmaster",
/* PGC_SIGHUP */ "sighup",
/* PGC_SU_BACKEND */ "superuser-backend",
/* PGC_BACKEND */ "backend",
/* PGC_SUSET */ "superuser",
/* PGC_USERSET */ "user"
};
PGC_INTERNAL:参数只能通过内部进程设定,用户不能设定。
PGC_POSTMASTER:参数只能在 Postmaster 启动时通过读配置文件或处理命令行参数来配置。
PGC_SIGHUP:参数只能在 Postmaster 启动时配置,或当我们改变了配置文件并发送信号SIGHUP 通知 Postmaster 或 postgres 的时候进行配置。
PGC_SU_BACKEND:参数只能通过超级用户进行设置。
PGC_BACKEND:参数只能在 Postmaster 启动时读取文件配置,或由客户端在进行连接请求时设置。已经启动的后台进程会忽略此类参数的设定。
PGC_SUSET:参数只能在 Postmaster 启动时或由超级用户通过 SQL( SET 命令)进行设置。
PGC_USERSET:可以在任何时候设置。
GUC 生效规则
GUC 参数可能会由不同的进程在不同的时机进行配置,系统会根据既定的优先权来确定什么情况下的配置生效。源码参考如下:
typedef enum
{
PGC_S_DEFAULT, /* hard-wired default ("boot_val") */
PGC_S_DYNAMIC_DEFAULT, /* default computed during initialization */
PGC_S_ENV_VAR, /* postmaster environment variable */
PGC_S_FILE, /* postgresql.conf */
PGC_S_ARGV, /* postmaster command line */
PGC_S_GLOBAL, /* global in-database setting */
PGC_S_DATABASE, /* per-database setting */
PGC_S_USER, /* per-user setting */
PGC_S_DATABASE_USER, /* per-user-and-database setting */
PGC_S_CLIENT, /* from client connection request */
PGC_S_OVERRIDE, /* special case to forcibly set default */
PGC_S_INTERACTIVE, /* dividing line for error reporting */
PGC_S_TEST, /* test per-database or per-user setting */
PGC_S_SESSION /* SET command */
} GucSource;
通过注释可以知道这些设置参数的作用,这些参数按照优先级从低到高的顺序排列,一个设置起作用当且仅当先前的设置优先级低于或等于当前设置的优先级。
GUC 参数组成
每一种数据类型的 GUC 参数都由两部分组成:共性部分和特性部分。
共性部分的数据结构如下:
struct config_generic
{
/* constant fields, must be set correctly in initial value: */
const char *name; /* name of variable - MUST BE FIRST */
GucContext context; /* context required to set the variable */
enum config_group group; /* to help organize variables by function */
const char *short_desc; /* short desc. of this variable's purpose */
const char *long_desc; /* long desc. of this variable's purpose */
int flags; /* flag bits, see guc.h */
/* variable fields, initialized at runtime: */
enum config_type vartype; /* type of variable (set only at startup) */
int status; /* status bits, see below */
GucSource source; /* source of the current actual value */
GucSource reset_source; /* source of the reset_value */
GucContext scontext; /* context that set the current value */
GucContext reset_scontext; /* context that set the reset value */
Oid srole; /* role that set the current value */
Oid reset_srole; /* role that set the reset value */
GucStack *stack; /* stacked prior values */
void *extra; /* "extra" pointer for current actual value */
char *last_reported; /* if variable is GUC_REPORT, value last sent
* to client (NULL if not yet sent) */
char *sourcefile; /* file current setting is from (NULL if not
* set in config file) */
int sourceline; /* line in source file */
};
其中参数的数据类型 config_type 有 5 种:
/*
* GUC supports these types of variables:
*/
enum config_type
{
PGC_BOOL,
PGC_INT,
PGC_REAL,
PGC_STRING,
PGC_ENUM
};
每一种具体的数据类型参数都有其特性的数据结构,特性数据结构中的第一项都是一个指向其共性数据结构的指针。以 int 型为例:
struct config_int
{
struct config_generic gen;
/* constant fields, must be set correctly in initial value: */
int *variable;
int boot_val;
int min;
int max;
GucIntCheckHook check_hook;
GucIntAssignHook assign_hook;
GucShowHook show_hook;
/* variable fields, initialized at runtime: */
int reset_val;
void *reset_extra;
};
PG 配置 GUC 参数过程
Postmaster 配置参数的基本过程如下所示三个步骤(图取自《PostgreSQL 数据库内核分析》一书):
初始化 GUC
GUC 参数设置在调用 PostmasterMain()
启动 Postmaster 时开始进行。入口函数为 InitializeGUCOptions()
,过程如下:
InitializeGUCOptions()
----将参数设置为默认值
—>build_guc_variables()
----统计参数个数并分配相应的 config_generic 类型全局指针数组 guc_variables 保存参数结构体的地址,并对数组按参数名进行排序
—>—>InitializeOneGUCOption()
----将 guc_variables 中各项参数设置为默认值
---->---->---->InitializeGUCOptionsFromEnvironment()
----调用 getenv()
获取环境变量 PGPORT、PGDATESTYLE、PGCLIENTENCODING 的值,不为空调用 SetConfigOption()
设置其对应的参数值;
---->之后调用 get_stack_depth_rlimit()
获得系统的最大安全栈深度(若这个深度最大值大于100KB 且不超过 2MB ,则用它设置 max_stack_depth 值)
配置 GUC
如果用户启动 Postmaster 进程时通过命令行参数指定了一些 GUC 参数值,那么 Postmaster 需要从命令行参数中将这些 GUC 参数的值解析出来并且设置到相应的 GUC 参数中。
主要通过 getopt()
进行参数解析,set_config_option()
写入配置。
读取配置文件
当完成了命令行参数的设置后,接着读取配置文件重新配置参数。需要注意的是,在配置文件中设置的参数都不能修改之前通过命令行已经设置的参数,因为其优先级没有通过命令行设置的优先级高。
该过程主要是调用 SelectConfigFiles(const char *userDoption, const char *progname)
函数来实现。