Postgresql - 源码 - 数据库启动

数据库启动,一个很简单的举动,只需要执行一条命令,

OS上执行的service postgresql start 或者 systemctl status postgresql.service

或是直接执行数据库启动命令

/usr/local/pgsql/bin/pg_ctl start -D ${PGDATA} -s -w -t 300 -l /usr/local/pgsql/logs/pgstartup.log

下面我们从源码中来看看数据库启动中到底做了什么操作。

1. 无论我们执行以上三种启动方式,最后都要归结到

/usr/local/pgsql/bin/pg_ctl start -D ${PGDATA} -s -w -t 300 -l /usr/local/pgsql/logs/pgstartup.log

那我们接下来就要从pg_ctl来入手。

在src/bin/pg_ctl/pg_ctl.c的main函数中,有一段代码是解析我们执行的哪个命令。

扫描二维码关注公众号,回复: 3664758 查看本文章

先从int main(){ ...... } 开始入手。

/* 先解析参数,判断参数,判断参数中是否有help 或 version */

if (argc > 1){ ...... }

/* 判断action参数,D e l m N o */

while (optind < argc)

    {

......

}

/* 判断启动参数,每一个执行的参数都是需要做什么 */

while (optind < argc)

    {

        while ((c = getopt_long(argc, argv, "cD:e:l:m:N:o:p:P:sS:t:U:wW",

                                long_options, &option_index)) != -1)

        {

            switch (c)

            {......

/* 判断参数是否为执行启动 */

else if (strcmp(argv[optind], "start") == 0)

ctl_command = START_COMMAND;

......

}

/* 定义文件夹等配置信息 */

......

pg_config = getenv("PGDATA");

adjust_data_dir();

......

switch (ctl_command)

    { ......

        case START_COMMAND:

            do_start();

            break;

......

}

2.src/bin/pg_ctl/pg_ctl.c的 do_start函数。

static void

do_start(void)

{

......

/* 判断是否存在启动的进程,如果有进程,报错。*/

    if (ctl_command != RESTART_COMMAND)

    {

        old_pid = get_pgpid(false);

        if (old_pid != 0)

            write_stderr(_("%s: another server might be running; "

                         "trying to start server anyway\n"),

                         progname);

    }

/* 读取配置 pgdata/postmaster.opts文件 */

    read_post_opts();

/* 判断是否有-D参数,表示数据文件的文件夹 */

    /* No -D or -D already added during server start */

    if (ctl_command == RESTART_COMMAND || pgdata_opt == NULL)

        pgdata_opt = "";

    if (exec_path == NULL)

        exec_path = find_other_exec_or_die(argv0, "postgres", PG_BACKEND_VERSIONSTR);

    if (exec_path == NULL)

        exec_path = find_other_exec_or_die(argv0, "postgres", PG_BACKEND_VERSIONSTR);

    /*

     * If possible, tell the postmaster our parent shell's PID (see the

     * comments in CreateLockFile() for motivation). Windows hasn't got

     * getppid() unfortunately.

     */

......

    pm_pid = start_postmaster();

/* 判断是否需要等待 */

    if (do_wait)

    {

        print_msg(_("waiting for server to start..."));

        switch (wait_for_postmaster(pm_pid, false))

        {

            case POSTMASTER_READY:

                print_msg(_(" done\n"));

                print_msg(_("server started\n"));

                break;

            case POSTMASTER_STILL_STARTING:

                print_msg(_(" stopped waiting\n"));

                write_stderr(_("%s: server did not start in time\n"),

                             progname);

                exit(1);

                break;

            case POSTMASTER_FAILED:

                print_msg(_(" stopped waiting\n"));

                write_stderr(_("%s: could not start server\n"

                             "Examine the log output.\n"),

                             progname);

                exit(1);

                break;

        }

    }

    else

/* 等待启动完成 */

        print_msg(_("server starting\n"));

......

}

3. do_start中的 start_postmaster函数

源码中对start_postmaster函数的注释信息

/*

* Start the postmaster and return its PID.

*

* Currently, on Windows what we return is the PID of the shell process

* that launched the postmaster (and, we trust, is waiting for it to exit).

* So the PID is usable for "is the postmaster still running" checks,

* but cannot be compared directly to postmaster.pid.

*

* On Windows, we also save aside a handle to the shell process in

* "postmasterProcess", which the caller should close when done with it.

*/

start_postmaster(void)

{

......

# 启动子进程

pm_pid = fork();

......

}

猜你喜欢

转载自blog.csdn.net/chuckchen1222/article/details/82843216