数据库执行查询计划详细代码分析

本文通过详述查询调用的函数栈,从main到PostgresMain,直至exec_simple_query,深入剖析了数据库执行查询的过程,为理解大数据环境下的数据库操作提供了宝贵洞察。
摘要由CSDN通过智能技术生成

 

查询调用的函数栈:
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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值