PG守护进程(Postmaster)——初始化GUC配置参数

  PostgreSQL系统的主要功能都集中于Postgres程序,其入口是Main模块中的main函数,在初始化数据集簇、启动数据库服务器时,都将从这里开始执行。Main模块主要的工作是确定当前的操作系统平台,并据此做一些平台相关的环境变量设置和初始化,然后通过对命令行参数的判断,将控制转到相应的模块中去。PG使用一种专用服务器进程体系结构,其中,最主要的两个进程就是守护进程Postmaster和服务进程Postgres。从本质上来说,Postmaster和Postgres都是通过载入Postgres程序而形成的进程,只是在运行时所处的分支不同而已。Postmaster在Linux和Unix系统上,仅仅是Postgres的一个符号链接。

  守护进程Postmaster负责整个系统的启动和关闭它监听并接受客户端的连接请求,为其分配服务进程Postgres。服务进程Postgres接受并执行客户端发送的命令,它在底层模块(如存储、事务管理、索引等)之上调用各个主要的功能模块(如编译器、优化器、执行器等),完成客户端的各种数据库操作,并返回执行结果。PostgreSQL守护进程Postmaster除了用户连接请求分配后台Postgres服务进程外,还将启动相关的后台辅助进程。守护进程Postmaster在完成基本运行环境初始化、创建接受用户请求的监听端口后,顺序启动如下系统辅助进程:SysLogger(系统日志进程)、PgStat(统计数据收集进程)、AutoVacuum(系统自动清理进程)。在守护进程Postmaster进入到循环监听中时启动如下进程:BgWriter(后台写进程)、WALWriter(预写式日志写进程)、PgArch(预写式日志归档进程)。

PG守护进程(Postmaster)——初始化GUC配置参数

 

 

  完成数据集簇初始化后,用户可以启动一个数据库实例来运行数据库管理系统,多用户模式下一个数据库实例由数据库服务器守护进程Postmaster来管理。它是一个运行在服务器上的总控进程,负责整个系统的启动和关闭,并且在服务进程出错时完成系统的恢复。它管理数据库文件、监听并接受来自客户端的连接请求,并且为客户端连接请求fork一个Postgres服务器,来代表客户端在数据库上执行各种命令。同时Postmaster还管理与数据库运行相关的辅助进程。用户可以使用postmaster、postgres或者pg_ctl命令启动Postmaster。使用/opt/pgsql(安装目录)/bin/postgres -D /pgdata/10/data/可以在前台运行数据库服务器,通常加上&符号可以在后台运行。PG的守护进程postmaster的入口函数注册了信号处理程序,对SIGINT、SIGTERM、SIGQUIT的处理方式分别对应PG的三种关闭方式smart、fast、immediate。因此可以使用kill命令给postgres进程发送SIGTERM、SIGINT、SIGQUIT信号停止数据库,比如kill -sigterm `head -l /pgdata/10/data/postmaster.pid`

  Postmaster负责管理整个系统范围的操作,例如中断等操作,Postmaster本身不进行折现操作,它指派一个子进程在适当的时间去处理它们。同时它要在数据库崩溃的时候重启系统。Postmaster进程在起始时会建立共享内存和信号库,Postmaster及其子进程的通信就通信就通过共享内存和信号来实现。这种多进程设计使得整个系统的稳定性更好,即使某个后台进程崩溃也不会影响系统中其他进程的工作,Postmaster只需要重置共享内存即可从单个后台进程的崩溃中恢复。

Postmaster守护进程执行流程:初始化内存上下文->初始化GUC选项->解析命令行参数并配置参数->设置连接环境->创建监听套接字->注册信号处理函数->启动子系统装载用户认证文件->循环等待用户请求,为每个请求fork后台进程。代码参照PostmasterMain函数(E:\opensource\postgresql-8.4.1\src\backend\postmaster\postmaster.c)

PostmasterMain函数

  Postmaster文件夹下面的代码主要用来创建一个服务器进程Postmaster,用来监听用户的连接请求,并fork子进程来处理客户端请求,此外还包含了用来进行统计、建立系统日志的代码。相应的代码位置在src/backend/postmaster文件夹中。包含以下文件:Postmaster进程源文件postmaster.c、统计数据收集进程的源文件pgstat.c、预写式日志归档进程的源文件pgarch.c、后台写进程的源文件bgwrite.c、系统日志进程的源文件syslogger.c和系统自动清理进程的源文件autovacuum.c。

 1 /* Postmaster main entry point */
 2 int PostmasterMain(int argc, char *argv[]) {
 3     int            opt;
 4     int            status;
 5     char       *userDoption = NULL;
 6     int            i;
 7     MyProcPid = PostmasterPid = getpid();
 8     MyStartTime = time(NULL);
 9     IsPostmasterEnvironment = true;
10     /* for security, no dir or file created can be group or other accessible */
11     umask((mode_t) 0077);
12     /* Fire up essential subsystems: memory management */
13     MemoryContextInit();
14     /* By default, palloc() requests in the postmaster will be allocated in the PostmasterContext, which is space that can be recycled by backends. Allocated data that needs to be available to backends should be allocated in TopMemoryContext. */
15     PostmasterContext =AllocSetContextCreate(TopMemoryContext,"Postmaster",
16                                               ALLOCSET_DEFAULT_MINSIZE,
17                                               ALLOCSET_DEFAULT_INITSIZE,
18                                               ALLOCSET_DEFAULT_MAXSIZE);
19     MemoryContextSwitchTo(PostmasterContext);
20     /* Initialize paths to installation files */
21     getInstallationPaths(argv[0]);

初始化内存上下文

初始化GUC选项

   GUC(Grand Unified Configuration)模块实现了多种数据类型(目前boolean、int、float、string四种)的变量配置。GucContext的项定义了参数可能会由不同进程在不同的时机进行配置的选项,系统会根据既定的优先权来确定什么情况下的配置可以生效。共有六种类型(通过枚举类型GucContext定义)并且只能在合适的环境下进行配置

  • PGC_INTERNAL:参数只能通过内部进程设定,用户不能设定
  • PGC_POSTMASTER:参数只能在Postmaster启动时通过读配置文件或处理文件或处理命令行参数来配置
  • PGC_SIGHUP:参数只能在Postmaster启动时配置,或当我们改变了配置文件并发送信号SIGHUP通知Postmaster或Postgres的时候进行配置
  • PGC_BACKEND:参数只能在Postmaster启动时读配置文件设置,或由客户端在进行连接请求时设置。已经启动的后台进程会忽略此类参数的改变
  • PGC_USERSET:可以在任何时候配置
  • PGC_SUSET:参数只能在Postmaster启动时或由超级用户通过SQL语言(SET命令)进行设置

  每种数据类型的GUC参数都由两部分组成:共性部分(config_generic)和特性部分。GUCSource枚举类型数据结构用于描述参数的来源,按照优先级从低到高的顺序排列,一个设置起作用当且仅当先前的设置优先级比当前的设置的优先级低或者相等。

 PG守护进程(Postmaster)——初始化GUC配置参数

 

 

 

Postmaster配置参数的基本过程包括:初始化GUC参数,将参数设置为默认值;配置GUC参数,根据命令行参数配置参数;读取配置文件,读配置文件重新设置参数。

初始化GUC参数

Postmaster将首先调用InitializeGUCOptions函数将参数设置为默认值:

1     /*
2      * Options setup
3      */
4     InitializeGUCOptions();

 1))首先调用build_guc_variables函数来统计参数个数并分配相应的config_generic类型的全局指针数组guc_variables以保存每个参数结构体的地址,并且对该数据进行排序。由于参数是通过全局静态数组ConfigureNamesBool、ConfigureNamesInt、ConfigureNamesReal、ConfigureNamesString、ConfigureNamesEnum存储的,因此在build_guc_variables函数中只需要遍历相应的数组,统计参数的个数并将参数结构体中config_generic域的参数vartyoe设置为相应的参数类型。当遍历完所有参数后,根据总的参数个数分配config_generic指针数组guc_vars,然后再次遍历静态参数数组,将每个参数结构的首地址保存到guc_vars数组中(这里分配的数组个数为当前参数总数的1.25倍,主要是为了方便以后参数的扩充)。接着将全局变量guc_variables也指向guc_vars数组。最后通过快速排序法把guc_variables按照参数名进行排序

 

2)接下来将每个参数设置为默认值。对于guc_variables中的每个参数,initializeGUCOptions函数先将其config_generic域中的status设置为0,将reset_source、tentative_source、source设置为PGC_S_DEFAULT表示默认;stack、sourcefile设置为NULL;然后根据参数值vartype的不同类型分别调用相应的assign_hook函数(如果该参数设置了该函数),assign_hook函数用来设置boot_val,最后将boot_val赋值给reset_val和variable指向的变量,通过这样一系列的步骤就将参数设置为了默认值。

 

3)通过系统调用getenv来获得环境变量PGPORT、PGDATESTYLE、PGCLIENTENCODING的值,不为空则调用SetConfigOption函数来设置这三个变量对应的参数的值。

 

4)最后,检测系统的最大安全栈深度,如果这个深度值大于100KB且不超过2MB,则用它设置max_stack_depth参数。

 

配置GUC参数

   如果用户启动Postmaster进程时通过命令行参数指定了一些GUC的参数值,那么Postmaster需要从命令行参数中将这些GUC参数的值解析出来并且设置到相应的GUC参数中,这一部分代码在Postmaster.c文件的509-674行中。根据命令行设置参数主要是通过getopt和SetConfigOption这两个函数来完成的。

读取配置文件

 

PG守护进程(Postmaster)——初始化GUC配置参数

上一篇:Linux vim操作


下一篇:[转]网络基本功12:细说Linux网络配置(上)