1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-21 02:52:47 +03:00

Add MODE option to CHECKPOINT command.

This option may be set to FAST (the default) to request the
checkpoint be completed as fast as possible, or SPREAD to request
the checkpoint be spread over a longer interval (based on the
checkpoint-related configuration parameters).  Note that the server
may consolidate the options for concurrently requested checkpoints.
For example, if one session requests a "fast" checkpoint and
another requests a "spread" checkpoint, the server may perform one
"fast" checkpoint.

Author: Christoph Berg <myon@debian.org>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Fujii Masao <masao.fujii@oss.nttdata.com>
Reviewed-by: Laurenz Albe <laurenz.albe@cybertec.at>
Reviewed-by: Dilip Kumar <dilipbalaut@gmail.com>
Discussion: https://postgr.es/m/aDnaKTEf-0dLiEfz%40msg.df7cb.de
This commit is contained in:
Nathan Bossart
2025-07-11 11:51:25 -05:00
parent a4f126516e
commit 2f698d7f4b
5 changed files with 79 additions and 12 deletions

View File

@@ -43,6 +43,7 @@
#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"
@@ -987,11 +988,28 @@ CheckpointerShmemInit(void)
void
ExecCheckpoint(ParseState *pstate, CheckPointStmt *stmt)
{
bool fast = true;
foreach_ptr(DefElem, opt, stmt->options)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("unrecognized CHECKPOINT option \"%s\"", opt->defname),
parser_errposition(pstate, opt->location)));
{
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
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,
@@ -1003,7 +1021,7 @@ ExecCheckpoint(ParseState *pstate, CheckPointStmt *stmt)
"pg_checkpoint")));
RequestCheckpoint(CHECKPOINT_WAIT |
CHECKPOINT_FAST |
(fast ? CHECKPOINT_FAST : 0) |
(RecoveryInProgress() ? 0 : CHECKPOINT_FORCE));
}

View File

@@ -3156,6 +3156,19 @@ match_previous_words(int pattern_id,
/* 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");
else if (TailMatches("MODE"))
COMPLETE_WITH("FAST", "SPREAD");
}
/* CLOSE */
else if (Matches("CLOSE"))
COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors,

View File

@@ -927,12 +927,17 @@ DROP TABLE test_stats_temp;
-- of the checkpoint. But after a second checkpoint we'll see at least the
-- results of the first.
--
-- While at it, test checkpoint options.
-- 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;
CHECKPOINT (MODE WRONG);
ERROR: unrecognized MODE option "wrong"
LINE 1: CHECKPOINT (MODE WRONG);
^
CHECKPOINT (MODE FAST);
CHECKPOINT;
SELECT num_requested > :rqst_ckpts_before FROM pg_stat_checkpointer;
?column?

View File

@@ -440,9 +440,11 @@ DROP TABLE test_stats_temp;
-- of the checkpoint. But after a second checkpoint we'll see at least the
-- results of the first.
--
-- While at it, test checkpoint options.
-- While at it, test checkpoint options. Note that we don't test MODE SPREAD
-- because it would prolong the test.
CHECKPOINT (WRONG);
CHECKPOINT;
CHECKPOINT (MODE WRONG);
CHECKPOINT (MODE FAST);
CHECKPOINT;
SELECT num_requested > :rqst_ckpts_before FROM pg_stat_checkpointer;