summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/ref/checkpoint.sgml35
-rw-r--r--src/backend/postmaster/checkpointer.c28
-rw-r--r--src/bin/psql/tab-complete.in.c13
-rw-r--r--src/test/regress/expected/stats.out9
-rw-r--r--src/test/regress/sql/stats.sql6
5 files changed, 79 insertions, 12 deletions
diff --git a/doc/src/sgml/ref/checkpoint.sgml b/doc/src/sgml/ref/checkpoint.sgml
index fad5e982d03..36a9e323f44 100644
--- a/doc/src/sgml/ref/checkpoint.sgml
+++ b/doc/src/sgml/ref/checkpoint.sgml
@@ -24,6 +24,8 @@ PostgreSQL documentation
CHECKPOINT [ ( option [, ...] ) ]
<phrase>where <replaceable class="parameter">option</replaceable> can be one of:</phrase>
+
+ MODE { FAST | SPREAD }
</synopsis>
</refsynopsisdiv>
@@ -39,15 +41,25 @@ CHECKPOINT [ ( option [, ...] ) ]
</para>
<para>
- The <command>CHECKPOINT</command> command forces a fast
+ By default, the <command>CHECKPOINT</command> command forces a fast
checkpoint when the command is issued, without waiting for a
regular checkpoint scheduled by the system (controlled by the settings in
<xref linkend="runtime-config-wal-checkpoints"/>).
+ To request the checkpoint be spread over a longer interval, set the
+ <literal>MODE</literal> option to <literal>SPREAD</literal>.
<command>CHECKPOINT</command> is not intended for use during normal
operation.
</para>
<para>
+ The server may consolidate concurrently requested checkpoints. Such
+ consolidated requests will contain a combined set of options. For example,
+ if one session requests a fast checkpoint and another requests a spread
+ checkpoint, the server may combine those requests and perform one fast
+ checkpoint.
+ </para>
+
+ <para>
If executed during recovery, the <command>CHECKPOINT</command> command
will force a restartpoint (see <xref linkend="wal-configuration"/>)
rather than writing a new checkpoint.
@@ -63,8 +75,25 @@ CHECKPOINT [ ( option [, ...] ) ]
<refsect1>
<title>Parameters</title>
- <para>
- </para>
+ <variablelist>
+ <varlistentry>
+ <term><literal>MODE</literal></term>
+ <listitem>
+ <para>
+ When set to <literal>FAST</literal>, which is the default, the requested
+ checkpoint will be completed as fast as possible, which may result in a
+ significantly higher rate of I/O during the checkpoint.
+ </para>
+ <para>
+ <literal>MODE</literal> can also be set to <literal>SPREAD</literal> to
+ request the checkpoint be spread over a longer interval (controlled via
+ the settings in <xref linkend="runtime-config-wal-checkpoints"/>), like a
+ regular checkpoint scheduled by the system. This can reduce the rate of
+ I/O during the checkpoint.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
</refsect1>
<refsect1>
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index dc01f2382f1..9d77269a374 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -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));
}
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index 089fe367d9f..a7db04efd93 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -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,
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 9b865ae5f6c..b4df9ad5960 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -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?
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index 97b50926aa6..0868b250a64 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -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;