postgresql 在流复制模式下,WAL发生以下错误的对处方法

postgresql在流复制模式(stream)时,slave侧log出现以下错误:

record with zero length at XXX

FATAL:terminating walreceiver process due to administrator command

错误

xlog.c      
       
4069      
       
 else if (record->xl_len == 0)   
 {     
  ereport(emode_for_corrupt_record(emode, *RecPtr),
    (errmsg("record with zero length at %X/%X",
      RecPtr->xlogid, RecPtr->xrecoff)));
  goto next_record_is_invalid;  
 }     
       
       
       
next_record_is_invalid:    
 failedSources |= readSource;   
       
 if (readFile >= 0)    
 {     
  close(readFile);   
  readFile = -1;   
 }     
       
 /*     
  * If archive recovery was requested, but we were still doing crash
  * recovery, switch to archive recovery and retry using the offline
  * archive. We have now replayed all the valid WAL in pg_xlog, so
  * we are presumably now consistent.  
  *     
  * We require that there's at least some valid WAL present in
  * pg_xlog, however (!fetch_ckpt). We could recover using the WAL
  * from the archive, even if pg_xlog is completely empty, but we'd
  * have no idea how far we'd have to replay to reach consistency.
  * So err on the safe side and give up.  
  */     
 if (!InArchiveRecovery && ArchiveRecoveryRequested && !fetching_ckpt)
 {     
  ereport(DEBUG1,   
    (errmsg_internal("reached end of WAL in pg_xlog, entering archive recovery")));
  InArchiveRecovery = true;  
  if (StandbyModeRequested)  
   StandbyMode = true; 
       
  /* initialize minRecoveryPoint to this record */
  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
  ControlFile->state = DB_IN_ARCHIVE_RECOVERY;
  if (XLByteLT(ControlFile->minRecoveryPoint, EndRecPtr))
   ControlFile->minRecoveryPoint = EndRecPtr;
       
  /* update local copy */  
  minRecoveryPoint = ControlFile->minRecoveryPoint;
       
  UpdateControlFile();  
  LWLockRelease(ControlFileLock); 
       
  CheckRecoveryConsistency();  
       
  goto retry;   
 }     
       
       
 retry:     
 /* See if we need to retrieve more data */ 
 if (readFile < 0 ||    
  (readSource == XLOG_FROM_STREAM && !XLByteLT(*RecPtr, receivedUpto)))
 {     
  if (StandbyMode)   
  {    
   /*   
    * In standby mode, wait for the requested record to become
    * available, either via restore_command succeeding to restore the
    * segment, or via walreceiver having streamed the record.
    */   
   for (;;)   
   {   
    if (WalRcvInProgress())
    {  
     bool 
       
     /* 
      * If we find an invalid record in the WAL streamed from
      * master, something is seriously wrong. There's little
      * chance that the problem will just go away, but PANIC is
      * not good for availability either, especially in hot
      * standby mode. Disconnect, and retry from
      * archive/pg_xlog again. The WAL in the archive should be
      * identical to what was streamed, so it's unlikely that
      * it helps, but one can hope...
      */ 
     if (failedSources & XLOG_FROM_STREAM)
     { 
      ShutdownWalRcv();
      continue;
     } 
       
     /* 
      * Walreceiver is active, so see if new data has arrived.
      * 
      * We only advance XLogReceiptTime when we obtain fresh
      * WAL from walreceiver and observe that we had already
      * processed everything before the most recent "chunk"
      * that it flushed to disk.  In steady state where we are
      * keeping up with the incoming data, XLogReceiptTime will
      * be updated on each cycle.  When we are behind,
      * XLogReceiptTime will not advance, so the grace time
      * alloted to conflicting queries will decrease.
      */ 
     if (XLByteLT(*RecPtr, receivedUpto))
      havedata = true;
     else 
     { 
      XLogRecPtr
       
      receivedUpto = GetWalRcvWriteRecPtr(&latestChunkStart);
      if (XLByteLT(*RecPtr, receivedUpto))
      {
       
       
       
       
       
       
      }
      else
       
     } 
     if (havedata)
     { 
      /*
       * Great, streamed far enough. Open the file if it's
       * not open already.  Use XLOG_FROM_STREAM so that
       * source info is set correctly and XLogReceiptTime
       * isn't changed.
       */
      if (readFile < 0)
      {
       
       
       
       
       
       
      }
      else
      {
       
       
       
      }
      break;
     } 
       
     /* 
      * Data not here yet, so check for trigger then sleep for
      * five seconds like in the WAL file polling case below.
      */ 
     if (CheckForStandbyTrigger())
      goto retry;
       
     /* 
      * Wait for more WAL to arrive, or timeout to be reached
      */ 
     WaitLatch(&XLogCtl->recoveryWakeupLatch,
       
       
     ResetLatch(&XLogCtl->recoveryWakeupLatch);
    }  
    else  
    {  
     int 
     pg_time_tnow;
       
     /* 
      * Until walreceiver manages to reconnect, poll the
      * archive.
      */ 
     if (readFile >= 0)
     { 
      close(readFile);
      readFile = -1;
     } 
     /* Reset curFileTLI if random fetch. */
     if (randAccess)
      curFileTLI = 0;
       
     /* 
      * Try to restore the file from archive, or read an
      * existing file from pg_xlog.
      */ 
     sources = XLOG_FROM_ARCHIVE | XLOG_FROM_PG_XLOG;
     if (!(sources & ~failedSources))
     { 
      /*
       * We've exhausted all options for retrieving the
       * file. Retry.
       */
      failedSources = 0;
       
      /*
       * Before we sleep, re-scan for possible new timelines
       * if we were requested to recover to the latest
       * timeline.
       */
      if (recoveryTargetIsLatest)
      {
       
       
      }
       
      /*
       * If it hasn't been long since last attempt, sleep to
       * avoid busy-waiting.
       */
      now = (pg_time_t) time(NULL);
      if ((now - last_fail_time) < 5)
      {
       
       
      }
      last_fail_time = now;
       
      /*
       * If primary_conninfo is set, launch walreceiver to
       * try to stream the missing WAL, before retrying to
       * restore from archive/pg_xlog.
       *
       * If fetching_ckpt is TRUE, RecPtr points to the
       * initial checkpoint location. In that case, we use
       * RedoStartLSN as the streaming start position
       * instead of RecPtr, so that when we later jump
       * backwards to start redo at RedoStartLSN, we will
       * have the logs streamed already.
       */
      if (PrimaryConnInfo)
      {
       
       
       
       
      }
     } 
     /* Don't try to read from a source that just failed */
     sources &= ~failedSources;
     readFile = XLogFileReadAnyTLI(readId, readSeg, DEBUG2,
       
     switched_segment = true;
     if (readFile >= 0)
      break;
       
     /* 
      * Nope, not found in archive and/or pg_xlog.
      */ 
     failedSources |= sources;
       
     /* 
      * Check to see if the trigger file exists. Note that we
      * do this only after failure, so when you create the
      * trigger file, we still finish replaying as much as we
      * can from archive and pg_xlog before failover.
      */ 
     if (CheckForStandbyTrigger())
      goto triggered;
    }  
       
    /*  
     * This possibly-long loop needs to handle interrupts of
     * startup process. 
     */  
    HandleStartupProcInterrupts();
   }   
  }    
  else    
  {    
   /* In archive or crash recovery. */
   if (readFile < 0)  
   {   
    int  
       
    /* Reset curFileTLI if random fetch. */
    if (randAccess) 
     curFileTLI = 0;
       
    sources = XLOG_FROM_PG_XLOG;
    if (InArchiveRecovery)
     sources |= XLOG_FROM_ARCHIVE;
       
    readFile = XLogFileReadAnyTLI(readId, readSeg, emode,
       
    switched_segment = true;
    if (readFile < 0) 
     return false;
   }   
  }    
 }     
       
 /*     
  * At this point, we have the right segment open and if we're streaming we
  * know the requested record is in it.  
  */     
 Assert(readFile != -1);   
       
 /*     
  * If the current segment is being streamed from master, calculate how
  * much of the current page we have received already. We know the
  * requested record has been received, but this is for the benefit of
  * future calls, to allow quick exit at the top of this function.
  */     
 if (readSource == XLOG_FROM_STREAM)  
 {     
  if (RecPtr->xlogid != receivedUpto.xlogid ||
   (RecPtr->xrecoff / XLOG_BLCKSZ) != (receivedUpto.xrecoff / XLOG_BLCKSZ))
  {    
   readLen = XLOG_BLCKSZ; 
  }    
  else    
   readLen = receivedUpto.xrecoff % XLogSegSize - targetPageOff;
 }     
 else     
  readLen = XLOG_BLCKSZ;  
       
 if (switched_segment && targetPageOff != 0) 
 {     
  /*    
   * Whenever switching to a new WAL segment, we read the first page of
   * the file and validate its header, even if that's not where the
   * target record is.  This is so that we can check the additional
   * identification info that is present in the first page's "long"
   * header.   
   */    
  readOff = 0;   
  if (read(readFile, readBuf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
  {    
   ereport(emode_for_corrupt_record(emode, *RecPtr),
     (errcode_for_file_access(),
      errmsg("could not read from log file %u, segment %u, offset %u: %m",
       
   goto next_record_is_invalid; 
  }    
  if (!ValidXLOGHeader((XLogPageHeader) readBuf, emode, true))
   goto next_record_is_invalid; 
 }     
       
 /* Read the requested page */   
 readOff = targetPageOff;   
 if (lseek(readFile, (off_t) readOff, SEEK_SET) < 0) 
 {     
  ereport(emode_for_corrupt_record(emode, *RecPtr),
    (errcode_for_file_access(),
   errmsg("could not seek in log file %u, segment %u to offset %u: %m",
    readId, readSeg, readOff)));
  goto next_record_is_invalid;  
 }     
 if (read(readFile, readBuf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
 {     
  ereport(emode_for_corrupt_record(emode, *RecPtr),
    (errcode_for_file_access(),
   errmsg("could not read from log file %u, segment %u, offset %u: %m",
    readId, readSeg, readOff)));
  goto next_record_is_invalid;  
 }     
 if (!ValidXLOGHeader((XLogPageHeader) readBuf, emode, false))
  goto next_record_is_invalid;  
       
 Assert(targetId == readId);   
 Assert(targetSeg == readSeg);   
 Assert(targetPageOff == readOff);  
 Assert(targetRecOff < readLen);  
       
 return true;    
       
next_record_is_invalid:    
 failedSources |= readSource;   
       
 if (readFile >= 0)    
  close(readFile);   
 readFile = -1;    
 readLen = 0;    
 readSource = 0;    
       
 /* In standby-mode, keep trying */  
 if (StandbyMode)    
  goto retry;   
 else     
  return false;   
       
triggered:     
 if (readFile >= 0)    
  close(readFile);   
 readFile = -1;    
 readLen = 0;    
 readSource = 0;    
       
 return false;    
}      
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值