一、 前言

PostgreSQL standby 可以通过两种方法来激活成为主库:

  • trigger file:配置在recovery.conf中。
  • pg_ctl promote:发送SIGUSR1信号给postmaster进程。

同时,PostgreSQL支持快速激活(fast promote)和非快速激活(fallback promote):

  • fast promote:开启数据库读写前不需要做检查点,而是推到开启读写之后执行一个CHECKPOINT_FORCE检查点。
  • fallback_promote:在开启数据库读写前需要先做一个检查点,现在这个模式已经不对用户开放,只是用作调试。

二、 实现分析

激活过程,根据fast_promote变量判断是否需要先做检查点,再激活。

src/backend/access/transam/xlog.cif (InRecovery) // 当前为Recovery模式{if (bgwriterLaunched){if (fast_promote)  // 如果是快速promote,在打开数据库读写前,不需要创建检查点。只需要创建一个recovery结束标记{checkPointLoc = ControlFile->prevCheckPoint;record = ReadCheckpointRecord(xlogreader, checkPointLoc, 1, false);if (record != NULL){fast_promoted = true;CreateEndOfRecoveryRecord();}}if (!fast_promoted)  //  如果是fallback_promote模式,须先创建一个检查点,再开启读写模式。RequestCheckpoint(CHECKPOINT_END_OF_RECOVERY |CHECKPOINT_IMMEDIATE |CHECKPOINT_WAIT);}
...InRecovery = false;    //  开启读写模式,允许接收用户写请求.LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);ControlFile->state = DB_IN_PRODUCTION;   //  改写控制文件的数据库状态ControlFile->time = (pg_time_t) time(NULL);UpdateControlFile();   //  更新控制文件LWLockRelease(ControlFileLock);...if (fast_promoted)   //  如果是快速promote,在允许用户写请求后,在这里执行一个检查点。所以提高了数据库的可用时间。RequestCheckpoint(CHECKPOINT_FORCE);
......

通过pg_ctl命令行工具,向postmaster发SIGUSR1信号,通知它激活数据库。 首先会写一个promote文件,告诉postmaster,是fast_promote模式。

src/bin/pg_ctl/pg_ctl.c
/** promote*/static void
do_promote(void)
{FILE       *prmfile;pgpid_t         pid;struct stat statbuf;pid = get_pgpid(false);......sig = SIGUSR1;if (kill((pid_t) pid, sig) != 0)  // 发送SIGUSR1信号,通知postmaster激活数据库。{write_stderr(_("%s: could not send promote signal (PID: %ld): %s\n"),progname, pid, strerror(errno));if (unlink(promote_file) != 0)write_stderr(_("%s: could not remove promote signal file \"%s\": %s\n"),progname, promote_file, strerror(errno));exit(1);}print_msg(_("server promoting\n"));
}

数据恢复时,检查standby是否收到promote请求或是否存在trigger文件。 如果是promote请求,则检查有没有promote文件,或者fallback_promote文件。如果有promote文件,则是fast_promote请求;如果有fallback_promote文件,则不是fast_promote请求(实际上根本不可能检测到fallback_promote文件,因为没有写这个文件的操作)。所以通过pg_ctl promote来激活,一定是fast promote的,即不需要先做检查点再激活。 如果检查到trigger文件,同样也是fast promote激活模式。

src/backend/access/transam/xlog.c
#define PROMOTE_SIGNAL_FILE             "promote"
#define FALLBACK_PROMOTE_SIGNAL_FILE "fallback_promote"/** Check to see whether the user-specified trigger file exists and whether a* promote request has arrived.  If either condition holds, return true.*/
static bool
CheckForStandbyTrigger(void)
{struct stat stat_buf;static bool triggered = false;if (triggered)return true;if (IsPromoteTriggered())   // 检查是否收到pg_ctl promote信号{
......if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)    // 先检查promote文件是否存在{unlink(PROMOTE_SIGNAL_FILE);unlink(FALLBACK_PROMOTE_SIGNAL_FILE);fast_promote = true;    //  快速promote}else if (stat(FALLBACK_PROMOTE_SIGNAL_FILE, &stat_buf) == 0)  // 否则再检查fallback_promote文件是否存在{unlink(FALLBACK_PROMOTE_SIGNAL_FILE);fast_promote = false;    //  先执行checkpoint再promote}ereport(LOG, (errmsg("received promote request")));ResetPromoteTriggered();triggered = true;return true;}if (TriggerFile == NULL)   //  检查recovery.conf是否配置了trigger_filereturn false;if (stat(TriggerFile, &stat_buf) == 0){ereport(LOG,(errmsg("trigger file found: %s", TriggerFile)));unlink(TriggerFile);triggered = true;fast_promote = true;    //   快速promotereturn true;}else if (errno != ENOENT)ereport(ERROR,(errcode_for_file_access(),errmsg("could not stat trigger file \"%s\": %m",TriggerFile)));return false;
}src/backend/postmaster/startup.cpqsignal(SIGUSR2, StartupProcTriggerHandler);  // 注册SIGUSR2信号处理函数/* SIGUSR2: set flag to finish recovery */
static void
StartupProcTriggerHandler(SIGNAL_ARGS)
{int                     save_errno = errno;promote_triggered = true;WakeupRecovery();errno = save_errno;
}bool
IsPromoteTriggered(void)
{return promote_triggered;
}

postmaster收到SIGUSER1信号后,检查是否收到promote信号,判断当前的状态是否处于恢复中的任意状态,然后向startup进程发一个SIGUSR2的信号,触发promote。

src/backend/postmaster/postmaster.cpqsignal(SIGUSR1, sigusr1_handler); /* message from child process */  // 注册SIGUSR1信号处理函数/** sigusr1_handler - handle signal conditions from child processes*/
static void
sigusr1_handler(SIGNAL_ARGS)
{
......if (CheckPromoteSignal() && StartupPID != 0 &&(pmState == PM_STARTUP || pmState == PM_RECOVERY ||pmState == PM_HOT_STANDBY || pmState == PM_WAIT_READONLY)){/* Tell startup process to finish recovery */signal_child(StartupPID, SIGUSR2);  //  向startup进程发SIGUSR2信号,通知它处理promote}
......src/backend/access/transam/xlog.c
/** Check to see if a promote request has arrived. Should be* called by postmaster after receiving SIGUSR1.*/
bool
CheckPromoteSignal(void)
{struct stat stat_buf;if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0 ||stat(FALLBACK_PROMOTE_SIGNAL_FILE, &stat_buf) == 0)return true;return false;
}

最后提一点, 9.3以前,曾经出现过pg_ctl promote -m 来指定是否需要fast promote或者fallback promote。

pg主从复制(二)——备库激活过程分析相关推荐

  1. DG 主库fial over,强制激活备库解决案例

    14年1月份的时候,因硬件环境的变更,需要把库从原来的存储平台移到新的存储平台.也就是把数据库的底层存储介质更换一下.下面主要记录一下事故的发生及应对措施. 事情概况 win平台,11R2,64位,单 ...

  2. postgres主备库切换测试

    主备库切换常用的有两种方式,第一种是使用触发文件,9.0之前的版本只能使用此种方式切换,第二个是使用命令promote的方式. 切换之前需要查看主备库的角色,查看角色的方式可以参考: https:// ...

  3. PostgreSQL 之 流复制主备库切换

    作者:瀚高PG实验室 (Highgo PG Lab)- 波罗 在主从复制的两个节点中,当主节点数据库服务访问异常的时候后,可以手动通过promote 命令在从节点执行将从节点状态切换到可读写的状态,变 ...

  4. Oracle 11g Data Guard 之逻辑备库角色转换

    逻辑备库不复制数据库服务,在进行switchover或者failover时,连接主库服务的中间层将不能连接(因为服务的创建没有被复制),或者连接不正确的版本(因为服务属性的修改没有被复制). Orac ...

  5. 【DG】基于同一个主机建立物理备库和逻辑备库 (四)--添加一个物理dg节点

    [DATAGUARD] 基于同一个主机建立物理备库和逻辑备库 (四)--添加一个物理dg节点 BLOG文档结构图 [DATAGUARD] 基于同一个主机建立物理备库和逻辑备库(一): http://b ...

  6. oracle主备库sync模式,Oracle 探索DG备库undo工作模式

    模拟备库出现 ORA-01555 分析备库 undo 工作模式 一: 修改主库 备库 undo 表空间 1.在主库创建undo表空间(会自动同步到备库) SYS@prod>create undo ...

  7. Oracle Dataguard 主备库的切换方法

    主备库的切换主要在两种情况下切换,Switchover和Failover,这两种切换都需要手工执行完成. 一是Switchover(计划中的切换,不会丢失数据) 二是Failover(当主库出现故障的 ...

  8. Oracle 11g Dataguard 物理备库配置(一)之Duplicate配置

    Oracle 11g Dataguard Duplicate物理备库配置(一)之物理备库创建配置 # ver:1.5 第五次修改 # modify: 2013.8.16 # author: koumm ...

  9. oracle dataguard in-memory,Oracle 11g Dataguard 物理备库配置(一)之Duplicate配置

    Oracle 11g Dataguard Duplicate物理备库配置(一)之物理备库创建配置 # ver:1.5 第五次修改 # modify: 2013.8.16 # author: koumm ...

最新文章

  1. WCF 4.0 进阶系列 – 第十二章 实现单向操作和异步操作(下)
  2. 寻求最佳开发模式,免得落得“精”尽人亡
  3. docker运行python程序_如何使用Docker运行多个Python脚本和一个可执行文件?
  4. SI4463模块配合WDS的快速上手指南
  5. ASP.NET中的OutOfMemoryException
  6. rhel5.4下编译安装python2..6.6 + mod_python
  7. 点击高德地图标注没法弹窗_如何在地图上标注我的店铺
  8. 使用Typescript开发(二)
  9. python中的写入文件
  10. python爬虫之一:爬取网页小说(魂破九天)
  11. MAC Safari 浏览器自动重启,活动监视器闪退,CPU过高导致风扇嗡嗡响
  12. 【vue】【开源】vue开源电商项目hello-mall嗨喽商城
  13. 各大AI研究院共35场NLP算法岗面经奉上
  14. 微信小程序获取openid失败
  15. 大海行船靠舵手,北森用海量数据记录中国领导力的五年跃迁
  16. coreldraw x8段落_CorelDRAWx8调整字间距的方法
  17. 李开复给中国大学生的第四封信—大学四年应是这样度过
  18. linux文件夹介绍
  19. 【PM 产品】产品经理的思维方式
  20. ⑩【图神经网络×自监督×时空】视频自监督学习、时间对比图学习、多尺度时间依赖性(长期、短期) 、频域学习

热门文章

  1. listview,你不知道的事(后面附有listview的焦点问题)
  2. 交房不验等于毁房!详细总结验房16项 别等开发商跑了才醒悟!
  3. 【推荐】10本黑客入门必看的书籍
  4. 从《蜗居》看失衡的中国城市化
  5. 如何选择合适的自动化测试工具?
  6. 首都机场计算机笔试题目,首都机场笔试感想
  7. 连接器插针插孔接触不良该如何检测呢?
  8. Mac视频播放器Elmedia Video Player Pro for Mac
  9. 12.集成学习进阶一——xgboost
  10. IPv6有哪些优势?