Commit 017e4f25 authored by Stephen Frost's avatar Stephen Frost

Expose waitforarchive option through pg_stop_backup()

Internally, we have supported the option to either wait for all of the
WAL associated with a backup to be archived, or to return immediately.
This option is useful to users of pg_stop_backup() as well, when they
are reading the stop backup record position and checking that the WAL
they need has been archived independently.

This patch adds an additional, optional, argument to pg_stop_backup()
which allows the user to indicate if they wish to wait for the WAL to be
archived or not.  The default matches current behavior, which is to
wait.

Author: David Steele, with some minor changes, doc updates by me.
Reviewed by: Takayuki Tsunakawa, Fujii Masao
Discussion: https://postgr.es/m/758e3fd1-45b4-5e28-75cd-e9e7f93a4c02@pgmasters.net
parent cbf7ed51
...@@ -887,7 +887,7 @@ SELECT pg_start_backup('label', false, false); ...@@ -887,7 +887,7 @@ SELECT pg_start_backup('label', false, false);
<para> <para>
In the same connection as before, issue the command: In the same connection as before, issue the command:
<programlisting> <programlisting>
SELECT * FROM pg_stop_backup(false); SELECT * FROM pg_stop_backup(false, true);
</programlisting> </programlisting>
This terminates the backup mode and performs an automatic switch to This terminates the backup mode and performs an automatic switch to
the next WAL segment. The reason for the switch is to arrange for the next WAL segment. The reason for the switch is to arrange for
...@@ -924,6 +924,17 @@ SELECT * FROM pg_stop_backup(false); ...@@ -924,6 +924,17 @@ SELECT * FROM pg_stop_backup(false);
<function>pg_stop_backup</> terminates because of this your backup <function>pg_stop_backup</> terminates because of this your backup
may not be valid. may not be valid.
</para> </para>
<para>
If the backup process monitors and ensures that all WAL segment files
required for the backup are successfully archived then the second
parameter (which defaults to true) can be set to false to have
<function>pg_stop_backup</> return as soon as the stop backup record is
written to the WAL. By default, <function>pg_stop_backup</> will wait
until all WAL has been archived, which can take some time. This option
must be used with caution: if WAL archiving is not monitored correctly
then the backup might not include all of the WAL files and will
therefore be incomplete and not able to be restored.
</para>
</listitem> </listitem>
</orderedlist> </orderedlist>
</para> </para>
......
...@@ -18355,7 +18355,7 @@ SELECT set_config('log_statement_stats', 'off', false); ...@@ -18355,7 +18355,7 @@ SELECT set_config('log_statement_stats', 'off', false);
</row> </row>
<row> <row>
<entry> <entry>
<literal><function>pg_stop_backup(<parameter>exclusive</> <type>boolean</>)</function></literal> <literal><function>pg_stop_backup(<parameter>exclusive</> <type>boolean</> <optional>, <parameter>wait_for_archive</> <type>boolean</> </optional>)</function></literal>
</entry> </entry>
<entry><type>setof record</type></entry> <entry><type>setof record</type></entry>
<entry>Finish performing exclusive or non-exclusive on-line backup (restricted to superusers by default, but other users can be granted EXECUTE to run the function)</entry> <entry>Finish performing exclusive or non-exclusive on-line backup (restricted to superusers by default, but other users can be granted EXECUTE to run the function)</entry>
...@@ -18439,7 +18439,13 @@ postgres=# select pg_start_backup('label_goes_here'); ...@@ -18439,7 +18439,13 @@ postgres=# select pg_start_backup('label_goes_here');
<function>pg_start_backup</>. In a non-exclusive backup, the contents of <function>pg_start_backup</>. In a non-exclusive backup, the contents of
the <filename>backup_label</> and <filename>tablespace_map</> are returned the <filename>backup_label</> and <filename>tablespace_map</> are returned
in the result of the function, and should be written to files in the in the result of the function, and should be written to files in the
backup (and not in the data directory). backup (and not in the data directory). There is an optional second
parameter of type boolean. If false, the <function>pg_stop_backup</>
will return immediately after the backup is completed without waiting for
WAL to be archived. This behavior is only useful for backup
software which independently monitors WAL archiving. Otherwise, WAL
required to make the backup consistent might be missing and make the backup
useless.
</para> </para>
<para> <para>
......
...@@ -10944,7 +10944,8 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p) ...@@ -10944,7 +10944,8 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
* *
* We wait forever, since archive_command is supposed to work and we * We wait forever, since archive_command is supposed to work and we
* assume the admin wanted his backup to work completely. If you don't * assume the admin wanted his backup to work completely. If you don't
* wish to wait, you can set statement_timeout. Also, some notices are * wish to wait, then either waitforarchive should be passed in as false,
* or you can set statement_timeout. Also, some notices are
* issued to clue in anyone who might be doing this interactively. * issued to clue in anyone who might be doing this interactively.
*/ */
if (waitforarchive && XLogArchivingActive()) if (waitforarchive && XLogArchivingActive())
......
...@@ -175,6 +175,13 @@ pg_stop_backup(PG_FUNCTION_ARGS) ...@@ -175,6 +175,13 @@ pg_stop_backup(PG_FUNCTION_ARGS)
* the backup label and tablespace map files as text fields in as part of the * the backup label and tablespace map files as text fields in as part of the
* resultset. * resultset.
* *
* The first parameter (variable 'exclusive') allows the user to tell us if
* this is an exclusive or a non-exclusive backup.
*
* The second paramter (variable 'waitforarchive'), which is optional,
* allows the user to choose if they want to wait for the WAL to be archived
* or if we should just return as soon as the WAL record is written.
*
* Permission checking for this function is managed through the normal * Permission checking for this function is managed through the normal
* GRANT system. * GRANT system.
*/ */
...@@ -190,6 +197,7 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS) ...@@ -190,6 +197,7 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
bool nulls[3]; bool nulls[3];
bool exclusive = PG_GETARG_BOOL(0); bool exclusive = PG_GETARG_BOOL(0);
bool waitforarchive = PG_GETARG_BOOL(1);
XLogRecPtr stoppoint; XLogRecPtr stoppoint;
/* check to see if caller supports us returning a tuplestore */ /* check to see if caller supports us returning a tuplestore */
...@@ -232,7 +240,7 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS) ...@@ -232,7 +240,7 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
* Stop the exclusive backup, and since we're in an exclusive backup * Stop the exclusive backup, and since we're in an exclusive backup
* return NULL for both backup_label and tablespace_map. * return NULL for both backup_label and tablespace_map.
*/ */
stoppoint = do_pg_stop_backup(NULL, true, NULL); stoppoint = do_pg_stop_backup(NULL, waitforarchive, NULL);
exclusive_backup_running = false; exclusive_backup_running = false;
nulls[1] = true; nulls[1] = true;
...@@ -250,7 +258,7 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS) ...@@ -250,7 +258,7 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
* Stop the non-exclusive backup. Return a copy of the backup label * Stop the non-exclusive backup. Return a copy of the backup label
* and tablespace map so they can be written to disk by the caller. * and tablespace map so they can be written to disk by the caller.
*/ */
stoppoint = do_pg_stop_backup(label_file->data, true, NULL); stoppoint = do_pg_stop_backup(label_file->data, waitforarchive, NULL);
nonexclusive_backup_running = false; nonexclusive_backup_running = false;
cancel_before_shmem_exit(nonexclusive_base_backup_cleanup, (Datum) 0); cancel_before_shmem_exit(nonexclusive_base_backup_cleanup, (Datum) 0);
......
...@@ -988,6 +988,12 @@ CREATE OR REPLACE FUNCTION ...@@ -988,6 +988,12 @@ CREATE OR REPLACE FUNCTION
RETURNS pg_lsn STRICT VOLATILE LANGUAGE internal AS 'pg_start_backup' RETURNS pg_lsn STRICT VOLATILE LANGUAGE internal AS 'pg_start_backup'
PARALLEL RESTRICTED; PARALLEL RESTRICTED;
CREATE OR REPLACE FUNCTION pg_stop_backup (
exclusive boolean, wait_for_archive boolean DEFAULT true,
OUT lsn pg_lsn, OUT labelfile text, OUT spcmapfile text)
RETURNS SETOF record STRICT VOLATILE LANGUAGE internal as 'pg_stop_backup_v2'
PARALLEL RESTRICTED;
-- legacy definition for compatibility with 9.3 -- legacy definition for compatibility with 9.3
CREATE OR REPLACE FUNCTION CREATE OR REPLACE FUNCTION
json_populate_record(base anyelement, from_json json, use_json_as_text boolean DEFAULT false) json_populate_record(base anyelement, from_json json, use_json_as_text boolean DEFAULT false)
...@@ -1088,7 +1094,7 @@ AS 'jsonb_insert'; ...@@ -1088,7 +1094,7 @@ AS 'jsonb_insert';
-- available to superuser / cluster owner, if they choose. -- available to superuser / cluster owner, if they choose.
REVOKE EXECUTE ON FUNCTION pg_start_backup(text, boolean, boolean) FROM public; REVOKE EXECUTE ON FUNCTION pg_start_backup(text, boolean, boolean) FROM public;
REVOKE EXECUTE ON FUNCTION pg_stop_backup() FROM public; REVOKE EXECUTE ON FUNCTION pg_stop_backup() FROM public;
REVOKE EXECUTE ON FUNCTION pg_stop_backup(boolean) FROM public; REVOKE EXECUTE ON FUNCTION pg_stop_backup(boolean, boolean) FROM public;
REVOKE EXECUTE ON FUNCTION pg_create_restore_point(text) FROM public; REVOKE EXECUTE ON FUNCTION pg_create_restore_point(text) FROM public;
REVOKE EXECUTE ON FUNCTION pg_switch_wal() FROM public; REVOKE EXECUTE ON FUNCTION pg_switch_wal() FROM public;
REVOKE EXECUTE ON FUNCTION pg_wal_replay_pause() FROM public; REVOKE EXECUTE ON FUNCTION pg_wal_replay_pause() FROM public;
......
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 201703161 #define CATALOG_VERSION_NO 201703221
#endif #endif
...@@ -3172,7 +3172,7 @@ DATA(insert OID = 2172 ( pg_start_backup PGNSP PGUID 12 1 0 0 0 f f f f t f v r ...@@ -3172,7 +3172,7 @@ DATA(insert OID = 2172 ( pg_start_backup PGNSP PGUID 12 1 0 0 0 f f f f t f v r
DESCR("prepare for taking an online backup"); DESCR("prepare for taking an online backup");
DATA(insert OID = 2173 ( pg_stop_backup PGNSP PGUID 12 1 0 0 0 f f f f t f v r 0 0 3220 "" _null_ _null_ _null_ _null_ _null_ pg_stop_backup _null_ _null_ _null_ )); DATA(insert OID = 2173 ( pg_stop_backup PGNSP PGUID 12 1 0 0 0 f f f f t f v r 0 0 3220 "" _null_ _null_ _null_ _null_ _null_ pg_stop_backup _null_ _null_ _null_ ));
DESCR("finish taking an online backup"); DESCR("finish taking an online backup");
DATA(insert OID = 2739 ( pg_stop_backup PGNSP PGUID 12 1 1 0 0 f f f f t t v r 1 0 2249 "16" "{16,3220,25,25}" "{i,o,o,o}" "{exclusive,lsn,labelfile,spcmapfile}" _null_ _null_ pg_stop_backup_v2 _null_ _null_ _null_ )); DATA(insert OID = 2739 ( pg_stop_backup PGNSP PGUID 12 1 1 0 0 f f f f t t v r 2 0 2249 "16 16" "{16,16,3220,25,25}" "{i,i,o,o,o}" "{exclusive,wait_for_archive,lsn,labelfile,spcmapfile}" _null_ _null_ pg_stop_backup_v2 _null_ _null_ _null_ ));
DESCR("finish taking an online backup"); DESCR("finish taking an online backup");
DATA(insert OID = 3813 ( pg_is_in_backup PGNSP PGUID 12 1 0 0 0 f f f f t f v s 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_is_in_backup _null_ _null_ _null_ )); DATA(insert OID = 3813 ( pg_is_in_backup PGNSP PGUID 12 1 0 0 0 f f f f t f v s 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_is_in_backup _null_ _null_ _null_ ));
DESCR("true if server is in online backup"); DESCR("true if server is in online backup");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment