From 7d9881be2cb49aba006f11330b12f64b613b31f3 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Wed, 25 Nov 2020 18:52:03 +0000 Subject: [PATCH v2 1/1] Add FAST option to CHECKPOINT. --- doc/src/sgml/ref/checkpoint.sgml | 50 ++++++++++++++++++++++++++++++-- src/backend/parser/gram.y | 36 ++++++++++++++++++++++- src/backend/postmaster/checkpointer.c | 37 +++++++++++++++++++++++ src/backend/tcop/utility.c | 8 +---- src/include/nodes/parsenodes.h | 1 + src/include/postmaster/bgwriter.h | 3 ++ src/test/regress/expected/checkpoint.out | 12 ++++++++ src/test/regress/parallel_schedule | 9 +++--- src/test/regress/serial_schedule | 1 + src/test/regress/sql/checkpoint.sql | 10 +++++++ 10 files changed, 153 insertions(+), 14 deletions(-) create mode 100644 src/test/regress/expected/checkpoint.out create mode 100644 src/test/regress/sql/checkpoint.sql diff --git a/doc/src/sgml/ref/checkpoint.sgml b/doc/src/sgml/ref/checkpoint.sgml index 2afee6d7b5..0dd035c456 100644 --- a/doc/src/sgml/ref/checkpoint.sgml +++ b/doc/src/sgml/ref/checkpoint.sgml @@ -21,7 +21,11 @@ PostgreSQL documentation -CHECKPOINT +CHECKPOINT [ ( option [, ...] ) ] + +where option can be one of: + + FAST [ boolean ] @@ -37,7 +41,7 @@ CHECKPOINT - The CHECKPOINT command forces an immediate + The CHECKPOINT command forces a checkpoint when the command is issued, without waiting for a regular checkpoint scheduled by the system (controlled by the settings in ). @@ -51,11 +55,53 @@ CHECKPOINT rather than writing a new checkpoint. + + Note that the server may consolidate concurrently requested checkpoints or + restartpoints. Such consolidated requests will contain a combined set of + options. For example, if one session requested a fast checkpoint and another + session requested a checkpoint with FAST turned off, the + server may combine these requests and perform one fast checkpoint. + + Only superusers can call CHECKPOINT. + + Parameters + + + + FAST + + + Specifies that CHECKPOINT should create a checkpoint or + restartpoint as fast as possible. If this option is turned off, the + checkpoint activity is throttled based on the setting for the + parameter. By default, + FAST is enabled, and the checkpoint activity is + not throttled. + + + + + + boolean + + + Specifies whether the selected option should be turned on or off. + You can write TRUE, ON, or + 1 to enable the option, and FALSE, + OFF, or 0 to disable it. The + boolean value can also + be omitted, in which case TRUE is assumed. + + + + + + Compatibility diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index efc9c99754..b36f4a1d30 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -314,6 +314,10 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); transaction_mode_item create_extension_opt_item alter_extension_opt_item +%type opt_chkpt_option_list chkpt_option_list +%type chkpt_option_elem +%type chkpt_option_arg + %type opt_lock lock_type cast_context %type vac_analyze_option_name %type vac_analyze_option_elem @@ -1777,13 +1781,43 @@ constraints_set_mode: * Checkpoint statement */ CheckPointStmt: - CHECKPOINT + CHECKPOINT opt_chkpt_option_list { CheckPointStmt *n = makeNode(CheckPointStmt); + n->options = $2; $$ = (Node *)n; } ; +opt_chkpt_option_list: + '(' chkpt_option_list ')' { $$ = $2; } + | /* EMPTY */ { $$ = NIL; } + ; + +chkpt_option_list: + chkpt_option_elem + { + $$ = list_make1($1); + } + | chkpt_option_list ',' chkpt_option_elem + { + $$ = lappend($1, $3); + } + ; + +chkpt_option_elem: + NonReservedWord chkpt_option_arg + { + $$ = makeDefElem($1, $2, @1); + } + ; + +chkpt_option_arg: + opt_boolean_or_string { $$ = (Node *) makeString($1); } + | NumericOnly { $$ = (Node *) $1; } + | /* EMPTY */ { $$ = NULL; } + ; + /***************************************************************************** * diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 429c8010ef..27cc233a67 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -41,6 +41,7 @@ #include "access/xlog.h" #include "access/xlog_internal.h" +#include "commands/defrem.h" #include "libpq/pqsignal.h" #include "miscadmin.h" #include "pgstat.h" @@ -895,6 +896,42 @@ CheckpointerShmemInit(void) } } +/* + * ExecCheckPointStmt + * Primary entry point for CHECKPOINT commands + */ +void +ExecCheckPointStmt(ParseState *pstate, CheckPointStmt *stmt) +{ + ListCell *lc; + bool fast = true; + int flags; + + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be superuser to do CHECKPOINT"))); + + foreach(lc, stmt->options) + { + DefElem *opt = (DefElem *) lfirst(lc); + + if (strcmp(opt->defname, "fast") == 0) + fast = defGetBoolean(opt); + else + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("unrecognized CHECKPOINT option \"%s\"", opt->defname), + parser_errposition(pstate, opt->location))); + } + + flags = CHECKPOINT_WAIT | + (RecoveryInProgress() ? 0 : CHECKPOINT_FORCE) | + (fast ? CHECKPOINT_IMMEDIATE : 0); + + RequestCheckpoint(flags); +} + /* * RequestCheckpoint * Called in backend processes to request a checkpoint diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 81ac9b1cb2..4af8de0a26 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -906,13 +906,7 @@ standard_ProcessUtility(PlannedStmt *pstmt, break; case T_CheckPointStmt: - if (!superuser()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to do CHECKPOINT"))); - - RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_WAIT | - (RecoveryInProgress() ? 0 : CHECKPOINT_FORCE)); + ExecCheckPointStmt(pstate, (CheckPointStmt *) parsetree); break; case T_ReindexStmt: diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index d1f9ef29ca..f1d9d46f69 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -3297,6 +3297,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 0a5708b32e..d945009707 100644 --- a/src/include/postmaster/bgwriter.h +++ b/src/include/postmaster/bgwriter.h @@ -15,6 +15,8 @@ #ifndef _BGWRITER_H #define _BGWRITER_H +#include "nodes/parsenodes.h" +#include "parser/parse_node.h" #include "storage/block.h" #include "storage/relfilenode.h" #include "storage/smgr.h" @@ -30,6 +32,7 @@ extern double CheckPointCompletionTarget; extern void BackgroundWriterMain(void) pg_attribute_noreturn(); extern void CheckpointerMain(void) pg_attribute_noreturn(); +extern void ExecCheckPointStmt(ParseState *pstate, CheckPointStmt *stmt); extern void RequestCheckpoint(int flags); extern void CheckpointWriteDelay(int flags, double progress); diff --git a/src/test/regress/expected/checkpoint.out b/src/test/regress/expected/checkpoint.out new file mode 100644 index 0000000000..5d7c59b32b --- /dev/null +++ b/src/test/regress/expected/checkpoint.out @@ -0,0 +1,12 @@ +-- CHECKPOINT +CHECKPOINT; +CHECKPOINT (FAST); +CHECKPOINT (FAST FALSE); +CHECKPOINT (FAST ON); +CHECKPOINT (FAST 0); +CHECKPOINT (FAST 2); +ERROR: fast requires a Boolean value +CHECKPOINT (NONEXISTENT); +ERROR: unrecognized CHECKPOINT option "nonexistent" +LINE 1: CHECKPOINT (NONEXISTENT); + ^ diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index ae89ed7f0b..354dda263f 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -5,10 +5,11 @@ # this limits the number of connections needed to run the tests. # ---------- -# run tablespace by itself, and first, because it forces a checkpoint; -# we'd prefer not to have checkpoints later in the tests because that -# interferes with crash-recovery testing. -test: tablespace +# ---------- +# Run tests that force checkpoints first. We'd prefer to not have checkpoints +# later in the tests because that interferes with crash-recovery testing. +# ---------- +test: checkpoint tablespace # ---------- # The first group of parallel tests diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 525bdc804f..49901521f4 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -1,5 +1,6 @@ # src/test/regress/serial_schedule # This should probably be in an order similar to parallel_schedule. +test: checkpoint test: tablespace test: boolean test: char diff --git a/src/test/regress/sql/checkpoint.sql b/src/test/regress/sql/checkpoint.sql new file mode 100644 index 0000000000..7423798c54 --- /dev/null +++ b/src/test/regress/sql/checkpoint.sql @@ -0,0 +1,10 @@ +-- CHECKPOINT + +CHECKPOINT; +CHECKPOINT (FAST); +CHECKPOINT (FAST FALSE); +CHECKPOINT (FAST ON); +CHECKPOINT (FAST 0); + +CHECKPOINT (FAST 2); +CHECKPOINT (NONEXISTENT); -- 2.16.6