postgresql 启动分析

postgresql架构简介

postgresql是一种C/S架构,postgres server process(或称postmaster)是主进程,负责启动各个常驻进程,以及监听client端的请求,为每个client端会创建一个postgres backend process。详细介绍见下面链接。
postgresql进程和内存介绍

image.png

postgresql进程例

postgresql/10371的进程,postmaster是postgres server process。logger/10372,checkpointer/10374等是常驻后台进程。mydb [local] idle/17300是client端对应的backend process。

\# pstree -pa 10371
postmaster,10371 -D /usr/local/pgsql/data4
  |-10372,postgres: logger
  |-10374,postgres: checkpointer
  |-10375,postgres: background writer
  |-10376,postgres: walwriter
  |-10377,postgres: autovacuum launcher
  |-10378,postgres: stats collector
  |-10379,postgres: logical replication launcher
  |-17300,postgres: postgres mydb [local] idle
  `-18542,postgres: postgres mydb [local] idle

在psql中可以获取其backend process的pid17300

mydb=# select pg_backend_pid();
-[ RECORD 1 ]--+------
pg_backend_pid | 17300

启动过程简介

下面分析postgresql的启动过程,大体流程为postmaster启动,启动常驻进程,进入主循环,监听client的请求。其中还包含配置文件读取,全局设置,信号处理函数注册,share memory初始化等等。

函数调用关系图

image

启动过程简要分析

postmaster主入口
PostmasterMain
  // 解析command-line options
  // 比如-o 选项的option,暂存于ExtraOptions
  while ((opt = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:W:-:")) != -1)
  {
    case 'o':
      snprintf(ExtraOptions + strlen(ExtraOptions),
         sizeof(ExtraOptions) - strlen(ExtraOptions)," %s", optarg);
   }
   
  // load 配置文件,postgresql.conf
  SelectConfigFiles
  // share memory init
  reset_shared
  // 对clientsocket开始listen
  // socket保存在ListenSocket[MAXLISTEN]
  StreamServerPort
  // load pg_hba.conf
  load_hba
  // ???待分析
  StartupDataBase
  // postmaster的主循环
  ServerLoop
postmaster主循环
ServerLoop
  // 检查,处理socket,详细见下面 "socket处理"部分
  // log collector 检查,启动
  SysLogger_Start
  // walwriter 检查,启动
  StartWalWriter
  // autovacuum launcher 检查,启动
  StartAutoVacLauncher
  // stats collector 检查,启动
  pgstat_start
  // archiver 检查,启动
  pgarch_start
  // WAL receiver 检查,启动
  MaybeStartWalReceiver
  // other worker processes 检查,启动
  maybe_start_bgworkers
socket处理
// 初始化fd_set readmask
nSockets = initMasks(&readmask);
select(nSockets, &rmask, NULL, NULL, &timeout);
for (i = 0; i < MAXLISTEN; i++)
{
    if (ListenSocket[i] == PGINVALID_SOCKET)
        break;

    // socket有数据
    if (FD_ISSET(ListenSocket[i], &rmask))
    {
        Port       *port;

        // 创建连接,accept
        port = ConnCreate(ListenSocket[i]);
        if (port)
        {
            // 创建backend process
            BackendStartup(port);
            // postmaster中关闭socket
            StreamClose(port->sock);
            ConnFree(port);
        }
    }
}

你可能感兴趣的:(postgresql源码分析)