From 387060951e40d550d37fe0457521e900d8c60feb Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Tue, 7 Apr 2009 00:31:26 +0000
Subject: [PATCH] Add an optional parameter to pg_start_backup() that specifies
 whether to do the checkpoint in immediate or lazy mode.  This is to address
 complaints that pg_start_backup() takes a long time even when there's no need
 to minimize its I/O consumption.

---
 doc/src/sgml/backup.sgml             | 22 +++++++++++-----------
 doc/src/sgml/func.sgml               | 21 +++++++++++++--------
 src/backend/access/transam/xlog.c    |  9 ++++++---
 src/backend/catalog/system_views.sql | 21 ++++++++++++++++++++-
 src/include/catalog/catversion.h     |  4 ++--
 src/include/catalog/pg_proc.h        |  4 ++--
 6 files changed, 54 insertions(+), 27 deletions(-)

diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml
index 51c3f909b31..ae9563a8e38 100644
--- a/doc/src/sgml/backup.sgml
+++ b/doc/src/sgml/backup.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.123 2009/03/05 19:50:03 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.124 2009/04/07 00:31:25 tgl Exp $ -->
 
 <chapter id="backup">
  <title>Backup and Restore</title>
@@ -730,19 +730,19 @@ SELECT pg_start_backup('label');
     </para>
 
     <para>
-     <function>pg_start_backup</> can take a long time to finish.
+     By default, <function>pg_start_backup</> can take a long time to finish.
      This is because it performs a checkpoint, and the I/O
-     required for a checkpoint will be spread out over a significant
+     required for the checkpoint will be spread out over a significant
      period of time, by default half your inter-checkpoint interval
      (see the configuration parameter
      <xref linkend="guc-checkpoint-completion-target">).  Usually
-     this is what you want because it minimizes the impact on query
+     this is what you want, because it minimizes the impact on query
      processing.  If you just want to start the backup as soon as
-     possible, execute a <command>CHECKPOINT</> command
-     (which performs a checkpoint as quickly as possible) and then
-     immediately execute <function>pg_start_backup</>.  Then there
-     will be very little for <function>pg_start_backup</>'s checkpoint
-     to do, and it won't take long.
+     possible, use:
+<programlisting>
+SELECT pg_start_backup('label', true);
+</programlisting>
+     This forces the checkpoint to be done as quickly as possible.
     </para>
    </listitem>
    <listitem>
@@ -769,9 +769,9 @@ SELECT pg_stop_backup();
     <para>
      Once the WAL segment files used during the backup are archived, you are
      done.  The file identified by <function>pg_stop_backup</>'s result is
-     the last segment that is required to form a complete set of backup files. 
+     the last segment that is required to form a complete set of backup files.
      <function>pg_stop_backup</> does not return until the last segment has
-     been archived. 
+     been archived.
      Archiving of these files happens automatically since you have
      already configured <varname>archive_command</>. In most cases this
      happens quickly, but you are advised to monitor your archive
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index bd05152f783..f42f3e93412 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.474 2009/04/01 03:32:29 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.475 2009/04/07 00:31:25 tgl Exp $ -->
 
  <chapter id="functions">
   <title>Functions and Operators</title>
@@ -12880,10 +12880,10 @@ SELECT set_config('log_statement_stats', 'off', false);
      <tbody>
       <row>
        <entry>
-        <literal><function>pg_start_backup</function>(<parameter>label</> <type>text</>)</literal>
+        <literal><function>pg_start_backup</function>(<parameter>label</> <type>text</> <optional>, <parameter>fast</> <type>boolean</> </optional>)</literal>
         </entry>
        <entry><type>text</type></entry>
-       <entry>Set up for performing on-line backup</entry>
+       <entry>Prepare for performing on-line backup</entry>
       </row>
       <row>
        <entry>
@@ -12932,13 +12932,14 @@ SELECT set_config('log_statement_stats', 'off', false);
    </table>
 
    <para>
-    <function>pg_start_backup</> accepts a single parameter which is an
+    <function>pg_start_backup</> accepts a text parameter which is an
     arbitrary user-defined label for the backup.  (Typically this would be
     the name under which the backup dump file will be stored.)  The function
     writes a backup label file into the database cluster's data directory,
-    and then returns the backup's starting transaction log location as text.  The user
-    need not pay any attention to this result value, but it is provided in
-    case it is of use. 
+    performs a checkpoint,
+    and then returns the backup's starting transaction log location as text.
+    The user need not pay any attention to this result value, but it is
+    provided in case it is of use.
 <programlisting>
 postgres=# select pg_start_backup('label_goes_here');
  pg_start_backup
@@ -12946,6 +12947,10 @@ postgres=# select pg_start_backup('label_goes_here');
  0/D4445B8
 (1 row)
 </programlisting>
+    There is an optional boolean second parameter.  If <literal>true</>,
+    it specifies executing <function>pg_start_backup</> as quickly as
+    possible.  This forces an immediate checkpoint which will cause a
+    spike in I/O operations, slowing any concurrently executing queries.
    </para>
 
    <para>
@@ -12961,7 +12966,7 @@ postgres=# select pg_start_backup('label_goes_here');
    </para>
 
    <para>
-    <function>pg_switch_xlog</> moves to the next transaction log file, allowing the 
+    <function>pg_switch_xlog</> moves to the next transaction log file, allowing the
     current file to be archived (assuming you are using continuous archiving).
     The result is the ending transaction log location + 1 within the just-completed transaction log file.
     If there has been no transaction log activity since the last transaction log switch,
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 3027129eb7c..65484b6f70d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.334 2009/03/11 23:19:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.335 2009/04/07 00:31:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -6914,6 +6914,7 @@ Datum
 pg_start_backup(PG_FUNCTION_ARGS)
 {
 	text	   *backupid = PG_GETARG_TEXT_P(0);
+	bool		fast = PG_GETARG_BOOL(1);
 	char	   *backupidstr;
 	XLogRecPtr	checkpointloc;
 	XLogRecPtr	startpoint;
@@ -6983,9 +6984,11 @@ pg_start_backup(PG_FUNCTION_ARGS)
 		 * have different checkpoint positions and hence different history
 		 * file names, even if nothing happened in between.
 		 *
-		 * We don't use CHECKPOINT_IMMEDIATE, hence this can take awhile.
+		 * We use CHECKPOINT_IMMEDIATE only if requested by user (via
+		 * passing fast = true).  Otherwise this can take awhile.
 		 */
-		RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT);
+		RequestCheckpoint(CHECKPOINT_FORCE | CHECKPOINT_WAIT |
+						  (fast ? CHECKPOINT_IMMEDIATE : 0));
 
 		/*
 		 * Now we need to fetch the checkpoint record location, and also its
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 897d930bfeb..73e391c8968 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1996-2009, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.59 2009/02/06 21:15:11 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.60 2009/04/07 00:31:26 tgl Exp $
  */
 
 CREATE VIEW pg_roles AS 
@@ -403,6 +403,12 @@ CREATE VIEW pg_user_mappings AS
 
 REVOKE ALL on pg_user_mapping FROM public;
 
+--
+-- We have a few function definitions in here, too.
+-- At some point there might be enough to justify breaking them out into
+-- a separate "system_functions.sql" file.
+--
+
 -- Tsearch debug function.  Defined here because it'd be pretty unwieldy
 -- to put it into pg_proc.h
 
@@ -464,3 +470,16 @@ LANGUAGE SQL STRICT STABLE;
 
 COMMENT ON FUNCTION ts_debug(text) IS
     'debug function for current text search configuration';
+
+--
+-- Redeclare built-in functions that need default values attached to their
+-- arguments.  It's impractical to set those up directly in pg_proc.h because
+-- of the complexity and platform-dependency of the expression tree
+-- representation.  (Note that internal functions still have to have entries
+-- in pg_proc.h; we are merely causing their proargnames and proargdefaults
+-- to get filled in.)
+--
+
+CREATE OR REPLACE FUNCTION
+  pg_start_backup(label text, fast boolean DEFAULT false)
+  RETURNS text STRICT VOLATILE LANGUAGE internal AS 'pg_start_backup';
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 95bd0ddb6b9..64c6e08e452 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.528 2009/04/05 22:28:59 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.529 2009/04/07 00:31:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200904051
+#define CATALOG_VERSION_NO	200904061
 
 #endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 00c82673706..fb711375a07 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.540 2009/04/05 22:28:59 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.541 2009/04/07 00:31:26 tgl Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -3252,7 +3252,7 @@ DATA(insert OID = 2171 ( pg_cancel_backend		PGNSP PGUID 12 1 0 0 f f f t f v 1 0
 DESCR("cancel a server process' current query");
 DATA(insert OID = 2096 ( pg_terminate_backend		PGNSP PGUID 12 1 0 0 f f f t f v 1 0 16 "23" _null_ _null_ _null_ _null_ pg_terminate_backend _null_ _null_ _null_ ));
 DESCR("terminate a server process");
-DATA(insert OID = 2172 ( pg_start_backup		PGNSP PGUID 12 1 0 0 f f f t f v 1 0 25 "25" _null_ _null_ _null_ _null_ pg_start_backup _null_ _null_ _null_ ));
+DATA(insert OID = 2172 ( pg_start_backup		PGNSP PGUID 12 1 0 0 f f f t f v 2 0 25 "25 16" _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 f f f t f v 0 0 25 "" _null_ _null_ _null_ _null_ pg_stop_backup _null_ _null_ _null_ ));
 DESCR("finish taking an online backup");
-- 
GitLab