On Fri, May 28, 2010 at 11:12 AM, Fujii Masao <masao.fu...@gmail.com> wrote:
> On Thu, May 27, 2010 at 11:13 PM, Robert Haas <robertmh...@gmail.com> wrote:
>>> I guess this happens because the frequency of checkpoint on the standby is
>>> too lower than that on the master. In the master, checkpoint occurs for 
>>> every
>>> consumption of three segments because of "checkpoint_segments = 3". On the
>>> other hand, in the standby, only checkpoint_timeout has effect, so 
>>> checkpoint
>>> occurs for every 30 minutes because of "checkpoint_timeout = 30min".
>>>
>>> The walreceiver should signal the bgwriter to start checkpoint if it has
>>> received more than checkpoint_segments WAL files, like normal processing?
>>
>> Is this also an issue when using log shipping, or just with SR?
>
> When using log shipping, checkpoint_segments always doesn't trigger a
> checkpoint. So recovery after the standby crashes might take unexpectedly
> long since redo starting point might be old.
>
> But in file-based log shipping, since WAL files don't accumulate in
> pg_xlog directory on the standby, even if the frequency of checkpoint
> is very low, pg_xlog will not be filled with many WAL files. That
> accumulation occurs only when using SR.
>
> If we should avoid low frequency of checkpoint itself rather than
> accumulation of WAL files, the bgwriter instead of the walreceiver
> should check if we've consumed too much WAL, I think. Thought?

I attached the patch, which changes the startup process so that it signals
bgwriter to perform a restartpoint if we've already replayed too much WAL
files. This leads checkpoint_segments to trigger a restartpoint.

This patch is worth applying for 9.0? If not, I'll add it into the next CF.

Regards,

-- 
Fujii Masao
NIPPON TELEGRAPH AND TELEPHONE CORPORATION
NTT Open Source Software Center
*** a/src/backend/access/transam/xlog.c
--- b/src/backend/access/transam/xlog.c
***************
*** 508,513 **** static bool reachedMinRecoveryPoint = false;
--- 508,516 ----
  
  static bool InRedo = false;
  
+ /* We've already launched bgwriter to perform restartpoint? */
+ static bool bgwriterLaunched = false;
+ 
  /*
   * Information logged when we detect a change in one of the parameters
   * important for Hot Standby.
***************
*** 550,555 **** static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags);
--- 553,559 ----
  static bool XLogCheckBuffer(XLogRecData *rdata, bool doPageWrites,
  				XLogRecPtr *lsn, BkpBlock *bkpb);
  static bool AdvanceXLInsertBuffer(bool new_segment);
+ static bool XLogCheckpointNeeded(uint32 logid, uint32 logseg);
  static void XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch);
  static bool InstallXLogFileSegment(uint32 *log, uint32 *seg, char *tmppath,
  					   bool find_free, int *max_advance,
***************
*** 1554,1567 **** AdvanceXLInsertBuffer(bool new_segment)
  /*
   * Check whether we've consumed enough xlog space that a checkpoint is needed.
   *
!  * Caller must have just finished filling the open log file (so that
!  * openLogId/openLogSeg are valid).  We measure the distance from RedoRecPtr
!  * to the open log file and see if that exceeds CheckPointSegments.
   *
   * Note: it is caller's responsibility that RedoRecPtr is up-to-date.
   */
  static bool
! XLogCheckpointNeeded(void)
  {
  	/*
  	 * A straight computation of segment number could overflow 32 bits. Rather
--- 1558,1571 ----
  /*
   * Check whether we've consumed enough xlog space that a checkpoint is needed.
   *
!  * Caller must have just finished filling or reading the log file (so that
!  * the given logid/logseg are valid).  We measure the distance from RedoRecPtr
!  * to the log file and see if that exceeds CheckPointSegments.
   *
   * Note: it is caller's responsibility that RedoRecPtr is up-to-date.
   */
  static bool
! XLogCheckpointNeeded(uint32 logid, uint32 logseg)
  {
  	/*
  	 * A straight computation of segment number could overflow 32 bits. Rather
***************
*** 1577,1584 **** XLogCheckpointNeeded(void)
  	old_segno = (RedoRecPtr.xlogid % XLogSegSize) * XLogSegsPerFile +
  		(RedoRecPtr.xrecoff / XLogSegSize);
  	old_highbits = RedoRecPtr.xlogid / XLogSegSize;
! 	new_segno = (openLogId % XLogSegSize) * XLogSegsPerFile + openLogSeg;
! 	new_highbits = openLogId / XLogSegSize;
  	if (new_highbits != old_highbits ||
  		new_segno >= old_segno + (uint32) (CheckPointSegments - 1))
  		return true;
--- 1581,1588 ----
  	old_segno = (RedoRecPtr.xlogid % XLogSegSize) * XLogSegsPerFile +
  		(RedoRecPtr.xrecoff / XLogSegSize);
  	old_highbits = RedoRecPtr.xlogid / XLogSegSize;
! 	new_segno = (logid % XLogSegSize) * XLogSegsPerFile + logseg;
! 	new_highbits = logid / XLogSegSize;
  	if (new_highbits != old_highbits ||
  		new_segno >= old_segno + (uint32) (CheckPointSegments - 1))
  		return true;
***************
*** 1782,1791 **** XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
  				 * update RedoRecPtr and recheck.
  				 */
  				if (IsUnderPostmaster &&
! 					XLogCheckpointNeeded())
  				{
  					(void) GetRedoRecPtr();
! 					if (XLogCheckpointNeeded())
  						RequestCheckpoint(CHECKPOINT_CAUSE_XLOG);
  				}
  			}
--- 1786,1795 ----
  				 * update RedoRecPtr and recheck.
  				 */
  				if (IsUnderPostmaster &&
! 					XLogCheckpointNeeded(openLogId, openLogSeg))
  				{
  					(void) GetRedoRecPtr();
! 					if (XLogCheckpointNeeded(openLogId, openLogSeg))
  						RequestCheckpoint(CHECKPOINT_CAUSE_XLOG);
  				}
  			}
***************
*** 5643,5649 **** StartupXLOG(void)
  	XLogRecord *record;
  	uint32		freespace;
  	TransactionId oldestActiveXID;
- 	bool		bgwriterLaunched = false;
  
  	/*
  	 * Read control file and check XLOG status looks valid.
--- 5647,5652 ----
***************
*** 9185,9190 **** XLogPageRead(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt,
--- 9188,9207 ----
  	 */
  	if (readFile >= 0 && !XLByteInSeg(*RecPtr, readId, readSeg))
  	{
+ 		/*
+ 		 * Signal bgwriter to start a restartpoint if we've replayed too
+ 		 * much xlog since the last one.
+ 		 */
+ 		if (bgwriterLaunched)
+ 		{
+ 			if (XLogCheckpointNeeded(readId, readSeg))
+ 			{
+ 				(void) GetRedoRecPtr();
+ 				if (XLogCheckpointNeeded(readId, readSeg))
+ 					RequestCheckpoint(CHECKPOINT_CAUSE_XLOG);
+ 			}
+ 		}
+ 
  		close(readFile);
  		readFile = -1;
  		readSource = 0;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to