postgresql架构简介
postgresql是一种C/S架构,postgres server process(或称postmaster)是主进程,负责启动各个常驻进程,以及监听client端的请求,为每个client端会创建一个postgres backend process。详细介绍见下面链接。
postgresql进程和内存介绍
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初始化等等。
函数调用关系图
启动过程简要分析
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);
}
}
}