summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xlog.c64
-rw-r--r--src/backend/commands/dbcommands.c14
-rw-r--r--src/backend/commands/tablespace.c2
-rw-r--r--src/backend/parser/gram.y7
-rw-r--r--src/backend/postmaster/checkpointer.c77
-rw-r--r--src/backend/replication/slot.c32
-rw-r--r--src/backend/storage/buffer/bufmgr.c10
-rw-r--r--src/backend/tcop/utility.c12
-rw-r--r--src/backend/utils/misc/guc_tables.c4
-rw-r--r--src/bin/pg_upgrade/server.c18
-rw-r--r--src/bin/psql/tab-complete.in.c16
-rw-r--r--src/include/access/xlog.h5
-rw-r--r--src/include/nodes/parsenodes.h1
-rw-r--r--src/include/postmaster/bgwriter.h2
-rw-r--r--src/include/utils/guc_hooks.h4
-rw-r--r--src/test/perl/PostgreSQL/Test/Utils.pm1
-rw-r--r--src/test/recovery/t/041_checkpoint_at_promote.pl2
-rw-r--r--src/test/regress/expected/stats.out15
-rw-r--r--src/test/regress/sql/stats.sql9
19 files changed, 158 insertions, 137 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index a8cc6402d62..88fb9b45b2a 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2347,25 +2347,6 @@ check_wal_segment_size(int *newval, void **extra, GucSource source)
}
/*
- * GUC check_hook for max_slot_wal_keep_size
- *
- * We don't allow the value of max_slot_wal_keep_size other than -1 during the
- * binary upgrade. See start_postmaster() in pg_upgrade for more details.
- */
-bool
-check_max_slot_wal_keep_size(int *newval, void **extra, GucSource source)
-{
- if (IsBinaryUpgrade && *newval != -1)
- {
- GUC_check_errdetail("\"%s\" must be set to -1 during binary upgrade mode.",
- "max_slot_wal_keep_size");
- return false;
- }
-
- return true;
-}
-
-/*
* At a checkpoint, how many WAL segments to recycle as preallocated future
* XLOG segments? Returns the highest segment that should be preallocated.
*/
@@ -6505,7 +6486,7 @@ PerformRecoveryXLogAction(void)
else
{
RequestCheckpoint(CHECKPOINT_END_OF_RECOVERY |
- CHECKPOINT_IMMEDIATE |
+ CHECKPOINT_FAST |
CHECKPOINT_WAIT);
}
@@ -6814,7 +6795,7 @@ ShutdownXLOG(int code, Datum arg)
WalSndWaitStopping();
if (RecoveryInProgress())
- CreateRestartPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE);
+ CreateRestartPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_FAST);
else
{
/*
@@ -6826,7 +6807,7 @@ ShutdownXLOG(int code, Datum arg)
if (XLogArchivingActive())
RequestXLogSwitch(false);
- CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE);
+ CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_FAST);
}
}
@@ -6842,24 +6823,24 @@ LogCheckpointStart(int flags, bool restartpoint)
(errmsg("restartpoint starting:%s%s%s%s%s%s%s%s",
(flags & CHECKPOINT_IS_SHUTDOWN) ? " shutdown" : "",
(flags & CHECKPOINT_END_OF_RECOVERY) ? " end-of-recovery" : "",
- (flags & CHECKPOINT_IMMEDIATE) ? " immediate" : "",
+ (flags & CHECKPOINT_FAST) ? " fast" : "",
(flags & CHECKPOINT_FORCE) ? " force" : "",
(flags & CHECKPOINT_WAIT) ? " wait" : "",
(flags & CHECKPOINT_CAUSE_XLOG) ? " wal" : "",
(flags & CHECKPOINT_CAUSE_TIME) ? " time" : "",
- (flags & CHECKPOINT_FLUSH_ALL) ? " flush-all" : "")));
+ (flags & CHECKPOINT_FLUSH_UNLOGGED) ? " flush-unlogged" : "")));
else
ereport(LOG,
/* translator: the placeholders show checkpoint options */
(errmsg("checkpoint starting:%s%s%s%s%s%s%s%s",
(flags & CHECKPOINT_IS_SHUTDOWN) ? " shutdown" : "",
(flags & CHECKPOINT_END_OF_RECOVERY) ? " end-of-recovery" : "",
- (flags & CHECKPOINT_IMMEDIATE) ? " immediate" : "",
+ (flags & CHECKPOINT_FAST) ? " fast" : "",
(flags & CHECKPOINT_FORCE) ? " force" : "",
(flags & CHECKPOINT_WAIT) ? " wait" : "",
(flags & CHECKPOINT_CAUSE_XLOG) ? " wal" : "",
(flags & CHECKPOINT_CAUSE_TIME) ? " time" : "",
- (flags & CHECKPOINT_FLUSH_ALL) ? " flush-all" : "")));
+ (flags & CHECKPOINT_FLUSH_UNLOGGED) ? " flush-unlogged" : "")));
}
/*
@@ -7042,12 +7023,12 @@ update_checkpoint_display(int flags, bool restartpoint, bool reset)
* flags is a bitwise OR of the following:
* CHECKPOINT_IS_SHUTDOWN: checkpoint is for database shutdown.
* CHECKPOINT_END_OF_RECOVERY: checkpoint is for end of WAL recovery.
- * CHECKPOINT_IMMEDIATE: finish the checkpoint ASAP,
- * ignoring checkpoint_completion_target parameter.
+ * CHECKPOINT_FAST: finish the checkpoint ASAP, ignoring
+ * checkpoint_completion_target parameter.
* CHECKPOINT_FORCE: force a checkpoint even if no XLOG activity has occurred
* since the last one (implied by CHECKPOINT_IS_SHUTDOWN or
* CHECKPOINT_END_OF_RECOVERY).
- * CHECKPOINT_FLUSH_ALL: also flush buffers of unlogged tables.
+ * CHECKPOINT_FLUSH_UNLOGGED: also flush buffers of unlogged tables.
*
* Note: flags contains other bits, of interest here only for logging purposes.
* In particular note that this routine is synchronous and does not pay
@@ -8150,17 +8131,19 @@ KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
XLByteToSeg(recptr, currSegNo, wal_segment_size);
segno = currSegNo;
- /*
- * Calculate how many segments are kept by slots first, adjusting for
- * max_slot_wal_keep_size.
- */
+ /* Calculate how many segments are kept by slots. */
keep = XLogGetReplicationSlotMinimumLSN();
if (keep != InvalidXLogRecPtr && keep < recptr)
{
XLByteToSeg(keep, segno, wal_segment_size);
- /* Cap by max_slot_wal_keep_size ... */
- if (max_slot_wal_keep_size_mb >= 0)
+ /*
+ * Account for max_slot_wal_keep_size to avoid keeping more than
+ * configured. However, don't do that during a binary upgrade: if
+ * slots were to be invalidated because of this, it would not be
+ * possible to preserve logical ones during the upgrade.
+ */
+ if (max_slot_wal_keep_size_mb >= 0 && !IsBinaryUpgrade)
{
uint64 slot_keep_segs;
@@ -8946,9 +8929,8 @@ issue_xlog_fsync(int fd, XLogSegNo segno, TimeLineID tli)
* backup state and tablespace map.
*
* Input parameters are "state" (the backup state), "fast" (if true, we do
- * the checkpoint in immediate mode to make it faster), and "tablespaces"
- * (if non-NULL, indicates a list of tablespaceinfo structs describing the
- * cluster's tablespaces.).
+ * the checkpoint in fast mode), and "tablespaces" (if non-NULL, indicates a
+ * list of tablespaceinfo structs describing the cluster's tablespaces.).
*
* The tablespace map contents are appended to passed-in parameter
* tablespace_map and the caller is responsible for including it in the backup
@@ -9076,11 +9058,11 @@ do_pg_backup_start(const char *backupidstr, bool fast, List **tablespaces,
* during recovery means that checkpointer is running, we can use
* RequestCheckpoint() to establish a restartpoint.
*
- * We use CHECKPOINT_IMMEDIATE only if requested by user (via
- * passing fast = true). Otherwise this can take awhile.
+ * We use CHECKPOINT_FAST only if requested by user (via passing
+ * fast = true). Otherwise this can take awhile.
*/
RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT |
- (fast ? CHECKPOINT_IMMEDIATE : 0));
+ (fast ? CHECKPOINT_FAST : 0));
/*
* Now we need to fetch the checkpoint record location, and also
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index c95eb945016..502a45163c8 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -570,8 +570,8 @@ CreateDatabaseUsingFileCopy(Oid src_dboid, Oid dst_dboid, Oid src_tsid,
* any CREATE DATABASE commands.
*/
if (!IsBinaryUpgrade)
- RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE |
- CHECKPOINT_WAIT | CHECKPOINT_FLUSH_ALL);
+ RequestCheckpoint(CHECKPOINT_FAST | CHECKPOINT_FORCE |
+ CHECKPOINT_WAIT | CHECKPOINT_FLUSH_UNLOGGED);
/*
* Iterate through all tablespaces of the template database, and copy each
@@ -673,7 +673,7 @@ CreateDatabaseUsingFileCopy(Oid src_dboid, Oid dst_dboid, Oid src_tsid,
* strategy that avoids these problems.
*/
if (!IsBinaryUpgrade)
- RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE |
+ RequestCheckpoint(CHECKPOINT_FAST | CHECKPOINT_FORCE |
CHECKPOINT_WAIT);
}
@@ -1870,7 +1870,7 @@ dropdb(const char *dbname, bool missing_ok, bool force)
* Force a checkpoint to make sure the checkpointer has received the
* message sent by ForgetDatabaseSyncRequests.
*/
- RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT);
+ RequestCheckpoint(CHECKPOINT_FAST | CHECKPOINT_FORCE | CHECKPOINT_WAIT);
/* Close all smgr fds in all backends. */
WaitForProcSignalBarrier(EmitProcSignalBarrier(PROCSIGNAL_BARRIER_SMGRRELEASE));
@@ -2120,8 +2120,8 @@ movedb(const char *dbname, const char *tblspcname)
* On Windows, this also ensures that background procs don't hold any open
* files, which would cause rmdir() to fail.
*/
- RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT
- | CHECKPOINT_FLUSH_ALL);
+ RequestCheckpoint(CHECKPOINT_FAST | CHECKPOINT_FORCE | CHECKPOINT_WAIT
+ | CHECKPOINT_FLUSH_UNLOGGED);
/* Close all smgr fds in all backends. */
WaitForProcSignalBarrier(EmitProcSignalBarrier(PROCSIGNAL_BARRIER_SMGRRELEASE));
@@ -2252,7 +2252,7 @@ movedb(const char *dbname, const char *tblspcname)
* any unlogged operations done in the new DB tablespace before the
* next checkpoint.
*/
- RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT);
+ RequestCheckpoint(CHECKPOINT_FAST | CHECKPOINT_FORCE | CHECKPOINT_WAIT);
/*
* Force synchronous commit, thus minimizing the window between
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index a9005cc7212..df31eace47a 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -500,7 +500,7 @@ DropTableSpace(DropTableSpaceStmt *stmt)
* mustn't delete. So instead, we force a checkpoint which will clean
* out any lingering files, and try again.
*/
- RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT);
+ RequestCheckpoint(CHECKPOINT_FAST | CHECKPOINT_FORCE | CHECKPOINT_WAIT);
/*
* On Windows, an unlinked file persists in the directory listing
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 70a0d832a11..73345bb3c70 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -2034,6 +2034,13 @@ CheckPointStmt:
$$ = (Node *) n;
}
+ | CHECKPOINT '(' utility_option_list ')'
+ {
+ CheckPointStmt *n = makeNode(CheckPointStmt);
+
+ $$ = (Node *) n;
+ n->options = $3;
+ }
;
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index fda91ffd1ce..2809e298a44 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -42,6 +42,8 @@
#include "access/xlog.h"
#include "access/xlog_internal.h"
#include "access/xlogrecovery.h"
+#include "catalog/pg_authid.h"
+#include "commands/defrem.h"
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "pgstat.h"
@@ -61,6 +63,7 @@
#include "storage/shmem.h"
#include "storage/smgr.h"
#include "storage/spin.h"
+#include "utils/acl.h"
#include "utils/guc.h"
#include "utils/memutils.h"
#include "utils/resowner.h"
@@ -161,7 +164,7 @@ static pg_time_t last_xlog_switch_time;
static void ProcessCheckpointerInterrupts(void);
static void CheckArchiveTimeout(void);
static bool IsCheckpointOnSchedule(double progress);
-static bool ImmediateCheckpointRequested(void);
+static bool FastCheckpointRequested(void);
static bool CompactCheckpointerRequestQueue(void);
static void UpdateSharedMemoryConfig(void);
@@ -734,12 +737,12 @@ CheckArchiveTimeout(void)
}
/*
- * Returns true if an immediate checkpoint request is pending. (Note that
- * this does not check the *current* checkpoint's IMMEDIATE flag, but whether
- * there is one pending behind it.)
+ * Returns true if a fast checkpoint request is pending. (Note that this does
+ * not check the *current* checkpoint's FAST flag, but whether there is one
+ * pending behind it.)
*/
static bool
-ImmediateCheckpointRequested(void)
+FastCheckpointRequested(void)
{
volatile CheckpointerShmemStruct *cps = CheckpointerShmem;
@@ -747,7 +750,7 @@ ImmediateCheckpointRequested(void)
* We don't need to acquire the ckpt_lck in this case because we're only
* looking at a single flag bit.
*/
- if (cps->ckpt_flags & CHECKPOINT_IMMEDIATE)
+ if (cps->ckpt_flags & CHECKPOINT_FAST)
return true;
return false;
}
@@ -760,7 +763,7 @@ ImmediateCheckpointRequested(void)
* checkpoint_completion_target.
*
* The checkpoint request flags should be passed in; currently the only one
- * examined is CHECKPOINT_IMMEDIATE, which disables delays between writes.
+ * examined is CHECKPOINT_FAST, which disables delays between writes.
*
* 'progress' is an estimate of how much of the work has been done, as a
* fraction between 0.0 meaning none, and 1.0 meaning all done.
@@ -778,10 +781,10 @@ CheckpointWriteDelay(int flags, double progress)
* 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.
*/
- if (!(flags & CHECKPOINT_IMMEDIATE) &&
+ if (!(flags & CHECKPOINT_FAST) &&
!ShutdownXLOGPending &&
!ShutdownRequestPending &&
- !ImmediateCheckpointRequested() &&
+ !FastCheckpointRequested() &&
IsCheckpointOnSchedule(progress))
{
if (ConfigReloadPending)
@@ -977,17 +980,67 @@ CheckpointerShmemInit(void)
}
/*
+ * ExecCheckpoint
+ * Primary entry point for manual CHECKPOINT commands
+ *
+ * This is mainly a wrapper for RequestCheckpoint().
+ */
+void
+ExecCheckpoint(ParseState *pstate, CheckPointStmt *stmt)
+{
+ bool fast = true;
+ bool unlogged = false;
+
+ foreach_ptr(DefElem, opt, stmt->options)
+ {
+ if (strcmp(opt->defname, "mode") == 0)
+ {
+ char *mode = defGetString(opt);
+
+ if (strcmp(mode, "spread") == 0)
+ fast = false;
+ else if (strcmp(mode, "fast") != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("unrecognized MODE option \"%s\"", mode),
+ parser_errposition(pstate, opt->location)));
+ }
+ else if (strcmp(opt->defname, "flush_unlogged") == 0)
+ unlogged = defGetBoolean(opt);
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("unrecognized CHECKPOINT option \"%s\"", opt->defname),
+ parser_errposition(pstate, opt->location)));
+ }
+
+ if (!has_privs_of_role(GetUserId(), ROLE_PG_CHECKPOINT))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ /* translator: %s is name of an SQL command (e.g., CHECKPOINT) */
+ errmsg("permission denied to execute %s command",
+ "CHECKPOINT"),
+ errdetail("Only roles with privileges of the \"%s\" role may execute this command.",
+ "pg_checkpoint")));
+
+ RequestCheckpoint(CHECKPOINT_WAIT |
+ (fast ? CHECKPOINT_FAST : 0) |
+ (unlogged ? CHECKPOINT_FLUSH_UNLOGGED : 0) |
+ (RecoveryInProgress() ? 0 : CHECKPOINT_FORCE));
+}
+
+/*
* RequestCheckpoint
* Called in backend processes to request a checkpoint
*
* flags is a bitwise OR of the following:
* CHECKPOINT_IS_SHUTDOWN: checkpoint is for database shutdown.
* CHECKPOINT_END_OF_RECOVERY: checkpoint is for end of WAL recovery.
- * CHECKPOINT_IMMEDIATE: finish the checkpoint ASAP,
+ * CHECKPOINT_FAST: finish the checkpoint ASAP,
* ignoring checkpoint_completion_target parameter.
* CHECKPOINT_FORCE: force a checkpoint even if no XLOG activity has occurred
* since the last one (implied by CHECKPOINT_IS_SHUTDOWN or
- * CHECKPOINT_END_OF_RECOVERY).
+ * CHECKPOINT_END_OF_RECOVERY, and the CHECKPOINT command).
* CHECKPOINT_WAIT: wait for completion before returning (otherwise,
* just signal checkpointer to do it, and return).
* CHECKPOINT_CAUSE_XLOG: checkpoint is requested due to xlog filling.
@@ -1009,7 +1062,7 @@ RequestCheckpoint(int flags)
* There's no point in doing slow checkpoints in a standalone backend,
* because there's no other backends the checkpoint could disrupt.
*/
- CreateCheckPoint(flags | CHECKPOINT_IMMEDIATE);
+ CreateCheckPoint(flags | CHECKPOINT_FAST);
/* Free all smgr objects, as CheckpointerMain() normally would. */
smgrdestroyall();
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index 281092279ac..e44ad576bc7 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -1888,15 +1888,6 @@ InvalidatePossiblyObsoleteSlot(uint32 possible_causes,
SpinLockRelease(&s->mutex);
/*
- * The logical replication slots shouldn't be invalidated as GUC
- * max_slot_wal_keep_size is set to -1 and
- * idle_replication_slot_timeout is set to 0 during the binary
- * upgrade. See check_old_cluster_for_valid_slots() where we ensure
- * that no slot was invalidated before the upgrade.
- */
- Assert(!(*invalidated && SlotIsLogical(s) && IsBinaryUpgrade));
-
- /*
* Calculate the idle time duration of the slot if slot is marked
* invalidated with RS_INVAL_IDLE_TIMEOUT.
*/
@@ -2042,6 +2033,10 @@ restart:
if (!s->in_use)
continue;
+ /* Prevent invalidation of logical slots during binary upgrade */
+ if (SlotIsLogical(s) && IsBinaryUpgrade)
+ continue;
+
if (InvalidatePossiblyObsoleteSlot(possible_causes, s, oldestLSN, dboid,
snapshotConflictHorizon,
&invalidated))
@@ -3054,22 +3049,3 @@ WaitForStandbyConfirmation(XLogRecPtr wait_for_lsn)
ConditionVariableCancelSleep();
}
-
-/*
- * GUC check_hook for idle_replication_slot_timeout
- *
- * The value of idle_replication_slot_timeout must be set to 0 during
- * a binary upgrade. See start_postmaster() in pg_upgrade for more details.
- */
-bool
-check_idle_replication_slot_timeout(int *newval, void **extra, GucSource source)
-{
- if (IsBinaryUpgrade && *newval != 0)
- {
- GUC_check_errdetail("\"%s\" must be set to 0 during binary upgrade mode.",
- "idle_replication_slot_timeout");
- return false;
- }
-
- return true;
-}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index bd68d7e0ca9..6afdd28dba6 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -3339,10 +3339,10 @@ UnpinBufferNoOwner(BufferDesc *buf)
* BufferSync -- Write out all dirty buffers in the pool.
*
* This is called at checkpoint time to write out all dirty shared buffers.
- * The checkpoint request flags should be passed in. If CHECKPOINT_IMMEDIATE
- * is set, we disable delays between writes; if CHECKPOINT_IS_SHUTDOWN,
- * CHECKPOINT_END_OF_RECOVERY or CHECKPOINT_FLUSH_ALL is set, we write even
- * unlogged buffers, which are otherwise skipped. The remaining flags
+ * The checkpoint request flags should be passed in. If CHECKPOINT_FAST is
+ * set, we disable delays between writes; if CHECKPOINT_IS_SHUTDOWN,
+ * CHECKPOINT_END_OF_RECOVERY or CHECKPOINT_FLUSH_UNLOGGED is set, we write
+ * even unlogged buffers, which are otherwise skipped. The remaining flags
* currently have no effect here.
*/
static void
@@ -3367,7 +3367,7 @@ BufferSync(int flags)
* recovery, we write all dirty buffers.
*/
if (!((flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_END_OF_RECOVERY |
- CHECKPOINT_FLUSH_ALL))))
+ CHECKPOINT_FLUSH_UNLOGGED))))
mask |= BM_PERMANENT;
/*
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index aff8510755f..4c1faf5575c 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -943,17 +943,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
break;
case T_CheckPointStmt:
- if (!has_privs_of_role(GetUserId(), ROLE_PG_CHECKPOINT))
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- /* translator: %s is name of a SQL command, eg CHECKPOINT */
- errmsg("permission denied to execute %s command",
- "CHECKPOINT"),
- errdetail("Only roles with privileges of the \"%s\" role may execute this command.",
- "pg_checkpoint")));
-
- RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_WAIT |
- (RecoveryInProgress() ? 0 : CHECKPOINT_FORCE));
+ ExecCheckpoint(pstate, (CheckPointStmt *) parsetree);
break;
/*
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index a925be86944..d14b1678e7f 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -3081,7 +3081,7 @@ struct config_int ConfigureNamesInt[] =
},
&max_slot_wal_keep_size_mb,
-1, -1, MAX_KILOBYTES,
- check_max_slot_wal_keep_size, NULL, NULL
+ NULL, NULL, NULL
},
{
@@ -3104,7 +3104,7 @@ struct config_int ConfigureNamesInt[] =
},
&idle_replication_slot_timeout_secs,
0, 0, INT_MAX,
- check_idle_replication_slot_timeout, NULL, NULL
+ NULL, NULL, NULL
},
{
diff --git a/src/bin/pg_upgrade/server.c b/src/bin/pg_upgrade/server.c
index 873e5b5117b..7eb15bc7d5a 100644
--- a/src/bin/pg_upgrade/server.c
+++ b/src/bin/pg_upgrade/server.c
@@ -242,24 +242,6 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error)
appendPQExpBufferStr(&pgoptions, " -c synchronous_commit=off -c fsync=off -c full_page_writes=off");
/*
- * Use max_slot_wal_keep_size as -1 to prevent the WAL removal by the
- * checkpointer process. If WALs required by logical replication slots
- * are removed, the slots are unusable. This setting prevents the
- * invalidation of slots during the upgrade. We set this option when
- * cluster is PG17 or later because logical replication slots can only be
- * migrated since then. Besides, max_slot_wal_keep_size is added in PG13.
- */
- if (GET_MAJOR_VERSION(cluster->major_version) >= 1700)
- appendPQExpBufferStr(&pgoptions, " -c max_slot_wal_keep_size=-1");
-
- /*
- * Use idle_replication_slot_timeout=0 to prevent slot invalidation due to
- * idle_timeout by checkpointer process during upgrade.
- */
- if (GET_MAJOR_VERSION(cluster->major_version) >= 1800)
- appendPQExpBufferStr(&pgoptions, " -c idle_replication_slot_timeout=0");
-
- /*
* Use -b to disable autovacuum and logical replication launcher
* (effective in PG17 or later for the latter).
*/
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index 5ba45a0bcb3..6872653c6c8 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -3153,6 +3153,22 @@ match_previous_words(int pattern_id,
COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_procedures);
else if (Matches("CALL", MatchAny))
COMPLETE_WITH("(");
+/* CHECKPOINT */
+ else if (Matches("CHECKPOINT"))
+ COMPLETE_WITH("(");
+ else if (HeadMatches("CHECKPOINT", "(*") &&
+ !HeadMatches("CHECKPOINT", "(*)"))
+ {
+ /*
+ * This fires if we're in an unfinished parenthesized option list.
+ * get_previous_words treats a completed parenthesized option list as
+ * one word, so the above test is correct.
+ */
+ if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
+ COMPLETE_WITH("MODE", "FLUSH_UNLOGGED");
+ else if (TailMatches("MODE"))
+ COMPLETE_WITH("FAST", "SPREAD");
+ }
/* CLOSE */
else if (Matches("CLOSE"))
COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors,
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index d313099c027..d12798be3d8 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -139,10 +139,9 @@ extern PGDLLIMPORT bool XLOG_DEBUG;
#define CHECKPOINT_IS_SHUTDOWN 0x0001 /* Checkpoint is for shutdown */
#define CHECKPOINT_END_OF_RECOVERY 0x0002 /* Like shutdown checkpoint, but
* issued at end of WAL recovery */
-#define CHECKPOINT_IMMEDIATE 0x0004 /* Do it without delays */
+#define CHECKPOINT_FAST 0x0004 /* Do it without delays */
#define CHECKPOINT_FORCE 0x0008 /* Force even if no activity */
-#define CHECKPOINT_FLUSH_ALL 0x0010 /* Flush all pages, including those
- * belonging to unlogged tables */
+#define CHECKPOINT_FLUSH_UNLOGGED 0x0010 /* Flush unlogged tables */
/* These are important to RequestCheckpoint */
#define CHECKPOINT_WAIT 0x0020 /* Wait for completion */
#define CHECKPOINT_REQUESTED 0x0040 /* Checkpoint request has been made */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 28e2e8dc0fd..86a236bd58b 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -4047,6 +4047,7 @@ typedef struct RefreshMatViewStmt
typedef struct CheckPointStmt
{
NodeTag type;
+ List *options; /* list of DefElem nodes */
} CheckPointStmt;
/* ----------------------
diff --git a/src/include/postmaster/bgwriter.h b/src/include/postmaster/bgwriter.h
index 800ecbfd13b..97001f4e7f6 100644
--- a/src/include/postmaster/bgwriter.h
+++ b/src/include/postmaster/bgwriter.h
@@ -15,6 +15,7 @@
#ifndef _BGWRITER_H
#define _BGWRITER_H
+#include "parser/parse_node.h"
#include "storage/block.h"
#include "storage/relfilelocator.h"
#include "storage/smgr.h"
@@ -30,6 +31,7 @@ extern PGDLLIMPORT double CheckPointCompletionTarget;
pg_noreturn extern void BackgroundWriterMain(const void *startup_data, size_t startup_data_len);
pg_noreturn extern void CheckpointerMain(const void *startup_data, size_t startup_data_len);
+extern void ExecCheckpoint(ParseState *pstate, CheckPointStmt *stmt);
extern void RequestCheckpoint(int flags);
extern void CheckpointWriteDelay(int flags, double progress);
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 799fa7ace68..82ac8646a8d 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -84,8 +84,6 @@ extern const char *show_log_timezone(void);
extern void assign_maintenance_io_concurrency(int newval, void *extra);
extern void assign_io_max_combine_limit(int newval, void *extra);
extern void assign_io_combine_limit(int newval, void *extra);
-extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
- GucSource source);
extern void assign_max_wal_size(int newval, void *extra);
extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
extern void assign_max_stack_depth(int newval, void *extra);
@@ -176,7 +174,5 @@ extern void assign_wal_sync_method(int new_wal_sync_method, void *extra);
extern bool check_synchronized_standby_slots(char **newval, void **extra,
GucSource source);
extern void assign_synchronized_standby_slots(const char *newval, void *extra);
-extern bool check_idle_replication_slot_timeout(int *newval, void **extra,
- GucSource source);
#endif /* GUC_HOOKS_H */
diff --git a/src/test/perl/PostgreSQL/Test/Utils.pm b/src/test/perl/PostgreSQL/Test/Utils.pm
index 7d7ca83495f..85d36a3171e 100644
--- a/src/test/perl/PostgreSQL/Test/Utils.pm
+++ b/src/test/perl/PostgreSQL/Test/Utils.pm
@@ -108,6 +108,7 @@ BEGIN
delete $ENV{LANGUAGE};
delete $ENV{LC_ALL};
$ENV{LC_MESSAGES} = 'C';
+ $ENV{LC_NUMERIC} = 'C';
setlocale(LC_ALL, "");
# This list should be kept in sync with pg_regress.c.
diff --git a/src/test/recovery/t/041_checkpoint_at_promote.pl b/src/test/recovery/t/041_checkpoint_at_promote.pl
index cb63ac8d5c9..12750ff7d4f 100644
--- a/src/test/recovery/t/041_checkpoint_at_promote.pl
+++ b/src/test/recovery/t/041_checkpoint_at_promote.pl
@@ -91,7 +91,7 @@ $node_standby->wait_for_event('checkpointer', 'create-restart-point');
# Check the logs that the restart point has started on standby. This is
# optional, but let's be sure.
ok( $node_standby->log_contains(
- "restartpoint starting: immediate wait", $logstart),
+ "restartpoint starting: fast wait", $logstart),
"restartpoint has started");
# Trigger promotion during the restart point.
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 776f1ad0e53..605f5070376 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -926,8 +926,19 @@ DROP TABLE test_stats_temp;
-- Checkpoint twice: The checkpointer reports stats after reporting completion
-- of the checkpoint. But after a second checkpoint we'll see at least the
-- results of the first.
-CHECKPOINT;
-CHECKPOINT;
+--
+-- While at it, test checkpoint options. Note that we don't test MODE SPREAD
+-- because it would prolong the test.
+CHECKPOINT (WRONG);
+ERROR: unrecognized CHECKPOINT option "wrong"
+LINE 1: CHECKPOINT (WRONG);
+ ^
+CHECKPOINT (MODE WRONG);
+ERROR: unrecognized MODE option "wrong"
+LINE 1: CHECKPOINT (MODE WRONG);
+ ^
+CHECKPOINT (MODE FAST, FLUSH_UNLOGGED FALSE);
+CHECKPOINT (FLUSH_UNLOGGED);
SELECT num_requested > :rqst_ckpts_before FROM pg_stat_checkpointer;
?column?
----------
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index 232ab8db8fa..54e72866344 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -439,8 +439,13 @@ DROP TABLE test_stats_temp;
-- Checkpoint twice: The checkpointer reports stats after reporting completion
-- of the checkpoint. But after a second checkpoint we'll see at least the
-- results of the first.
-CHECKPOINT;
-CHECKPOINT;
+--
+-- While at it, test checkpoint options. Note that we don't test MODE SPREAD
+-- because it would prolong the test.
+CHECKPOINT (WRONG);
+CHECKPOINT (MODE WRONG);
+CHECKPOINT (MODE FAST, FLUSH_UNLOGGED FALSE);
+CHECKPOINT (FLUSH_UNLOGGED);
SELECT num_requested > :rqst_ckpts_before FROM pg_stat_checkpointer;
SELECT wal_bytes > :wal_bytes_before FROM pg_stat_wal;