checkpoint-sync-pause-v1.patch
text/x-patch
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| src/backend/postmaster/checkpointer.c | 72 | 0 |
| src/backend/storage/smgr/md.c | 2 | 0 |
| src/backend/utils/misc/guc.c | 10 | 0 |
| src/backend/utils/misc/postgresql.conf.sample | 1 | 0 |
| src/include/access/xlog.h | 1 | 0 |
| src/include/postmaster/bgwriter.h | 2 | 0 |
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 0b792d2..54da69a 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -142,6 +142,7 @@ static BgWriterShmemStruct *BgWriterShmem;
int CheckPointTimeout = 300;
int CheckPointWarning = 30;
double CheckPointCompletionTarget = 0.5;
+int CheckPointSyncPause = 0;
/*
* Flags set by interrupt handlers for later service in the main loop.
@@ -157,6 +158,8 @@ static bool am_checkpointer = false;
static bool ckpt_active = false;
+static int checkpoint_flags = 0;
+
/* these values are valid when ckpt_active is true: */
static pg_time_t ckpt_start_time;
static XLogRecPtr ckpt_start_recptr;
@@ -643,6 +646,9 @@ CheckpointWriteDelay(int flags, double progress)
if (!am_checkpointer)
return;
+ /* Cache this value for a later sync delay */
+ checkpoint_flags=flags;
+
/*
* Perform the usual duties and take a nap, unless we're behind
* schedule, in which case we just try to catch up as quickly as possible.
@@ -685,6 +691,72 @@ CheckpointWriteDelay(int flags, double progress)
}
/*
+ * CheckpointSyncDelay -- control rate of checkpoint sync stage
+ *
+ * This function is called after each relation sync performed by mdsync().
+ * It delays for a fixed period while still making sure to absorb
+ * incoming fsync requests.
+ *
+ * Due to where this is called with the md layer, it's not practical
+ * for it to be directly passed the checkpoint flags. It's expected
+ * they will have been stashed within the checkpointer's local state
+ * by a call to CheckpointWriteDelay.
+ *
+ */
+void
+CheckpointSyncDelay()
+{
+ static int absorb_counter = WRITES_PER_ABSORB;
+ int sync_delay_secs = CheckPointSyncPause;
+
+ /* Do nothing if checkpoint is being executed by non-checkpointer process */
+ if (!am_checkpointer)
+ return;
+
+ /*
+ * Perform the usual duties and take a nap if there's time left
+ */
+ while (!(checkpoint_flags & CHECKPOINT_IMMEDIATE) &&
+ !shutdown_requested &&
+ !ImmediateCheckpointRequested() &&
+ (sync_delay_secs > 0))
+ {
+ elog(DEBUG2,"checkpoint sync delay: seconds left=%d",sync_delay_secs);
+ if (got_SIGHUP)
+ {
+ got_SIGHUP = false;
+ ProcessConfigFile(PGC_SIGHUP);
+ /* update global shmem state for sync rep */
+ SyncRepUpdateSyncStandbysDefined();
+ }
+
+ AbsorbFsyncRequests();
+ absorb_counter = WRITES_PER_ABSORB;
+
+ CheckArchiveTimeout();
+
+ /*
+ * Checkpoint sleep used to be connected to bgwriter_delay at 200ms.
+ * That resulted in more frequent wakeups if not much work to do.
+ * Checkpointer and bgwriter are no longer related so take the Big Sleep.
+ */
+ pg_usleep(100000L);
+ sync_delay_secs--;
+ }
+
+ if (--absorb_counter <= 0)
+ {
+ /*
+ * Absorb pending fsync requests after each WRITES_PER_ABSORB write
+ * operations even when we don't sleep, to prevent overflow of the
+ * fsync request queue.
+ */
+ AbsorbFsyncRequests();
+ absorb_counter = WRITES_PER_ABSORB;
+ }
+}
+
+/*
* IsCheckpointOnSchedule -- are we on schedule to finish this checkpoint
* in time?
*
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index bfc9f06..dd63535 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -1047,6 +1047,8 @@ mdsync(void)
absorb_counter = FSYNCS_PER_ABSORB;
}
+ CheckpointSyncDelay();
+
/*
* The fsync table could contain requests to fsync segments that
* have been deleted (unlinked) by the time we get to them. Rather
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 5c910dd..6c856c1 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1975,6 +1975,16 @@ static struct config_int ConfigureNamesInt[] =
},
{
+ {"checkpoint_sync_pause", PGC_SIGHUP, WAL_CHECKPOINTS,
+ gettext_noop("Inserts a delay after each checkpoint file sync operation"),
+ NULL
+ },
+ &CheckPointSyncPause,
+ 0, 0, INT_MAX,
+ NULL, NULL, NULL
+ },
+
+ {
{"wal_buffers", PGC_POSTMASTER, WAL_SETTINGS,
gettext_noop("Sets the number of disk-page buffers in shared memory for WAL."),
NULL,
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 315db46..5fc6476 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -180,6 +180,7 @@
#checkpoint_timeout = 5min # range 30s-1h
#checkpoint_completion_target = 0.5 # checkpoint target duration, 0.0 - 1.0
#checkpoint_warning = 30s # 0 disables
+#checkpoint_sync_pause = 0 # in seconds
# - Archiving -
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 1ddf4bf..1736ba6 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -186,6 +186,7 @@ extern bool reachedConsistency;
/* these variables are GUC parameters related to XLOG */
extern int CheckPointSegments;
+extern int CheckPointSyncPause;
extern int wal_keep_segments;
extern int XLOGbuffers;
extern int XLogArchiveTimeout;
diff --git a/src/include/postmaster/bgwriter.h b/src/include/postmaster/bgwriter.h
index 6cc4b62..4d57b4a 100644
--- a/src/include/postmaster/bgwriter.h
+++ b/src/include/postmaster/bgwriter.h
@@ -21,12 +21,14 @@ extern int BgWriterDelay;
extern int CheckPointTimeout;
extern int CheckPointWarning;
extern double CheckPointCompletionTarget;
+extern int CheckPointSyncPause;
extern void BackgroundWriterMain(void);
extern void CheckpointerMain(void);
extern void RequestCheckpoint(int flags);
extern void CheckpointWriteDelay(int flags, double progress);
+extern void CheckpointSyncDelay();
extern bool ForwardFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum,
BlockNumber segno);