PostgreSQL pg_ctl start启动超时实例分析

一、问题

pg_ctl start启动时报错退出:pg_ctl:server did not start in time。超时时间是多少?从什么时候到哪个阶段算超时?

二、分析:该信息打印位置,从后面代码段do_start函数中可以看出

1、pg_ctl start调用start_postmaster启动PG的主进程后,每隔0.1ms检查一次postmaster.pid文件,是否已写入ready/standby

2、总共会检查600次,即从启动主进程后,最多等待60s,如果没有写入ready/standby则打印上述日志并退出

3、默认等待时间是60s,如果pg_ctl start -t指定等待时间,则等待时间为该指定时间

三、什么时候postmaster.pid文件写入ready/standby

1、如果是主机不管有没有设置hot standby

1)当startup进程恢复完成退出时,调用proc_exit函数向主进程发送SIGCHLD信号并退出

2)主进程接收到信号后,signal处理函数reaper调用AddToDataDirLockFile向postmaster.pid文件写入ready

2、如果是备机即data目录下有recovery.cnf文件,且设置了hot standby,在实际恢复前没有到达一致性位置

1)startup进程向主进程发送PMSIGNAL_RECOVERY_STARTED信号,主进程调用信号处理函数sigusr1_handler,将pmState=PM_RECOVERY

2)每次读取下一个xlog前都会调用CheckRecoveryConsistency函数进行一致性检查:

2.1 进入一致性状态,starup进程向主进程发送PMSIGNAL_BEGIN_HOT_STANDBY信号,主进程接收到信号后调用sigusr1_handler->AddToDataDirLockFile向postmaster.pid文件写入ready

3、如果是备机即data目录下有recovery.cnf文件,且设置了hot standby,在实际恢复前没有到达一致性位置

1)startup进程向主进程发送PMSIGNAL_RECOVERY_STARTED信号,主进程调用信号处理函数sigusr1_handler,将pmState=PM_RECOVERY

2)每次读取下一个xlog前都会调用CheckRecoveryConsistency函数进行一致性检查。如果没有进入一致性状态

3)本地日志恢复完成,切换日志源时同样调用CheckRecoveryConsistency函数进行一致性检查

3.1 进入一致性状态,starup进程向主进程发送PMSIGNAL_BEGIN_HOT_STANDBY信号,主进程接收到信号后调用sigusr1_handler->AddToDataDirLockFile向postmaster.pid文件写入ready

4、如果是备机即data目录下有recovery.cnf文件,且设置了hot standby,在实际恢复前到达一致性位置

1)startup进程向主进程发送PMSIGNAL_RECOVERY_STARTED信号,主进程调用信号处理函数sigusr1_handler,将pmState=PM_RECOVERY

2)CheckRecoveryConsistency函数进行一致性检查,向主进程发送PMSIGNAL_BEGIN_HOT_STANDBY信号,主进程接收到信号后调用sigusr1_handler->AddToDataDirLockFile向postmaster.pid文件写入ready

5、如果是备机即data目录下有recovery.cnf文件,没有设置hot standby

1)startup进程向主进程发送PMSIGNAL_RECOVERY_STARTED信号

2)主进程接收到信号后,向postmaster.将pmState=PM_RECOVERY

四、代码分析

1、pg_ctl start流程

do_start->
 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"));
wait_for_postmaster->
 for (i = 0; i < wait_seconds * WAITS_PER_SEC; i++){
  if ((optlines = readfile(pid_file, &numlines)) != NULL && numlines >= LOCK_FILE_LINE_PM_STATUS){
   pmpid = atol(optlines[LOCK_FILE_LINE_PID - 1]);
   pmstart = atol(optlines[LOCK_FILE_LINE_START_TIME - 1]);
   if (pmstart >= start_time - 2 && pmpid == pm_pid){
    char  *pmstatus = optlines[LOCK_FILE_LINE_PM_STATUS - 1];
    if (strcmp(pmstatus, PM_STATUS_READY) == 0 || strcmp(pmstatus, PM_STATUS_STANDBY) == 0){
     /* postmaster is done starting up */
     free_readfile(optlines);
     return POSTMASTER_READY;
    }
   }
  }
  free_readfile(optlines);
  if (waitpid((pid_t) pm_pid, &exitstatus, WNOHANG) == (pid_t) pm_pid)
   return POSTMASTER_FAILED;
  pg_usleep(USEC_PER_SEC / WAITS_PER_SEC);
 }
 /* out of patience; report that postmaster is still starting up */
 return POSTMASTER_STILL_STARTING;

2、server主进程及信号处理函数

PostmasterMain->
 pqsignal_no_restart(SIGUSR1, sigusr1_handler); /* message from child process */
 pqsignal_no_restart(SIGCHLD, reaper); /* handle child termination */
 ...
 StartupXLOG();
 ...
 proc_exit(0);//exit函数向主进程发送SIGCHLD信号
reaper->//进程终止或者停止的信号
 AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, PM_STATUS_READY);
postmaster进程接收信号:
sigusr1_handler->
 if (CheckPostmasterSignal(PMSIGNAL_RECOVERY_STARTED) &&
  pmState == PM_STARTUP && Shutdown == NoShutdown){
  CheckpointerPID = StartCheckpointer();
  BgWriterPID = StartBackgroundWriter();
  if (XLogArchivingAlways())
   PgArchPID = pgarch_start();
  //hot_standby在postgresql.conf文件中配置TRUE
  //表示在恢复的时候允许连接
  if (!EnableHotStandby){
   //将standby写入postmaster.pid文件,表示up但不允许连接
   AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, PM_STATUS_STANDBY);
  }
  pmState = PM_RECOVERY;
 }
 if (CheckPostmasterSignal(PMSIGNAL_BEGIN_HOT_STANDBY) &&
  pmState == PM_RECOVERY && Shutdown == NoShutdown){
  PgStatPID = pgstat_start();
  //将ready写入postmaster.pid文件,允许连接
  AddToDataDirLockFile(LOCK_FILE_LINE_PM_STATUS, PM_STATUS_READY);
  pmState = PM_HOT_STANDBY;
 }
 ...

3、Startup进程

StartupXLOG->
 ReadCheckpointRecord
 if (ArchiveRecoveryRequested && IsUnderPostmaster){//有recovery.conf文件则ArchiveRecoveryRequested为TRUE
  //有recovery.conf文件则ArchiveRecoveryRequested为TRUE
  PublishStartupProcessInformation();
  SetForwardFsyncRequests();
  //向master进程发送PMSIGNAL_RECOVERY_STARTED信号
  SendPostmasterSignal(PMSIGNAL_RECOVERY_STARTED);
  bgwriterLaunched = true;
 }
 CheckRecoveryConsistency();-->...
 |-- if (standbyState == STANDBY_SNAPSHOT_READY && !LocalHotStandbyActive &&
 |  reachedConsistency && IsUnderPostmaster){
 |  SpinLockAcquire(&XLogCtl->info_lck);
 |  XLogCtl->SharedHotStandbyActive = true;
 |  SpinLockRelease(&XLogCtl->info_lck);
 |  LocalHotStandbyActive = true;
 |  SendPostmasterSignal(PMSIGNAL_BEGIN_HOT_STANDBY);
 |-- }
 ...
 回放一个record后,每次读取下一个record前都会调用CheckRecoveryConsistency

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • PostgreSQL 安装和简单使用第1/2页

    据我了解国内四大国产数据库,其中三个都是基于PostgreSQL开发的.并且,因为许可证的灵活,任何人都可以以任何目的免费使用,修改,和分发 PostgreSQL,不管是私用,商用,还是学术研究使用.本文只是简单介绍一下postgresql的安装和简单的使用,语法方面涉及的比较少,以方便新手上路为目的. 1.系统环境和安装方法 : PostgreSQL的安装方法比较灵活,可以用源码包安装,也可以用您使用的发行版所带的软件包来安装,还可以采用在线安装-- 1.1 系统环境:Ubuntu Linux

  • PostgreSQL中的OID和XID 说明

    oid: 行的对象标识符(对象 ID).这个字段只有在创建表的时候使用了 WITH OIDS ,或者是设置了default_with_oids 配置参数时出现. 这个字段的类型是 oid (和字段同名). 例子: 复制代码 代码如下: CREATE TABLE pg_language ( lanname name NOT NULL, lanowner oid NOT NULL, lanispl boolean NOT NULL, lanpltrusted boolean NOT NULL, la

  • Windows PostgreSQL 安装图文教程

    它提供了多版本并行控制,支持几乎所有 SQL 构件(包括子查询,事务和用户定义类型和函数), 并且可以获得非常广阔范围的(开发)语言绑定 (包括 C,C++,Java,perl,tcl,和 python).本文介绍的是其在windows系统下的安装过程. 一般说来,一个现代的与 Unix 兼容的平台应该就能运行 PostgreSQL.而如果在windows系统下安装,你需要 Cygwin 和cygipc 包.另外,如果要制作服务器端编程语言 PL/Perl,则还需要完整的Perl安装,包括 li

  • 15个postgresql数据库实用命令分享

    最初是想找postgresql数据库占用空间命令发现的这篇blog,发现其中提供的几 条命令很有用(但也有几条感觉是充数的=.=),于是就把它翻译过来了.另外这篇文章是09年的,所以里面的内容可能有点过时,我收集了原文中有用的评论放在了最后面. 现在有不少开源软件都在使用postgreSQL作为它们的数据库系统.但公司可能不会招一些全职的postgreSQL DBA来维护它(piglei: 在国内基本也找不到).而会让一些比如说Oracle DBA.Linux系统管理员或者程序员去 维护.在这篇

  • Windows下PostgreSQL安装图解

    现在谈起免费数据库,大多数人首先想到的可能是MySQL,的确MySQL目前已经应用在国内很多领域,尤其是网站架设方面.但是,实际上功能最强大.特性最丰富和最复杂的免费数据库应该是PostgreSQL.它的很多特性正是当今许多商业数据库例如Oracle.DB2等的前身. 其实笔者最近也是因为项目需要,接触了一点PostgreSQL的皮毛,最近PostgreSQL又刚发布了8.1版本,笔者结合网上各位高手的经验谈一点自己的安装心得,和才开始接触PostgreSQL的新手朋友共同学习. 从Postgr

  • PostgreSQL新手入门教程

    自从MySQL被Oracle收购以后,PostgreSQL逐渐成为开源关系型数据库的首选. 本文介绍PostgreSQL的安装和基本用法,供初次使用者上手.以下内容基于Debian操作系统,其他操作系统实在没有精力兼顾,但是大部分内容应该普遍适用. 安装 1.首先,安装PostgreSQL客户端. sudo apt-get install postgresql-client 然后,安装PostgreSQL服务器. sudo apt-get install postgresql 2.正常情况下,安

  • Windows下Postgresql数据库的下载与配置方法

    注意下载的是二进制版,不是带Windows Installer的. http://www.enterprisedb.com/products-services-training/pgbindownload x86下载http://get.enterprisedb.com/postgresql/postgresql-9.2.4-1-windows-binaries.zip x64下载http://get.enterprisedb.com/postgresql/postgresql-9.2.4-1-

  • PostgreSQL pg_ctl start启动超时实例分析

    一.问题 pg_ctl start启动时报错退出:pg_ctl:server did not start in time.超时时间是多少?从什么时候到哪个阶段算超时? 二.分析:该信息打印位置,从后面代码段do_start函数中可以看出 1.pg_ctl start调用start_postmaster启动PG的主进程后,每隔0.1ms检查一次postmaster.pid文件,是否已写入ready/standby 2.总共会检查600次,即从启动主进程后,最多等待60s,如果没有写入ready/s

  • js超时调用setTimeout和间歇调用setInterval实例分析

    本文实例分析了js超时调用setTimeout和间歇调用setInterval的用法.分享给大家供大家参考.具体如下: 今天看了javascript高级程序设计(第三版)一书,发现说setTimeout比setInterval更好,觉得的确如此.平时都是用setInterval多点,现在还是转一下思路了.又学习到了.分析如下: setTimeout包含两个参数,第一个参数是要执行的代码,第二个参数是时间. 第一个参数可以是字符串也可以是函数,但是推荐使用函数而不是字符串. 使用字符串相当于eva

  • Java创建和启动线程的两种方式实例分析

    本文实例讲述了Java创建和启动线程的两种方式.分享给大家供大家参考,具体如下: 方式1:继承Thread类 步骤: 1):定义一个类A继承于java.lang.Thread类. 2):在A类中覆盖Thread类中的run方法. 3):我们在run方法中编写需要执行的操作:run方法里的代码,线程执行体. 4):在main方法(线程)中,创建线程对象,并启动线程. (1)创建线程类对象: A类 a = new A类(); (2)调用线程对象的start方法: a.start();//启动一个线程

  • MySQL 实例无法启动的问题分析及解决

    前言 前几天,有位朋友微信联系我,告知一个生产数据库,在机器宕机恢复后,实例启动失败,而且该实例没有做任何的高可用.容灾.备份等,对业务影响非常大,希望能够协助排查一下,我也在第一时间就加入到排查中. 场景分析 (1)首先查看错误日志,报错很清晰"Could not open log file",无法打开日志文件 2021-01-06 13:23:51 20464 [ERROR] Failed to open log (file 'something is definitely wro

  • Input系统之InputReader概要性实例分析

    目录 InputReader 的创建 EventHub 创建过程如下 InputReader 的运行 EventHub 提供事件 InputReader 的创建 从 InputManagerService: 创建与启动 可知,Input 系统的主要功能,主要集中在 native 层,并且Input 系统的 native 层又包含 InputReader, InputClassifer, InputDispatcher 三个子模块.本文来分析 InputReader 从创建到启动的基本流程,为后续

  • jQuery基础的工厂函数以及定时器的经典实例分析

    1. jQuery的基本信息: 1.1 定义: jQuery是JavaScript的程序库之一,它是JavaScript对象和实用函数的封装, 1.2 作用: 许多使用JavaScript能实现的交互特效,使用jQuery都能完美地实现,下面通过五个用途来更多的了解. 1.2.1 访问和操作DOM元素 1.2.2 制作页面样式 1.2.3 对页面时间的处理 1.2.4 方便地使用jQuery插件 1.2.5 与Ajax的完美结合 1.3 优势: 想必有人就会问了:为什么人们会更多的选择jQuer

  • Android中home键和back键区别实例分析

    本文实例分析了Android中home键和back键区别.分享给大家供大家参考.具体如下: back键 Android的程序无需刻意的去退出,当你一按下手机的back键的时候,系统会默认调用程序栈中最上层Activity的Destroy()方法来销毁当前Activity,当此Activity又被其它Activity启动起来的时候,会重新调用OnCreate()方法进行创建,当栈中所有Activity都弹出结束后,应用也就随之结束了.如果说程序中存在service之类的,则可以在恰当的位置监听处理

  • python进程与线程小结实例分析

    传统方式是调用2个方法执行1个任务,方法按顺序依次执行 # -*- coding:utf-8 -*- import threading import time def run(n): print('task',n) time.sleep(3) if __name__ == '__main__': run('t1') run('t2') 多线程例子 2个线程同时并发执行1个任务 # -*- coding:utf-8 -*- import threading import time def run(

  • Spring标准的xml文件头实例分析

    这篇文章主要介绍了Spring标准的xml文件头实例分析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 代码如下 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2

  • Python多进程与服务器并发原理及用法实例分析

    本文实例分析了Python多进程与服务器并发原理及用法.分享给大家供大家参考,具体如下: 进程 什么是进程 进程:正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 进程与程序的区别 程序仅仅只是一堆代码而已,而进程指的是程序的运行过程. 并发与并行 无论是并行还是并发,在用户看来都是'同时'运行的,不管是进程还是线程,都只是一个任务而已,真是干活的是cpu,cpu来做这些任务,而一个cpu同一时刻只能执行一个任务 一 并发:是伪并行,即看起来是同时运行.单个cpu+多道技术就可以实现

随机推荐