aboutsummaryrefslogtreecommitdiff
path: root/src/backend/postmaster/bgwriter.c
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2009-02-18 15:58:41 +0000
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2009-02-18 15:58:41 +0000
commitcdd46c765488a317997c266ba2bdcc85c4a95c8f (patch)
treeb4569c1908c9fd21392879c625695c973fc82130 /src/backend/postmaster/bgwriter.c
parent36a9cf38c52690b48aa61ca18c66d00ccd749204 (diff)
downloadpostgresql-cdd46c765488a317997c266ba2bdcc85c4a95c8f.tar.gz
postgresql-cdd46c765488a317997c266ba2bdcc85c4a95c8f.zip
Start background writer during archive recovery. Background writer now performs
its usual buffer cleaning duties during archive recovery, and it's responsible for performing restartpoints. This requires some changes in postmaster. When the startup process has done all the initialization and is ready to start WAL redo, it signals the postmaster to launch the background writer. The postmaster is signaled again when the point in recovery is reached where we know that the database is in consistent state. Postmaster isn't interested in that at the moment, but that's the point where we could let other backends in to perform read-only queries. The postmaster is signaled third time when the recovery has ended, so that postmaster knows that it's safe to start accepting connections. The startup process now traps SIGTERM, and performs a "clean" shutdown. If you do a fast shutdown during recovery, a shutdown restartpoint is performed, like a shutdown checkpoint, and postmaster kills the processes cleanly. You still have to continue the recovery at next startup, though. Currently, the background writer is only launched during archive recovery. We could launch it during crash recovery as well, but it seems better to keep that codepath as simple as possible, for the sake of robustness. And it couldn't do any restartpoints during crash recovery anyway, so it wouldn't be that useful. log_restartpoints is gone. Use log_checkpoints instead. This is yet to be documented. This whole operation is a pre-requisite for Hot Standby, but has some value of its own whether the hot standby patch makes 8.4 or not. Simon Riggs, with lots of modifications by me.
Diffstat (limited to 'src/backend/postmaster/bgwriter.c')
-rw-r--r--src/backend/postmaster/bgwriter.c77
1 files changed, 56 insertions, 21 deletions
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index a7377f0280f..4909fbe37a4 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/postmaster/bgwriter.c,v 1.55 2009/01/01 17:23:46 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/postmaster/bgwriter.c,v 1.56 2009/02/18 15:58:41 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -49,6 +49,7 @@
#include <unistd.h>
#include "access/xlog_internal.h"
+#include "catalog/pg_control.h"
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "pgstat.h"
@@ -423,10 +424,20 @@ BackgroundWriterMain(void)
*/
if (do_checkpoint)
{
+ bool ckpt_performed = false;
+ bool do_restartpoint;
+
/* use volatile pointer to prevent code rearrangement */
volatile BgWriterShmemStruct *bgs = BgWriterShmem;
/*
+ * Check if we should perform a checkpoint or a restartpoint.
+ * As a side-effect, RecoveryInProgress() initializes
+ * TimeLineID if it's not set yet.
+ */
+ do_restartpoint = RecoveryInProgress();
+
+ /*
* Atomically fetch the request flags to figure out what kind of a
* checkpoint we should perform, and increase the started-counter
* to acknowledge that we've started a new checkpoint.
@@ -444,7 +455,8 @@ BackgroundWriterMain(void)
* implementation will not generate warnings caused by
* CheckPointTimeout < CheckPointWarning.
*/
- if ((flags & CHECKPOINT_CAUSE_XLOG) &&
+ if (!do_restartpoint &&
+ (flags & CHECKPOINT_CAUSE_XLOG) &&
elapsed_secs < CheckPointWarning)
ereport(LOG,
(errmsg("checkpoints are occurring too frequently (%d seconds apart)",
@@ -455,14 +467,21 @@ BackgroundWriterMain(void)
* Initialize bgwriter-private variables used during checkpoint.
*/
ckpt_active = true;
- ckpt_start_recptr = GetInsertRecPtr();
+ if (!do_restartpoint)
+ ckpt_start_recptr = GetInsertRecPtr();
ckpt_start_time = now;
ckpt_cached_elapsed = 0;
/*
* Do the checkpoint.
*/
- CreateCheckPoint(flags);
+ if (!do_restartpoint)
+ {
+ CreateCheckPoint(flags);
+ ckpt_performed = true;
+ }
+ else
+ ckpt_performed = CreateRestartPoint(flags);
/*
* After any checkpoint, close all smgr files. This is so we
@@ -477,14 +496,27 @@ BackgroundWriterMain(void)
bgs->ckpt_done = bgs->ckpt_started;
SpinLockRelease(&bgs->ckpt_lck);
- ckpt_active = false;
+ if (ckpt_performed)
+ {
+ /*
+ * Note we record the checkpoint start time not end time as
+ * last_checkpoint_time. This is so that time-driven
+ * checkpoints happen at a predictable spacing.
+ */
+ last_checkpoint_time = now;
+ }
+ else
+ {
+ /*
+ * We were not able to perform the restartpoint (checkpoints
+ * throw an ERROR in case of error). Most likely because we
+ * have not received any new checkpoint WAL records since the
+ * last restartpoint. Try again in 15 s.
+ */
+ last_checkpoint_time = now - CheckPointTimeout + 15;
+ }
- /*
- * Note we record the checkpoint start time not end time as
- * last_checkpoint_time. This is so that time-driven checkpoints
- * happen at a predictable spacing.
- */
- last_checkpoint_time = now;
+ ckpt_active = false;
}
else
BgBufferSync();
@@ -507,7 +539,7 @@ CheckArchiveTimeout(void)
pg_time_t now;
pg_time_t last_time;
- if (XLogArchiveTimeout <= 0)
+ if (XLogArchiveTimeout <= 0 || RecoveryInProgress())
return;
now = (pg_time_t) time(NULL);
@@ -714,16 +746,19 @@ IsCheckpointOnSchedule(double progress)
* However, it's good enough for our purposes, we're only calculating an
* estimate anyway.
*/
- recptr = GetInsertRecPtr();
- elapsed_xlogs =
- (((double) (int32) (recptr.xlogid - ckpt_start_recptr.xlogid)) * XLogSegsPerFile +
- ((double) recptr.xrecoff - (double) ckpt_start_recptr.xrecoff) / XLogSegSize) /
- CheckPointSegments;
-
- if (progress < elapsed_xlogs)
+ if (!RecoveryInProgress())
{
- ckpt_cached_elapsed = elapsed_xlogs;
- return false;
+ recptr = GetInsertRecPtr();
+ elapsed_xlogs =
+ (((double) (int32) (recptr.xlogid - ckpt_start_recptr.xlogid)) * XLogSegsPerFile +
+ ((double) recptr.xrecoff - (double) ckpt_start_recptr.xrecoff) / XLogSegSize) /
+ CheckPointSegments;
+
+ if (progress < elapsed_xlogs)
+ {
+ ckpt_cached_elapsed = elapsed_xlogs;
+ return false;
+ }
}
/*