一、 前言

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. 面试造飞机系列:用心整理的HashMap面试题,以后都不用担心了
  2. rea t插件 vscode_推荐VSCode12个比较实用的插件
  3. 【Thread】- ReentrantLock、ReentrantReadWriteLock
  4. 在哪里可以找到用于读取 YML 配置文件的 Spring 文档
  5. 嵌入式实时系统程序开发一:按键程序编写
  6. java sunjce,无法初始化类javax.crypto.SunJCE_b
  7. 基于JAVA+SpringBoot+Mybatis+MYSQL的送水公司后台管理系统
  8. 破碎的互联网下,加密技术正在恢复数据主权!
  9. 蓝桥杯 ADV-201 算法提高 我们的征途是星辰大海
  10. 红旗linux mysql_请问红旗Linux下,安装Mysql时,应该下载mysql 的哪一种rpm包?谢谢
  11. 干货 | 万字长文带你复习线性代数!
  12. PHP把商品详情数据加入到商品数据,如果商品有多个详情只展示一次商品数据
  13. 数控机床通信协议汇总
  14. 文件压缩(哈夫曼树)
  15. 信息流广告如何操作?一文搞懂!
  16. Nginx出现大量499响应码怎么办?
  17. element-ui的upload 上传组件 照片墙当超过限定图片后隐藏上传按钮
  18. 今天开始弄c++,copy下人家的文章来看看参考一下哈哈
  19. 如何利用MES系统实现防错和预警?(详细整理,值得收藏)
  20. 体系解读罗克韦尔MES平台FTPC-跟我入门MES/MOM系列特别篇

热门文章

  1. html在一起100天纪念代码
  2. springboot 论坛项目
  3. vue实现粘贴截图上传图片
  4. 好不容易从流水线转码农的我又“失业”了...
  5. CRM,不止是一套软件!
  6. 解决Error:initialization failed for ‘https://start.spring.io‘‘ please check URL
  7. 迈德威视网口相机--配置及使用
  8. 双屏怎么快速切换鼠标_不让鼠标乱跑 双屏使用必备技能
  9. dw cs6 支持高分辨率
  10. ACDC:开箱即用的多租户数据集成平台