Add recovery_target='immediate' option.
authorHeikki Linnakangas
Sat, 25 Jan 2014 15:34:04 +0000 (17:34 +0200)
committerHeikki Linnakangas
Sat, 25 Jan 2014 15:34:04 +0000 (17:34 +0200)
This allows ending recovery as a consistent state has been reached. Without
this, there was no easy way to e.g restore an online backup, without
replaying any extra WAL after the backup ended.

MauMau and me.

doc/src/sgml/backup.sgml
doc/src/sgml/recovery-config.sgml
src/backend/access/transam/recovery.conf.sample
src/backend/access/transam/xlog.c
src/include/access/xlog.h

index a2361d780fbeed21223c4a04a759d29c08409c46..854b5fde41cf9e7801b46bbda51c9193f18eeb82 100644 (file)
@@ -1124,7 +1124,7 @@ restore_command = 'cp /mnt/server/archivedir/%f %p'
    
     If you want to recover to some previous point in time (say, right before
     the junior DBA dropped your main transaction table), just specify the
-    required stopping point in recovery.conf.  You can specify
+    required stopping point in recovery.conf.  You can specify
     the stop point, known as the recovery target, either by
     date/time, named restore point or by completion of a specific transaction
     ID.  As of this writing only the date/time and named restore point options
index 550cdce6f99a23d3c00c854a151798a5a4719a67..b818197299de4d27ce6978ff507a7c9fcd34b2ad 100644 (file)
@@ -199,8 +199,33 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"'  # Windows
   
 
     Recovery Target Settings
+     
+      By default, recovery will recover to the end of the WAL log. The
+      following parameters can be used to specify an earlier stopping point.
+      At most one of recovery_target,
+      recovery_target_name, recovery_target_time, or
+      recovery_target_xid can be specified. 
+     
      
 
+     
+      recovery_target = 'immediate'
+      
+        recovery_target recovery parameter
+      
+      
+       
+        This parameter specifies that recovery should end as soon as a
+        consistency is reached, ie. as early as possible. When restoring from an
+        online backup, this means the point where taking the backup ended.
+       
+       
+        Technically, this is a string parameter, but 'immediate'
+        is currently the only allowed value.
+       
+      
+     
+
      
       recovery_target_name
            (string)
@@ -212,10 +237,6 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"'  # Windows
        
         This parameter specifies the named restore point, created with
         pg_create_restore_point() to which recovery will proceed.
-        At most one of recovery_target_name,
-         or
-         can be specified.  The default is to
-        recover to the end of the WAL log.
        
       
      
@@ -231,10 +252,6 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"'  # Windows
        
         This parameter specifies the time stamp up to which recovery
         will proceed.
-        At most one of recovery_target_time,
-         or
-         can be specified.
-        The default is to recover to the end of the WAL log.
         The precise stopping point is also influenced by
         .
        
@@ -254,15 +271,18 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"'  # Windows
         start, transactions can complete in a different numeric order.
         The transactions that will be recovered are those that committed
         before (and optionally including) the specified one.
-        At most one of recovery_target_xid,
-         or
-         can be specified.
-        The default is to recover to the end of the WAL log.
         The precise stopping point is also influenced by
         .
        
       
      
+     
+     
+       The following options further specify the recovery target, and affect
+       what happens when the target is reached:
+     
+
+     
 
      
                    xreflabel="recovery_target_inclusive">
index 673605cfc661d1a1bc69e78f7a79f4c0fbb7ac9e..6f7b38eb1979365bea209d54baa47c4f1409da93 100644 (file)
 #recovery_target_inclusive = true
 #
 #
+# Alternatively, you can request stopping as soon as a consistent state
+# is reached, by uncommenting this option.
+#
+#recovery_target = 'immediate'
+#
+#
 # If you want to recover into a timeline other than the "main line" shown in
 # pg_control, specify the timeline number here, or write 'latest' to get
 # the latest branch for which there's a history file.
index 9559d6d6aef93fcce6c2b7011568af61c9fed2f5..b333d820c7236e9df0ed5472857fe94f2484fa56 100644 (file)
@@ -5434,6 +5434,19 @@ readRecoveryCommandFile(void)
                    (errmsg_internal("recovery_target_name = '%s'",
                                     recoveryTargetName)));
        }
+       else if (strcmp(item->name, "recovery_target") == 0)
+       {
+           if (strcmp(item->value, "immediate") == 0)
+               recoveryTarget = RECOVERY_TARGET_IMMEDIATE;
+           else
+               ereport(ERROR,
+                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                        errmsg("invalid recovery_target parameter"),
+                        errhint("The only allowed value is 'immediate'")));
+           ereport(DEBUG2,
+                   (errmsg_internal("recovery_target = '%s'",
+                                    item->value)));
+       }
        else if (strcmp(item->name, "recovery_target_inclusive") == 0)
        {
            /*
@@ -5676,7 +5689,20 @@ recoveryStopsBefore(XLogRecord *record)
    bool        isCommit;
    TimestampTz recordXtime = 0;
 
-   /* We only consider stopping before COMMIT or ABORT records. */
+   /* Check if we should stop as soon as reaching consistency */
+   if (recoveryTarget == RECOVERY_TARGET_IMMEDIATE && reachedConsistency)
+   {
+       ereport(LOG,
+               (errmsg("recovery stopping after reaching consistency")));
+
+       recoveryStopAfter = false;
+       recoveryStopXid = InvalidTransactionId;
+       recoveryStopTime = 0;
+       recoveryStopName[0] = '\0';
+       return true;
+   }
+
+   /* Otherwise we only consider stopping before COMMIT or ABORT records. */
    if (record->xl_rmid != RM_XACT_ID)
        return false;
    record_info = record->xl_info & ~XLR_INFO_MASK;
@@ -5825,6 +5851,19 @@ recoveryStopsAfter(XLogRecord *record)
        }
    }
 
+   /* Check if we should stop as soon as reaching consistency */
+   if (recoveryTarget == RECOVERY_TARGET_IMMEDIATE && reachedConsistency)
+   {
+       ereport(LOG,
+               (errmsg("recovery stopping after reaching consistency")));
+
+       recoveryStopAfter = true;
+       recoveryStopXid = InvalidTransactionId;
+       recoveryStopTime = 0;
+       recoveryStopName[0] = '\0';
+       return true;
+   }
+
    return false;
 }
 
@@ -6246,6 +6285,9 @@ StartupXLOG(void)
            ereport(LOG,
                    (errmsg("starting point-in-time recovery to \"%s\"",
                            recoveryTargetName)));
+       else if (recoveryTarget == RECOVERY_TARGET_IMMEDIATE)
+           ereport(LOG,
+                   (errmsg("starting point-in-time recovery to earliest consistent point")));
        else
            ereport(LOG,
                    (errmsg("starting archive recovery")));
@@ -7125,6 +7167,8 @@ StartupXLOG(void)
            snprintf(reason, sizeof(reason),
                     "at restore point \"%s\"",
                     recoveryStopName);
+       else if (recoveryTarget == RECOVERY_TARGET_IMMEDIATE)
+           snprintf(reason, sizeof(reason), "reached consistency");
        else
            snprintf(reason, sizeof(reason), "no recovery target specified");
 
index 281f51629e4195acecf537f386e1a07971805f86..47e302276b4e977e25ec1b473b1d330dfb4b89eb 100644 (file)
@@ -173,7 +173,8 @@ typedef enum
    RECOVERY_TARGET_UNSET,
    RECOVERY_TARGET_XID,
    RECOVERY_TARGET_TIME,
-   RECOVERY_TARGET_NAME
+   RECOVERY_TARGET_NAME,
+   RECOVERY_TARGET_IMMEDIATE
 } RecoveryTargetType;
 
 extern XLogRecPtr XactLastRecEnd;