这篇文章主要给大家介绍了关于PostgreSQL实战之启动恢复读取checkpoint记录失败的条件的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧

1、首先读取ControlFile->checkPoint指向的checkpoint

2、如果读取失败,slave直接abort退出,master再次读取ControlFile->prevCheckPoint指向的checkpoint

StartupXLOG->
 |--checkPointLoc = ControlFile->checkPoint;
 |--record = ReadCheckpointRecord(xlogreader, checkPointLoc, 1, true):
 |-- if (record != NULL){
   ...
  }else if (StandbyMode){
   ereport(PANIC,(errmsg("could not locate a valid checkpoint record")));
  }else{
   checkPointLoc = ControlFile->prevCheckPoint;
   record = ReadCheckpointRecord(xlogreader, checkPointLoc, 2, true);
   if (record != NULL){
    InRecovery = true;//标记下面进入recovery
   }else{
    ereport(PANIC,(errmsg("could not locate a valid checkpoint record")));
   }
  }

一、那么什么条件下读取的checkpoint记录record==NULL?

1、ControlFile->checkPoint % XLOG_BLCKSZ < SizeOfXLogShortPHD
2、ReadRecord(xlogreader, ControlFile->checkPoint, LOG, true)返回NULL
3、ReadRecord读到的record!=NULL && record->xl_rmid != RM_XLOG_ID
4、ReadRecord读到的record!=NULL && info != XLOG_CHECKPOINT_SHUTDOWN && info != XLOG_CHECKPOINT_ONLINE
5、ReadRecord读到的record!=NULL && record->xl_tot_len != SizeOfXLogRecord + SizeOfXLogRecordDataHeaderShort + sizeof(CheckPoint)

二、ReadRecord函数返回NULL的条件

ReadRecord(xlogreader, ControlFile->checkPoint, LOG, true)
 |--record = XLogReadRecord(xlogreader, ControlFile->checkPoint, &errormsg);
 |-- 2.1 record==NULL && !StandbyMode
 |-- 2.2 record!=NULL && !tliInHistory(xlogreader->latestPageTLI, expectedTLEs)
 /*-----
 note:只要读取了一页xlog,就会赋值为该页第一个记录的时间线
 XLogReaderValidatePageHeader
  -->xlogreader->latestPageTLI=hdr->xlp_tli;
 ------*/

三、XlogReadRecord读取checkpoint返回NULL的条件?

XLogReadRecord(xlogreader, ControlFile->checkPoint, &errormsg)
  targetPagePtr = ControlFile->checkPoint - (ControlFile->checkPoint % XLOG_BLCKSZ);
  targetRecOff = ControlFile->checkPoint % XLOG_BLCKSZ;
  readOff = ReadPageInternal(state,targetPagePtr, Min(targetRecOff + SizeOfXLogRecord, XLOG_BLCKSZ));
  pageHeaderSize = XLogPageHeaderSize((XLogPageHeader) state->readBuf);
  record = (XLogRecord *) (state->readBuf + RecPtr % XLOG_BLCKSZ);
  total_len = record->xl_tot_len;
  -------------
  1、readOff < 0
  2、0< targetRecOff < pageHeaderSize
  3、(((XLogPageHeader) state->readBuf)->xlp_info & XLP_FIRST_IS_CONTRECORD) && targetRecOff == pageHeaderSize
page头有跨页的record并且checkpoint定位的偏移正好在页头尾部
  4、targetRecOff <= XLOG_BLCKSZ - SizeOfXLogRecord &&
!ValidXLogRecordHeader(state, ControlFile->checkPoint, state->ReadRecPtr, record,randAccess)
---(record->xl_tot_len < SizeOfXLogRecord || record->xl_rmid > RM_MAX_ID || record->xl_prev != state->ReadRecPtr)
  5、targetRecOff > XLOG_BLCKSZ - SizeOfXLogRecord && total_len < SizeOfXLogRecord
  6、total_len > state->readRecordBufSize && !allocate_recordbuf(state, total_len)
一旦该记录损坏,total_len的长度非常大的话,就需要allocate_recordbuf扩展state->readbuf,可能因此分配失败abort
记录的checksum需要等待全部读取完整记录后才校验
  -------------

三、ReadPageInternal返回的readOff返回小于0的条件

ReadPageInternal(state,targetPagePtr, Min(targetRecOff + SizeOfXLogRecord, XLOG_BLCKSZ))

  1、第一次read wal文件,readLen = state->read_page:读取第一页。readLen < 0

  2、readLen>0 && !XLogReaderValidatePageHeader(state, targetSegmentPtr, state->readBuf)
  --

  3、读取checkpoint所在页readLen = state->read_page: readLen < 0

  4、readLen > 0 && readLen <= SizeOfXLogShortPHD

  5、!XLogReaderValidatePageHeader(state, pageptr, (char *) hdr)

四、XLogPageRead何时返回值<0 ?

/*
 1、WaitForWALToBecomeAvailable open失败
 2、lseek 失败 && !StandbyMode
 3、read失败 && !StandbyMode
 4、校验page头失败 && !StandbyMode
 如果是StandbyMode,则会重新retry->WaitForWALToBecomeAvailable,切换日志源进行open
 */
 !WaitForWALToBecomeAvailable(targetPagePtr + reqLen,private->randAccess,1,targetRecPtr)//open
 |-- return -1
 readOff = targetPageOff;
 if (lseek(readFile, (off_t) readOff, SEEK_SET) < 0){
  !StandbyMode:: return -1
 }
 if (read(readFile, readBuf, XLOG_BLCKSZ) != XLOG_BLCKSZ){
  !StandbyMode:: return -1
 }
 XLogReaderValidatePageHeader(xlogreader, targetPagePtr, readBuf)
 !StandbyMode:: return -1

五、WaitForWALToBecomeAvailable何时返回false?

--XLOG_FROM_ARCHIVE | XLOG_FROM_PG_WAL
  1、先XLogFileReadAnyTLI open日志:
  1、遍历时间线列表里的每一个时间线,从最新的开始
  2、当读取checkpoint的时候,source是XLOG_FROM_ANY
  3、先找归档的日志进行open;如果open失败再找WAL日志进行open
  4、如果都没有open成功,则向前找时间线,open前一个时间线segno和文件号相同的文件进行open
  5、open成功后expectedTLEs被赋值为当前时间线列表的所有值
  2、如果open失败,则切换日志源:XLOG_FROM_ARCHIVE | XLOG_FROM_PG_WAL -> XLOG_FROM_STREAM
  3、切换日志源后,XLOG_FROM_ARCHIVE | XLOG_FROM_PG_WAL 则:
slave && promote :return false
!StandbyMode:return false
  --XLOG_FROM_STREAM
  1、!WalRcvStreaming()即receiver进程挂了,切换日志源
  2、CheckForStandbyTrigger()切换日志源
  3、XLOG_FROM_STREAM->XLOG_FROM_ARCHIVE

总结

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

最新资讯
神州租车有救了?北汽或接盘 股价一度大涨8%

神州租车有救了?北汽或

北汽集团将收购神州优车不多于4.51亿股股份,占神州租车
睡觉玩耍手动驾驶,宇航员在美国“龙”飞船上都做了什么?

睡觉玩耍手动驾驶,宇航

北京时间6月1日凌晨1点22分,搭乘美国SpaceX载人龙飞船
一季度亏损收窄,但蔚来并未走出泥潭

一季度亏损收窄,但蔚来

蔚来释放的种种信号都是想说明,蔚来正在走出泥潭,并且未
SpaceX载人航天发射成功 有望提升特斯拉电动汽车销量

SpaceX载人航天发射成

美国太空探索技术公司(SpaceX)的载人龙飞船,在当地时间5
一种蛋白质 会导致乳腺癌加快恶化

一种蛋白质 会导致乳

南澳大利亚大学5月26日发布公报说,该校研究人员发现,一
网易入场费约12727港元 在香港市值将超过200亿港元

网易入场费约12727港

不计及超额配股权,按照118.71港元计算,港股市值为203亿
最新文章
pgsql查询优化之模糊查询实例详解

pgsql查询优化之模糊

这篇文章主要给大家介绍了关于pgsql查询优化之模糊查
Ubuntu PostgreSQL安装和配置的介绍

Ubuntu PostgreSQL安

今天小编就为大家分享一篇关于Ubuntu PostgreSQL安装
PostgreSQL实现一个通用标签系统

PostgreSQL实现一个通

这篇文章主要给大家介绍了关于利用PostgreSQL实现一个
PostgreSQL中使用数组改进性能实例代码

PostgreSQL中使用数组

这篇文章主要给大家介绍了关于PostgreSQL中使用数组改
Postgresql主从异步流复制方案的深入探究

Postgresql主从异步流

这篇文章主要给大家介绍了关于Postgresql主从异步流复
PostgreSQL存储过程用法实战详解

PostgreSQL存储过程用

这篇文章主要介绍了PostgreSQL存储过程用法,结合具体