查询调用的函数栈:
main()->PostmasterMain()->ServerLoop()->BackendStartup()->BackendRun()->PostgresMain()->exec_simple_query()→
其中的postgresmain函数的分析进入下:
//postgres主循环--所有后端,交互或者其他从这里开始
//postgres服务进程
void
PostgresMain(int argc, char *argv[],
const char *dbname,
const char *username)
{
int firstchar; //临时变量,读取输入command
StringInfoData input_message; //字符串增强结构体
sigjmp_buf local_sigjmp_buf; //系统变量
volatile bool send_ready_for_query = true;
MemoryAccountIdType postgresMainMemoryAccountId = MEMORY_OWNER_TYPE_Undefined;
/*
* CDB: Catch program error signals.//捕获程序错误信息
* Save our main thread-id for comparison during signals.//保存我们的主线程id,以便在信号期间进行比较
*/
//获取自身线程的id
main_tid = pthread_self();
/*
* Initialize globals (already done if under postmaster, but not if
* standalone).
*初始化全局变量
*/
if (!IsUnderPostmaster)
{
MyProcPid = getpid();
MyStartTime = time(NULL);
srandom((unsigned int) (MyProcPid ^ MyStartTime));
}
#ifndef WIN32
PostmasterPriority = getpriority(PRIO_PROCESS, 0);
#endif
postgresMainMemoryAccountId = MemoryAccounting_CreateAccount(0, MEMORY_OWNER_TYPE_MainEntry);
MemoryAccounting_SwitchAccount(postgresMainMemoryAccountId);
set_ps_display("startup", false);
SetProcessingMode(InitProcessing);//设置进程状态为InitProcessing
/* Compute paths, if we didn't inherit them from postmaster */
//计算路径、如果我们没有从postmaster继承他们
if (my_exec_path[0] == '\0')
{
if (find_my_exec(argv[0], my_exec_path) < 0)
elog(FATAL, "%s: could not locate my own executable path",
argv[0]);
}
if (pkglib_path[0] == '\0')
get_pkglib_path(my_exec_path, pkglib_path);
/*
* Set default values for command-line options.
*为命令行选项设置默认值
*/
EchoQuery = false;
if (!IsUnderPostmaster)
InitializeGUCOptions();//初始化GUC参数
/*
*解析命令行选项
* Parse command-line options.
*/
process_postgres_switches(argc, argv, PGC_POSTMASTER, &dbname);//解析输入参数
/*
* Must have gotten a database name, or have a default (the username)
* 必须有一个数据库名、或者有一个默认的用户名
*/
if (dbname == NULL)//输入的dbname为空
{
dbname = username;//设置为用户名
if (dbname == NULL)//如果仍为空,则报错
ereport(FATAL,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("%s: no database nor user name specified",
progname)));
}
/*
* Acquire configuration parameters, unless inherited from postmaster
* 获取配置参数,除非从postmaster继承
*/
if (!IsUnderPostmaster)
{
if (!SelectConfigFiles(userDoption, progname))//读取配置文件conf/hba文件&定位数据数目
proc_exit(1);
/*
* Remember stand-alone backend startup time.
* CDB: Moved this up from below for use in error message headers.
*记住独立后端的启动时间
*CDB:将它从下面移动到错误信息头中使用
*/
PgStartTime = GetCurrentTimestamp();
}
/*
* Set up signal handlers and masks.//设置信号处理器和masks
*/
if (am_walsender)//判断是否wal sender进程
WalSndSignals();//如果是,则调用walsandsignals
else//不是wal sender进程
{
pqsignal(SIGHUP, PostgresSigHupHandler); /* set flag to read config
* file */
pqsignal(SIGINT, StatementCancelHandler); /* cancel current query */
pqsignal(SIGTERM, die); /* cancel current query and exit */
if (IsUnderPostmaster)
pqsignal(SIGQUIT, quickdie); /* hard crash time */
else
pqsignal(SIGQUIT, die); /* cancel current query and exit */
InitializeTimeouts(); /* establishes SIGALRM handler */
pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, SIG_IGN);
pqsignal(SIGFPE, FloatExceptionHandler);
pqsignal(SIGCHLD, SIG_DFL); /* system() requires this on some
* platforms */
#ifndef _WIN32
#ifdef SIGILL
pqsignal(SIGILL, CdbProgramErrorHandler);
#endif
#ifdef SIGSEGV
pqsignal(SIGSEGV, CdbProgramErrorHandler);
#endif
#ifdef SIGBUS
pqsignal(SIGBUS, CdbProgramErrorHandler);
#endif
#endif
}
pqinitmask();//初始化BlockSig、UnBlockSig和StartupBlockSig
if (IsUnderPostmaster)
{
/* We allow SIGQUIT (quickdie) at all times */
sigdelset(&BlockSig, SIGQUIT);
}
PG_SETMASK(&BlockSig); /* block everything except SIGQUIT */
if (!IsUnderPostmaster)
{
/*
* Validate we have been given a reasonable-looking DataDir (if under
* postmaster, assume postmaster did this already).
*/
Assert(DataDir);
ValidatePgVersion(DataDir);
/* Change into DataDir (if under postmaster, was done already) */
ChangeToDataDir();//切换至数据库路径,使用chdir命令
/*
* Create lockfile for data directory.
*/
CreateDataDirLockFile(false);//创建锁定文件
lizeMaxBackends();
}
/* Early initialization //早期的初始化
*/
BaseInit();//基础的初始化
#ifdef EXEC_BACKEND
if (!IsUnderPostmaster)
InitProcess();
#else
InitProcess();
#endif
/* We need to allow SIGINT, etc during the initial transaction */
PG_SETMASK(&UnBlockSig);
PG_SETMASK(&UnBlockSig);
ereport(DEBUG3,
(errmsg_internal("InitPostgres")));
InitPostgres(dbname, InvalidOid, username, NULL);
if (PostmasterContext)
{
MemoryContextDelete(PostmasterContext);
PostmasterContext = NULL;
}
SetProcessingMode(NormalProcessing);//完成初始化后,设置进程模式为NormalProcessing
BeginReportingGUCOptions();//report GUC
if (IsUnderPostmaster && Log_disconnections)
on_proc_exit(log_disconnections, 0);
if (am_walsender)
InitWalSender();//初始化WAL sender process
/*
*处理任何在后端启动时应该加载的库,
*在GUC设置完成前不能做
*/
process_session_preload_libraries();//加载LIB
/*
*DA要求在开始就清除这些
*/
DtxContextInfo_Reset(&QEDtxContextInfo);
/*
* 将后台的取消信息发送给前台
*/
if (whereToSendOutput == DestRemote &&
PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
{
StringInfoData buf;
pq_beginmessage(&buf, 'K');
pq_sendint(&buf, (int32) MyProcPid, sizeof(int32));
pq_sendint(&buf, (int32) MyCancelKey, sizeof(int32));
pq_endmessage(&buf);
/* Need not flush since ReadyForQuery will do it. *///不需要刷新,因为ReadyForQuery会这样做
}
/* Also send GPDB QE-backend startup info (motion listener, version). *///也发送GPDB的后端启动信息
if (!(am_ftshandler || IsFaultHandler) && Gp_role == GP_ROLE_EXECUTE)