Commit c016ce72 authored by Simon Riggs's avatar Simon Riggs

Named restore points in recovery. Users can record named points, then

new recovery.conf parameter recovery_target_name allows PITR to
specify named points as recovery targets.

Jaime Casanova, reviewed by Euler Taveira de Oliveira, plus minor edits
parent 8c6e3adb
...@@ -1086,9 +1086,10 @@ restore_command = 'cp /mnt/server/archivedir/%f %p' ...@@ -1086,9 +1086,10 @@ restore_command = 'cp /mnt/server/archivedir/%f %p'
the junior DBA dropped your main transaction table), just specify the the junior DBA dropped your main transaction table), just specify the
required stopping point in <filename>recovery.conf</>. You can specify required stopping point in <filename>recovery.conf</>. You can specify
the stop point, known as the <quote>recovery target</>, either by the stop point, known as the <quote>recovery target</>, either by
date/time or by completion of a specific transaction ID. As of this date/time, named restore point or by completion of a specific transaction
writing only the date/time option is very usable, since there are no tools ID. As of this writing only the date/time and named restore point options
to help you identify with any accuracy which transaction ID to use. are very usable, since there are no tools to help you identify with any
accuracy which transaction ID to use.
</para> </para>
<note> <note>
......
...@@ -13914,6 +13914,9 @@ SELECT set_config('log_statement_stats', 'off', false); ...@@ -13914,6 +13914,9 @@ SELECT set_config('log_statement_stats', 'off', false);
<indexterm> <indexterm>
<primary>backup</primary> <primary>backup</primary>
</indexterm> </indexterm>
<indexterm>
<primary>pg_create_restore_point</primary>
</indexterm>
<indexterm> <indexterm>
<primary>pg_current_xlog_insert_location</primary> <primary>pg_current_xlog_insert_location</primary>
</indexterm> </indexterm>
...@@ -13951,6 +13954,13 @@ SELECT set_config('log_statement_stats', 'off', false); ...@@ -13951,6 +13954,13 @@ SELECT set_config('log_statement_stats', 'off', false);
</thead> </thead>
<tbody> <tbody>
<row>
<entry>
<literal><function>pg_create_restore_point(<parameter>name</> <type>text</>)</function></literal>
</entry>
<entry><type>text</type></entry>
<entry>Create a named point for performing restore (restricted to superusers)</entry>
</row>
<row> <row>
<entry> <entry>
<literal><function>pg_current_xlog_insert_location()</function></literal> <literal><function>pg_current_xlog_insert_location()</function></literal>
......
...@@ -143,6 +143,25 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows ...@@ -143,6 +143,25 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
<title>Recovery Target Settings</title> <title>Recovery Target Settings</title>
<variablelist> <variablelist>
<varlistentry id="recovery-target-name" xreflabel="recovery_target_name">
<term><varname>recovery_target_name</varname>
(<type>string</type>)
</term>
<indexterm>
<primary><varname>recovery_target_name</> recovery parameter</primary>
</indexterm>
<listitem>
<para>
This parameter specifies the named restore point, created with
<function>pg_create_restore_point()</> to which recovery will proceed.
At most one of <varname>recovery_target_name</>,
<xref linkend="recovery-target-time"> or
<xref linkend="recovery-target-xid"> can be specified. The default is to
recover to the end of the WAL log.
</para>
</listitem>
</varlistentry>
<varlistentry id="recovery-target-time" xreflabel="recovery_target_time"> <varlistentry id="recovery-target-time" xreflabel="recovery_target_time">
<term><varname>recovery_target_time</varname> <term><varname>recovery_target_time</varname>
(<type>timestamp</type>) (<type>timestamp</type>)
...@@ -154,7 +173,8 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows ...@@ -154,7 +173,8 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
<para> <para>
This parameter specifies the time stamp up to which recovery This parameter specifies the time stamp up to which recovery
will proceed. will proceed.
At most one of <varname>recovery_target_time</> and At most one of <varname>recovery_target_time</>,
<xref linkend="recovery-target-name"> or
<xref linkend="recovery-target-xid"> can be specified. <xref linkend="recovery-target-xid"> can be specified.
The default is to recover to the end of the WAL log. The default is to recover to the end of the WAL log.
The precise stopping point is also influenced by The precise stopping point is also influenced by
...@@ -176,7 +196,8 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows ...@@ -176,7 +196,8 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
start, transactions can complete in a different numeric order. start, transactions can complete in a different numeric order.
The transactions that will be recovered are those that committed The transactions that will be recovered are those that committed
before (and optionally including) the specified one. before (and optionally including) the specified one.
At most one of <varname>recovery_target_xid</> and At most one of <varname>recovery_target_xid</>,
<xref linkend="recovery-target-name"> or
<xref linkend="recovery-target-time"> can be specified. <xref linkend="recovery-target-time"> can be specified.
The default is to recover to the end of the WAL log. The default is to recover to the end of the WAL log.
The precise stopping point is also influenced by The precise stopping point is also influenced by
......
...@@ -66,11 +66,14 @@ ...@@ -66,11 +66,14 @@
# If you want to stop rollforward at a specific point, you # If you want to stop rollforward at a specific point, you
# must set a recovery target. # must set a recovery target.
# #
# You may set a recovery target either by transactionId, or # You may set a recovery target either by transactionId, by name,
# by timestamp. Recovery may either include or exclude the # or by timestamp. Recovery may either include or exclude the
# transaction(s) with the recovery target value (ie, stop either # transaction(s) with the recovery target value (ie, stop either
# just after or just before the given target, respectively). # just after or just before the given target, respectively).
# #
#
#recovery_target_name = '' # e.g. 'daily backup 2011-01-26'
#
#recovery_target_time = '' # e.g. '2004-07-14 22:39:00 EST' #recovery_target_time = '' # e.g. '2004-07-14 22:39:00 EST'
# #
#recovery_target_xid = '' #recovery_target_xid = ''
......
...@@ -185,15 +185,17 @@ static bool recoveryTargetInclusive = true; ...@@ -185,15 +185,17 @@ static bool recoveryTargetInclusive = true;
static bool recoveryPauseAtTarget = true; static bool recoveryPauseAtTarget = true;
static TransactionId recoveryTargetXid; static TransactionId recoveryTargetXid;
static TimestampTz recoveryTargetTime; static TimestampTz recoveryTargetTime;
static char *recoveryTargetName;
/* options taken from recovery.conf for XLOG streaming */ /* options taken from recovery.conf for XLOG streaming */
static bool StandbyMode = false; static bool StandbyMode = false;
static char *PrimaryConnInfo = NULL; static char *PrimaryConnInfo = NULL;
static char *TriggerFile = NULL; static char *TriggerFile = NULL;
/* if recoveryStopsHere returns true, it saves actual stop xid/time here */ /* if recoveryStopsHere returns true, it saves actual stop xid/time/name here */
static TransactionId recoveryStopXid; static TransactionId recoveryStopXid;
static TimestampTz recoveryStopTime; static TimestampTz recoveryStopTime;
static char recoveryStopName[MAXFNAMELEN];
static bool recoveryStopAfter; static bool recoveryStopAfter;
/* /*
...@@ -551,6 +553,13 @@ typedef struct xl_parameter_change ...@@ -551,6 +553,13 @@ typedef struct xl_parameter_change
int wal_level; int wal_level;
} xl_parameter_change; } xl_parameter_change;
/* logs restore point */
typedef struct xl_restore_point
{
TimestampTz rp_time;
char rp_name[MAXFNAMELEN];
} xl_restore_point;
/* /*
* Flags set by interrupt handlers for later service in the redo loop. * Flags set by interrupt handlers for later service in the redo loop.
*/ */
...@@ -4391,6 +4400,13 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI, ...@@ -4391,6 +4400,13 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
xlogfname, xlogfname,
recoveryStopAfter ? "after" : "before", recoveryStopAfter ? "after" : "before",
timestamptz_to_str(recoveryStopTime)); timestamptz_to_str(recoveryStopTime));
else if (recoveryTarget == RECOVERY_TARGET_NAME)
snprintf(buffer, sizeof(buffer),
"%s%u\t%s\tat restore point \"%s\"\n",
(srcfd < 0) ? "" : "\n",
parentTLI,
xlogfname,
recoveryStopName);
else else
snprintf(buffer, sizeof(buffer), snprintf(buffer, sizeof(buffer),
"%s%u\t%s\tno recovery target specified\n", "%s%u\t%s\tno recovery target specified\n",
...@@ -5178,10 +5194,11 @@ readRecoveryCommandFile(void) ...@@ -5178,10 +5194,11 @@ readRecoveryCommandFile(void)
else if (strcmp(item->name, "recovery_target_time") == 0) else if (strcmp(item->name, "recovery_target_time") == 0)
{ {
/* /*
* if recovery_target_xid specified, then this overrides * if recovery_target_xid or recovery_target_name specified, then
* recovery_target_time * this overrides recovery_target_time
*/ */
if (recoveryTarget == RECOVERY_TARGET_XID) if (recoveryTarget == RECOVERY_TARGET_XID ||
recoveryTarget == RECOVERY_TARGET_NAME)
continue; continue;
recoveryTarget = RECOVERY_TARGET_TIME; recoveryTarget = RECOVERY_TARGET_TIME;
...@@ -5197,6 +5214,26 @@ readRecoveryCommandFile(void) ...@@ -5197,6 +5214,26 @@ readRecoveryCommandFile(void)
(errmsg("recovery_target_time = '%s'", (errmsg("recovery_target_time = '%s'",
timestamptz_to_str(recoveryTargetTime)))); timestamptz_to_str(recoveryTargetTime))));
} }
else if (strcmp(item->name, "recovery_target_name") == 0)
{
/*
* if recovery_target_xid specified, then this overrides
* recovery_target_name
*/
if (recoveryTarget == RECOVERY_TARGET_XID)
continue;
recoveryTarget = RECOVERY_TARGET_NAME;
recoveryTargetName = pstrdup(item->value);
if (strlen(recoveryTargetName) >= MAXFNAMELEN)
ereport(FATAL,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("recovery_target_name is too long")));
ereport(DEBUG2,
(errmsg("recovery_target_name = '%s'",
recoveryTargetName)));
}
else if (strcmp(item->name, "recovery_target_inclusive") == 0) else if (strcmp(item->name, "recovery_target_inclusive") == 0)
{ {
/* /*
...@@ -5411,8 +5448,8 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg) ...@@ -5411,8 +5448,8 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg)
* Returns TRUE if we are stopping, FALSE otherwise. On TRUE return, * Returns TRUE if we are stopping, FALSE otherwise. On TRUE return,
* *includeThis is set TRUE if we should apply this record before stopping. * *includeThis is set TRUE if we should apply this record before stopping.
* *
* We also track the timestamp of the latest applied COMMIT/ABORT record * We also track the timestamp of the latest applied COMMIT/ABORT/RESTORE POINT
* in XLogCtl->recoveryLastXTime, for logging purposes. * record in XLogCtl->recoveryLastXTime, for logging purposes.
* Also, some information is saved in recoveryStopXid et al for use in * Also, some information is saved in recoveryStopXid et al for use in
* annotating the new timeline's history file. * annotating the new timeline's history file.
*/ */
...@@ -5422,9 +5459,10 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis) ...@@ -5422,9 +5459,10 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
bool stopsHere; bool stopsHere;
uint8 record_info; uint8 record_info;
TimestampTz recordXtime; TimestampTz recordXtime;
char recordRPName[MAXFNAMELEN];
/* We only consider stopping at COMMIT or ABORT records */ /* We only consider stopping at COMMIT, ABORT or RESTORE POINT records */
if (record->xl_rmid != RM_XACT_ID) if (record->xl_rmid != RM_XACT_ID && record->xl_rmid != RM_XLOG_ID)
return false; return false;
record_info = record->xl_info & ~XLR_INFO_MASK; record_info = record->xl_info & ~XLR_INFO_MASK;
if (record_info == XLOG_XACT_COMMIT) if (record_info == XLOG_XACT_COMMIT)
...@@ -5441,6 +5479,14 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis) ...@@ -5441,6 +5479,14 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
recordXactAbortData = (xl_xact_abort *) XLogRecGetData(record); recordXactAbortData = (xl_xact_abort *) XLogRecGetData(record);
recordXtime = recordXactAbortData->xact_time; recordXtime = recordXactAbortData->xact_time;
} }
else if (record_info == XLOG_RESTORE_POINT)
{
xl_restore_point *recordRestorePointData;
recordRestorePointData = (xl_restore_point *) XLogRecGetData(record);
recordXtime = recordRestorePointData->rp_time;
strncpy(recordRPName, recordRestorePointData->rp_name, MAXFNAMELEN);
}
else else
return false; return false;
...@@ -5466,6 +5512,20 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis) ...@@ -5466,6 +5512,20 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
if (stopsHere) if (stopsHere)
*includeThis = recoveryTargetInclusive; *includeThis = recoveryTargetInclusive;
} }
else if (recoveryTarget == RECOVERY_TARGET_NAME)
{
/*
* there can be many restore points that share the same name, so we stop
* at the first one
*/
stopsHere = (strcmp(recordRPName, recoveryTargetName) == 0);
/*
* ignore recoveryTargetInclusive because this is not a transaction
* record
*/
*includeThis = false;
}
else else
{ {
/* /*
...@@ -5500,7 +5560,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis) ...@@ -5500,7 +5560,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
recoveryStopXid, recoveryStopXid,
timestamptz_to_str(recoveryStopTime)))); timestamptz_to_str(recoveryStopTime))));
} }
else else if (record_info == XLOG_XACT_ABORT)
{ {
if (recoveryStopAfter) if (recoveryStopAfter)
ereport(LOG, ereport(LOG,
...@@ -5513,6 +5573,15 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis) ...@@ -5513,6 +5573,15 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
recoveryStopXid, recoveryStopXid,
timestamptz_to_str(recoveryStopTime)))); timestamptz_to_str(recoveryStopTime))));
} }
else
{
strncpy(recoveryStopName, recordRPName, MAXFNAMELEN);
ereport(LOG,
(errmsg("recovery stopping at restore point \"%s\", time %s",
recoveryStopName,
timestamptz_to_str(recoveryStopTime))));
}
if (recoveryStopAfter) if (recoveryStopAfter)
SetLatestXTime(recordXtime); SetLatestXTime(recordXtime);
...@@ -5900,6 +5969,10 @@ StartupXLOG(void) ...@@ -5900,6 +5969,10 @@ StartupXLOG(void)
ereport(LOG, ereport(LOG,
(errmsg("starting point-in-time recovery to %s", (errmsg("starting point-in-time recovery to %s",
timestamptz_to_str(recoveryTargetTime)))); timestamptz_to_str(recoveryTargetTime))));
else if (recoveryTarget == RECOVERY_TARGET_NAME)
ereport(LOG,
(errmsg("starting point-in-time recovery to \"%s\"",
recoveryTargetName)));
else else
ereport(LOG, ereport(LOG,
(errmsg("starting archive recovery"))); (errmsg("starting archive recovery")));
...@@ -7989,6 +8062,29 @@ RequestXLogSwitch(void) ...@@ -7989,6 +8062,29 @@ RequestXLogSwitch(void)
return RecPtr; return RecPtr;
} }
/*
* Write a RESTORE POINT record
*/
XLogRecPtr
XLogRestorePoint(const char *rpName)
{
XLogRecPtr RecPtr;
XLogRecData rdata;
xl_restore_point xlrec;
xlrec.rp_time = GetCurrentTimestamp();
strncpy(xlrec.rp_name, rpName, MAXFNAMELEN);
rdata.buffer = InvalidBuffer;
rdata.data = (char *) &xlrec;
rdata.len = sizeof(xl_restore_point);
rdata.next = NULL;
RecPtr = XLogInsert(RM_XLOG_ID, XLOG_RESTORE_POINT, &rdata);
return RecPtr;
}
/* /*
* Check if any of the GUC parameters that are critical for hot standby * Check if any of the GUC parameters that are critical for hot standby
* have changed, and update the value in pg_control file if necessary. * have changed, and update the value in pg_control file if necessary.
...@@ -8181,6 +8277,10 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -8181,6 +8277,10 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
{ {
/* nothing to do here */ /* nothing to do here */
} }
else if (info == XLOG_RESTORE_POINT)
{
/* nothing to do here */
}
else if (info == XLOG_BACKUP_END) else if (info == XLOG_BACKUP_END)
{ {
XLogRecPtr startpoint; XLogRecPtr startpoint;
...@@ -8283,6 +8383,13 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec) ...@@ -8283,6 +8383,13 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
{ {
appendStringInfo(buf, "xlog switch"); appendStringInfo(buf, "xlog switch");
} }
else if (info == XLOG_RESTORE_POINT)
{
xl_restore_point *xlrec = (xl_restore_point *) rec;
appendStringInfo(buf, "restore point: %s", xlrec->rp_name);
}
else if (info == XLOG_BACKUP_END) else if (info == XLOG_BACKUP_END)
{ {
XLogRecPtr startpoint; XLogRecPtr startpoint;
...@@ -9080,6 +9187,51 @@ pg_switch_xlog(PG_FUNCTION_ARGS) ...@@ -9080,6 +9187,51 @@ pg_switch_xlog(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(cstring_to_text(location)); PG_RETURN_TEXT_P(cstring_to_text(location));
} }
/*
* pg_create_restore_point: a named point for restore
*/
Datum
pg_create_restore_point(PG_FUNCTION_ARGS)
{
text *restore_name = PG_GETARG_TEXT_P(0);
char *restore_name_str;
XLogRecPtr restorepoint;
char location[MAXFNAMELEN];
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to create a restore point"))));
if (RecoveryInProgress())
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
(errmsg("recovery is in progress"),
errhint("WAL control functions cannot be executed during recovery."))));
if (!XLogIsNeeded())
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("WAL level not sufficient for creating a restore point"),
errhint("wal_level must be set to \"archive\" or \"hot_standby\" at server start.")));
restore_name_str = text_to_cstring(restore_name);
if (strlen(restore_name_str) >= MAXFNAMELEN)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("value too long for restore point")));
restorepoint = XLogRestorePoint(restore_name_str);
/*
* As a convenience, return the WAL location of the restore point record
*/
snprintf(location, sizeof(location), "%X/%X",
restorepoint.xlogid, restorepoint.xrecoff);
PG_RETURN_TEXT_P(cstring_to_text(location));
}
/* /*
* Report the current WAL write location (same format as pg_start_backup etc) * Report the current WAL write location (same format as pg_start_backup etc)
* *
......
...@@ -184,7 +184,8 @@ typedef enum ...@@ -184,7 +184,8 @@ typedef enum
{ {
RECOVERY_TARGET_UNSET, RECOVERY_TARGET_UNSET,
RECOVERY_TARGET_XID, RECOVERY_TARGET_XID,
RECOVERY_TARGET_TIME RECOVERY_TARGET_TIME,
RECOVERY_TARGET_NAME
} RecoveryTargetType; } RecoveryTargetType;
extern XLogRecPtr XactLastRecEnd; extern XLogRecPtr XactLastRecEnd;
...@@ -302,6 +303,7 @@ extern void InitXLOGAccess(void); ...@@ -302,6 +303,7 @@ extern void InitXLOGAccess(void);
extern void CreateCheckPoint(int flags); extern void CreateCheckPoint(int flags);
extern bool CreateRestartPoint(int flags); extern bool CreateRestartPoint(int flags);
extern void XLogPutNextOid(Oid nextOid); extern void XLogPutNextOid(Oid nextOid);
extern XLogRecPtr XLogRestorePoint(const char *rpName);
extern XLogRecPtr GetRedoRecPtr(void); extern XLogRecPtr GetRedoRecPtr(void);
extern XLogRecPtr GetInsertRecPtr(void); extern XLogRecPtr GetInsertRecPtr(void);
extern XLogRecPtr GetFlushRecPtr(void); extern XLogRecPtr GetFlushRecPtr(void);
......
...@@ -267,6 +267,7 @@ extern XLogRecPtr RequestXLogSwitch(void); ...@@ -267,6 +267,7 @@ extern XLogRecPtr RequestXLogSwitch(void);
extern Datum pg_start_backup(PG_FUNCTION_ARGS); extern Datum pg_start_backup(PG_FUNCTION_ARGS);
extern Datum pg_stop_backup(PG_FUNCTION_ARGS); extern Datum pg_stop_backup(PG_FUNCTION_ARGS);
extern Datum pg_switch_xlog(PG_FUNCTION_ARGS); extern Datum pg_switch_xlog(PG_FUNCTION_ARGS);
extern Datum pg_create_restore_point(PG_FUNCTION_ARGS);
extern Datum pg_current_xlog_location(PG_FUNCTION_ARGS); extern Datum pg_current_xlog_location(PG_FUNCTION_ARGS);
extern Datum pg_current_xlog_insert_location(PG_FUNCTION_ARGS); extern Datum pg_current_xlog_insert_location(PG_FUNCTION_ARGS);
extern Datum pg_last_xlog_receive_location(PG_FUNCTION_ARGS); extern Datum pg_last_xlog_receive_location(PG_FUNCTION_ARGS);
......
...@@ -59,6 +59,7 @@ typedef struct CheckPoint ...@@ -59,6 +59,7 @@ typedef struct CheckPoint
#define XLOG_SWITCH 0x40 #define XLOG_SWITCH 0x40
#define XLOG_BACKUP_END 0x50 #define XLOG_BACKUP_END 0x50
#define XLOG_PARAMETER_CHANGE 0x60 #define XLOG_PARAMETER_CHANGE 0x60
#define XLOG_RESTORE_POINT 0x70
/* /*
......
...@@ -3397,6 +3397,7 @@ DATA(insert OID = 2173 ( pg_stop_backup PGNSP PGUID 12 1 0 0 f f f t f v 0 0 2 ...@@ -3397,6 +3397,7 @@ DATA(insert OID = 2173 ( pg_stop_backup PGNSP PGUID 12 1 0 0 f f f t f v 0 0 2
DESCR("finish taking an online backup"); DESCR("finish taking an online backup");
DATA(insert OID = 2848 ( pg_switch_xlog PGNSP PGUID 12 1 0 0 f f f t f v 0 0 25 "" _null_ _null_ _null_ _null_ pg_switch_xlog _null_ _null_ _null_ )); DATA(insert OID = 2848 ( pg_switch_xlog PGNSP PGUID 12 1 0 0 f f f t f v 0 0 25 "" _null_ _null_ _null_ _null_ pg_switch_xlog _null_ _null_ _null_ ));
DESCR("switch to new xlog file"); DESCR("switch to new xlog file");
DATA(insert OID = 3098 ( pg_create_restore_point PGNSP PGUID 12 1 0 0 f f f t f v 1 0 25 "25" _null_ _null_ _null_ _null_ pg_create_restore_point _null_ _null_ _null_ ));
DATA(insert OID = 2849 ( pg_current_xlog_location PGNSP PGUID 12 1 0 0 f f f t f v 0 0 25 "" _null_ _null_ _null_ _null_ pg_current_xlog_location _null_ _null_ _null_ )); DATA(insert OID = 2849 ( pg_current_xlog_location PGNSP PGUID 12 1 0 0 f f f t f v 0 0 25 "" _null_ _null_ _null_ _null_ pg_current_xlog_location _null_ _null_ _null_ ));
DESCR("current xlog write location"); DESCR("current xlog write location");
DATA(insert OID = 2852 ( pg_current_xlog_insert_location PGNSP PGUID 12 1 0 0 f f f t f v 0 0 25 "" _null_ _null_ _null_ _null_ pg_current_xlog_insert_location _null_ _null_ _null_ )); DATA(insert OID = 2852 ( pg_current_xlog_insert_location PGNSP PGUID 12 1 0 0 f f f t f v 0 0 25 "" _null_ _null_ _null_ _null_ pg_current_xlog_insert_location _null_ _null_ _null_ ));
......
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