Currently pg_stop_backup() will wait for all WAL to be archived before
returning.  If there is a problem with the archive command or a large
backlog it may not return for a very long time (if ever).  Backup
software is faced with the choice of cancelling the query and hoping the
stop backup record was written or waiting indefinitely.

The purpose of this patch is to make waiting for archive optional, with
the default being the current behavior, i.e., to wait for all WAL to be
archived.  This functionality is already used internally by
pg_basebackup, so the only real change is to expose it through the
pg_stop_backup() function.

I wasn't sure where, if anywhere, to put tests (the underlying
functionality is tested in the pg_basebackup TAP tests).  test/recovery
and bin/pg_basebackup did not seem like appropriate places and the
pg_regress tests are not capable enough.  It seems like a new
test/backup suite would be a good idea but I wanted to get some feedback
before proceeding in that direction.

I also marked the pg_stop_* functions as parallel restricted, the same
as pg_start_backup().  Previously they were parallel safe which I don't
believe is accurate for the non-exclusive version at the very least,
since it is tied to a particular backend.

The patch applies cleanly on 30df93f but will be broken (and easily
fixed) by any cat version bump in later commits.

-- 
-David
da...@pgmasters.net
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 9c53e42..680a0dc 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -18044,7 +18044,7 @@ SELECT set_config('log_statement_stats', 'off', false);
       </row>
       <row>
        <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><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>
@@ -18128,7 +18128,13 @@ postgres=# select pg_start_backup('label_goes_here');
     <function>pg_start_backup</>. In a non-exclusive backup, the contents of
     the <filename>backup_label</> and <filename>tablespace_map</> are returned
     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>
diff --git a/src/backend/access/transam/xlogfuncs.c 
b/src/backend/access/transam/xlogfuncs.c
index 27c0c56..d8fdacf 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -190,6 +190,7 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
        bool            nulls[3];
 
        bool            exclusive = PG_GETARG_BOOL(0);
+       bool            waitforarchive = PG_GETARG_BOOL(1);
        XLogRecPtr      stoppoint;
 
        /* check to see if caller supports us returning a tuplestore */
@@ -232,7 +233,7 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
                 * Stop the exclusive backup, and since we're in an exclusive 
backup
                 * 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;
 
                nulls[1] = true;
@@ -250,7 +251,7 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
                 * 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.
                 */
-               stoppoint = do_pg_stop_backup(label_file->data, true, NULL);
+               stoppoint = do_pg_stop_backup(label_file->data, waitforarchive, 
NULL);
                nonexclusive_backup_running = false;
                cancel_before_shmem_exit(nonexclusive_base_backup_cleanup, 
(Datum) 0);
 
diff --git a/src/backend/catalog/system_views.sql 
b/src/backend/catalog/system_views.sql
index 38be9cf..c2ca2b8 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -984,6 +984,12 @@ CREATE OR REPLACE FUNCTION
   RETURNS pg_lsn STRICT VOLATILE LANGUAGE internal AS 'pg_start_backup'
   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'
+  PARALLEL RESTRICTED;
+
 -- legacy definition for compatibility with 9.3
 CREATE OR REPLACE FUNCTION
   json_populate_record(base anyelement, from_json json, use_json_as_text 
boolean DEFAULT false)
@@ -1084,7 +1090,7 @@ AS 'jsonb_insert';
 -- 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_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_switch_wal() FROM public;
 REVOKE EXECUTE ON FUNCTION pg_wal_replay_pause() FROM public;
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 9e8c1c2..df47eea 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201702231
+#define CATALOG_VERSION_NO     201702271
 
 #endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index a4cc86d..68735c3 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -3141,9 +3141,9 @@ DATA(insert OID = 2096 ( pg_terminate_backend             
PGNSP PGUID 12 1 0 0 0 f f f f t
 DESCR("terminate a server process");
 DATA(insert OID = 2172 ( pg_start_backup               PGNSP PGUID 12 1 0 0 0 
f f f f t f v r 3 0 3220 "25 16 16" _null_ _null_ _null_ _null_ _null_ 
pg_start_backup _null_ _null_ _null_ ));
 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 s 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");
-DATA(insert OID = 2739 ( pg_stop_backup                        PGNSP PGUID 12 
1 1 0 0 f f f f t t v s 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");
 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");
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to