checkpoint-sync-pause-v1.patch

text/x-patch

Filename: checkpoint-sync-pause-v1.patch
Type: text/x-patch
Part: 0
Message: Checkpoint sync pause

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);