@@ -2221,13 +2221,18 @@ CalculateCheckpointSegments(void)
22212221 * Calculate the distance at which to trigger a checkpoint, to avoid
22222222 * exceeding max_wal_size_mb. This is based on two assumptions:
22232223 *
2224- * a) we keep WAL for two checkpoint cycles, back to the "prev" checkpoint.
2224+ * a) we keep WAL for only one checkpoint cycle (prior to PG11 we kept
2225+ * WAL for two checkpoint cycles to allow us to recover from the
2226+ * secondary checkpoint if the first checkpoint failed, though we
2227+ * only did this on the master anyway, not on standby. Keeping just
2228+ * one checkpoint simplifies processing and reduces disk space in
2229+ * many smaller databases.)
22252230 * b) during checkpoint, we consume checkpoint_completion_target *
22262231 * number of segments consumed between checkpoints.
22272232 *-------
22282233 */
22292234target = (double )ConvertToXSegs (max_wal_size_mb ,wal_segment_size ) /
2230- (2 .0+ CheckPointCompletionTarget );
2235+ (1 .0+ CheckPointCompletionTarget );
22312236
22322237/* round down */
22332238CheckPointSegments = (int )target ;
@@ -2279,23 +2284,8 @@ XLOGfileslop(XLogRecPtr PriorRedoPtr)
22792284 * To estimate where the next checkpoint will finish, assume that the
22802285 * system runs steadily consuming CheckPointDistanceEstimate bytes between
22812286 * every checkpoint.
2282- *
2283- * The reason this calculation is done from the prior checkpoint, not the
2284- * one that just finished, is that this behaves better if some checkpoint
2285- * cycles are abnormally short, like if you perform a manual checkpoint
2286- * right after a timed one. The manual checkpoint will make almost a full
2287- * cycle's worth of WAL segments available for recycling, because the
2288- * segments from the prior's prior, fully-sized checkpoint cycle are no
2289- * longer needed. However, the next checkpoint will make only few segments
2290- * available for recycling, the ones generated between the timed
2291- * checkpoint and the manual one right after that. If at the manual
2292- * checkpoint we only retained enough segments to get us to the next timed
2293- * one, and removed the rest, then at the next checkpoint we would not
2294- * have enough segments around for recycling, to get us to the checkpoint
2295- * after that. Basing the calculations on the distance from the prior redo
2296- * pointer largely fixes that problem.
2297- */
2298- distance = (2.0 + CheckPointCompletionTarget )* CheckPointDistanceEstimate ;
2287+ */
2288+ distance = (1.0 + CheckPointCompletionTarget )* CheckPointDistanceEstimate ;
22992289/* add 10% for good measure. */
23002290distance *=1.10 ;
23012291
@@ -6593,30 +6583,17 @@ StartupXLOG(void)
65936583(errmsg ("checkpoint record is at %X/%X" ,
65946584(uint32 ) (checkPointLoc >>32 ), (uint32 )checkPointLoc )));
65956585}
6596- else if ( StandbyMode )
6586+ else
65976587{
65986588/*
6599- * The last valid checkpoint record required for a streaming
6600- * recovery exists in neither standby nor the primary.
6589+ * We used to attempt to go back to a secondary checkpoint
6590+ * record here, but only when not in standby_mode. We now
6591+ * just fail if we can't read the last checkpoint because
6592+ * this allows us to simplify processing around checkpoints.
66016593 */
66026594ereport (PANIC ,
66036595(errmsg ("could not locate a valid checkpoint record" )));
66046596}
6605- else
6606- {
6607- checkPointLoc = ControlFile -> prevCheckPoint ;
6608- record = ReadCheckpointRecord (xlogreader ,checkPointLoc ,2 , true);
6609- if (record != NULL )
6610- {
6611- ereport (LOG ,
6612- (errmsg ("using previous checkpoint record at %X/%X" ,
6613- (uint32 ) (checkPointLoc >>32 ), (uint32 )checkPointLoc )));
6614- InRecovery = true;/* force recovery even if SHUTDOWNED */
6615- }
6616- else
6617- ereport (PANIC ,
6618- (errmsg ("could not locate a valid checkpoint record" )));
6619- }
66206597memcpy (& checkPoint ,XLogRecGetData (xlogreader ),sizeof (CheckPoint ));
66216598wasShutdown = ((record -> xl_info & ~XLR_INFO_MASK )== XLOG_CHECKPOINT_SHUTDOWN );
66226599}
@@ -6845,7 +6822,6 @@ StartupXLOG(void)
68456822recoveryTargetTLI )));
68466823ControlFile -> state = DB_IN_CRASH_RECOVERY ;
68476824}
6848- ControlFile -> prevCheckPoint = ControlFile -> checkPoint ;
68496825ControlFile -> checkPoint = checkPointLoc ;
68506826ControlFile -> checkPointCopy = checkPoint ;
68516827if (InArchiveRecovery )
@@ -7619,12 +7595,11 @@ StartupXLOG(void)
76197595{
76207596if (fast_promote )
76217597{
7622- checkPointLoc = ControlFile -> prevCheckPoint ;
7598+ checkPointLoc = ControlFile -> checkPoint ;
76237599
76247600/*
76257601 * Confirm the last checkpoint is available for us to recover
7626- * from if we fail. Note that we don't check for the secondary
7627- * checkpoint since that isn't available in most base backups.
7602+ * from if we fail.
76287603 */
76297604record = ReadCheckpointRecord (xlogreader ,checkPointLoc ,1 , false);
76307605if (record != NULL )
@@ -8090,7 +8065,7 @@ LocalSetXLogInsertAllowed(void)
80908065 * Subroutine to try to fetch and validate a prior checkpoint record.
80918066 *
80928067 * whichChkpt identifies the checkpoint (merely for reporting purposes).
8093- * 1 for "primary",2 for "secondary", 0 for "other" (backup_label)
8068+ * 1 for "primary", 0 for "other" (backup_label)
80948069 */
80958070static XLogRecord *
80968071ReadCheckpointRecord (XLogReaderState * xlogreader ,XLogRecPtr RecPtr ,
@@ -8110,10 +8085,6 @@ ReadCheckpointRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr,
81108085ereport (LOG ,
81118086(errmsg ("invalid primary checkpoint link in control file" )));
81128087break ;
8113- case 2 :
8114- ereport (LOG ,
8115- (errmsg ("invalid secondary checkpoint link in control file" )));
8116- break ;
81178088default :
81188089ereport (LOG ,
81198090(errmsg ("invalid checkpoint link in backup_label file" )));
@@ -8135,10 +8106,6 @@ ReadCheckpointRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr,
81358106ereport (LOG ,
81368107(errmsg ("invalid primary checkpoint record" )));
81378108break ;
8138- case 2 :
8139- ereport (LOG ,
8140- (errmsg ("invalid secondary checkpoint record" )));
8141- break ;
81428109default :
81438110ereport (LOG ,
81448111(errmsg ("invalid checkpoint record" )));
@@ -8154,10 +8121,6 @@ ReadCheckpointRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr,
81548121ereport (LOG ,
81558122(errmsg ("invalid resource manager ID in primary checkpoint record" )));
81568123break ;
8157- case 2 :
8158- ereport (LOG ,
8159- (errmsg ("invalid resource manager ID in secondary checkpoint record" )));
8160- break ;
81618124default :
81628125ereport (LOG ,
81638126(errmsg ("invalid resource manager ID in checkpoint record" )));
@@ -8175,10 +8138,6 @@ ReadCheckpointRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr,
81758138ereport (LOG ,
81768139(errmsg ("invalid xl_info in primary checkpoint record" )));
81778140break ;
8178- case 2 :
8179- ereport (LOG ,
8180- (errmsg ("invalid xl_info in secondary checkpoint record" )));
8181- break ;
81828141default :
81838142ereport (LOG ,
81848143(errmsg ("invalid xl_info in checkpoint record" )));
@@ -8194,10 +8153,6 @@ ReadCheckpointRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr,
81948153ereport (LOG ,
81958154(errmsg ("invalid length of primary checkpoint record" )));
81968155break ;
8197- case 2 :
8198- ereport (LOG ,
8199- (errmsg ("invalid length of secondary checkpoint record" )));
8200- break ;
82018156default :
82028157ereport (LOG ,
82038158(errmsg ("invalid length of checkpoint record" )));
@@ -8933,8 +8888,7 @@ CreateCheckPoint(int flags)
89338888(errmsg ("concurrent write-ahead log activity while database system is shutting down" )));
89348889
89358890/*
8936- * Remember the prior checkpoint's redo pointer, used later to determine
8937- * the point where the log can be truncated.
8891+ * Remember the prior checkpoint's redo ptr for UpdateCheckPointDistanceEstimate()
89388892 */
89398893PriorRedoPtr = ControlFile -> checkPointCopy .redo ;
89408894
@@ -8944,7 +8898,6 @@ CreateCheckPoint(int flags)
89448898LWLockAcquire (ControlFileLock ,LW_EXCLUSIVE );
89458899if (shutdown )
89468900ControlFile -> state = DB_SHUTDOWNED ;
8947- ControlFile -> prevCheckPoint = ControlFile -> checkPoint ;
89488901ControlFile -> checkPoint = ProcLastRecPtr ;
89498902ControlFile -> checkPointCopy = checkPoint ;
89508903ControlFile -> time = (pg_time_t )time (NULL );
@@ -8982,8 +8935,7 @@ CreateCheckPoint(int flags)
89828935smgrpostckpt ();
89838936
89848937/*
8985- * Delete old log files (those no longer needed even for previous
8986- * checkpoint or the standbys in XLOG streaming).
8938+ * Delete old log files and recycle them
89878939 */
89888940if (PriorRedoPtr != InvalidXLogRecPtr )
89898941{
@@ -8992,7 +8944,8 @@ CreateCheckPoint(int flags)
89928944/* Update the average distance between checkpoints. */
89938945UpdateCheckPointDistanceEstimate (RedoRecPtr - PriorRedoPtr );
89948946
8995- XLByteToSeg (PriorRedoPtr ,_logSegNo ,wal_segment_size );
8947+ /* Trim from the last checkpoint, not the last - 1 */
8948+ XLByteToSeg (RedoRecPtr ,_logSegNo ,wal_segment_size );
89968949KeepLogSeg (recptr ,& _logSegNo );
89978950_logSegNo -- ;
89988951RemoveOldXlogFiles (_logSegNo ,PriorRedoPtr ,recptr );
@@ -9258,8 +9211,7 @@ CreateRestartPoint(int flags)
92589211CheckPointGuts (lastCheckPoint .redo ,flags );
92599212
92609213/*
9261- * Remember the prior checkpoint's redo pointer, used later to determine
9262- * the point at which we can truncate the log.
9214+ * Remember the prior checkpoint's redo ptr for UpdateCheckPointDistanceEstimate()
92639215 */
92649216PriorRedoPtr = ControlFile -> checkPointCopy .redo ;
92659217
@@ -9273,7 +9225,6 @@ CreateRestartPoint(int flags)
92739225if (ControlFile -> state == DB_IN_ARCHIVE_RECOVERY &&
92749226ControlFile -> checkPointCopy .redo < lastCheckPoint .redo )
92759227{
9276- ControlFile -> prevCheckPoint = ControlFile -> checkPoint ;
92779228ControlFile -> checkPoint = lastCheckPointRecPtr ;
92789229ControlFile -> checkPointCopy = lastCheckPoint ;
92799230ControlFile -> time = (pg_time_t )time (NULL );