Implement archive_timeout feature to force xlog file switches to occur no more
than N seconds apart. This allows a simple, if not very high performance, means of guaranteeing that a PITR archive is no more than N seconds behind real time. Also make pg_current_xlog_location return the WAL Write pointer, add pg_current_xlog_insert_location to return the Insert pointer, and fix pg_xlogfile_name_offset to return its results as a two-element record instead of a smashed-together string, as per recent discussion. Simon Riggs
This commit is contained in:
parent
bb764e94ce
commit
e8ea9e9587
|
@ -1,4 +1,4 @@
|
||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.82 2006/08/06 03:53:43 tgl Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.83 2006/08/17 23:04:02 tgl Exp $ -->
|
||||||
|
|
||||||
<chapter id="backup">
|
<chapter id="backup">
|
||||||
<title>Backup and Restore</title>
|
<title>Backup and Restore</title>
|
||||||
|
@ -492,7 +492,7 @@ tar -cf backup.tar /usr/local/pgsql/data
|
||||||
the archiving will be done. Instead, <productname>PostgreSQL</> lets
|
the archiving will be done. Instead, <productname>PostgreSQL</> lets
|
||||||
the administrator specify a shell command to be executed to copy a
|
the administrator specify a shell command to be executed to copy a
|
||||||
completed segment file to wherever it needs to go. The command could be
|
completed segment file to wherever it needs to go. The command could be
|
||||||
as simple as a <application>cp</>, or it could invoke a complex shell
|
as simple as a <literal>cp</>, or it could invoke a complex shell
|
||||||
script — it's all up to you.
|
script — it's all up to you.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
@ -576,36 +576,6 @@ archive_command = 'test ! -f .../%f && cp %p .../%f'
|
||||||
it is working as you intend.
|
it is working as you intend.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
|
||||||
If you are concerned about being able to recover right up to the
|
|
||||||
current instant, you may want to take additional steps to ensure that
|
|
||||||
the current, partially-filled WAL segment is also copied someplace.
|
|
||||||
This is particularly important if your server generates only little WAL
|
|
||||||
traffic (or has slack periods where it does so), since it could take a
|
|
||||||
long time before a WAL segment file is completely filled and ready to
|
|
||||||
archive. One possible way to handle this is to set up a
|
|
||||||
<application>cron</> job that periodically (once a minute, perhaps)
|
|
||||||
identifies the current WAL segment file and saves it someplace safe.
|
|
||||||
Then the combination of the archived WAL segments and the saved current
|
|
||||||
segment will be enough to ensure you can always restore to within a
|
|
||||||
minute of current time. This behavior is not presently built into
|
|
||||||
<productname>PostgreSQL</> because we did not want to complicate the
|
|
||||||
definition of the <xref linkend="guc-archive-command"> by requiring it
|
|
||||||
to keep track of successively archived, but different, copies of the
|
|
||||||
same WAL file. The <xref linkend="guc-archive-command"> is only
|
|
||||||
invoked on completed WAL segments. Except in the case of retrying a
|
|
||||||
failure, it will be called only once for any given file name.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Another way to limit your exposure to data loss is to call
|
|
||||||
<function>pg_switch_xlog()</> periodically, such as once a minute.
|
|
||||||
This function forces the current WAL segment file to be completed
|
|
||||||
and made available to the archiving command. This approach does
|
|
||||||
not work well for extremely short update intervals, however, since
|
|
||||||
copying a new 16MB segment file every few seconds is expensive.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
In writing your archive command, you should assume that the file names to
|
In writing your archive command, you should assume that the file names to
|
||||||
be archived may be up to 64 characters long and may contain any
|
be archived may be up to 64 characters long and may contain any
|
||||||
|
@ -626,6 +596,29 @@ archive_command = 'test ! -f .../%f && cp %p .../%f'
|
||||||
<xref linkend="runtime-config-file-locations"> for how to relocate the
|
<xref linkend="runtime-config-file-locations"> for how to relocate the
|
||||||
configuration files.
|
configuration files.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The archive command is only invoked on completed WAL segments. Hence,
|
||||||
|
if your server generates only little WAL traffic (or has slack periods
|
||||||
|
where it does so), there could be a long delay between the completion
|
||||||
|
of a transaction and its safe recording in archive storage. To put
|
||||||
|
a limit on how old unarchived data can be, you can set
|
||||||
|
<xref linkend="guc-archive-timeout"> to force the server to switch
|
||||||
|
to a new WAL segment file at least that often. Note that archived
|
||||||
|
files that are ended early due to a forced switch are still the same
|
||||||
|
length as completely full files. It is therefore unwise to set a very
|
||||||
|
short <varname>archive_timeout</> — it will bloat your archive
|
||||||
|
storage. <varname>archive_timeout</> settings of a minute or so are
|
||||||
|
usually reasonable.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Also, you can force a segment switch manually with
|
||||||
|
<function>pg_switch_xlog()</>,
|
||||||
|
if you want to ensure that a just-finished transaction is archived
|
||||||
|
immediately. Other utility functions related to WAL management are
|
||||||
|
listed in <xref linkend="functions-admin-backup-table">.
|
||||||
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="backup-base-backup">
|
<sect2 id="backup-base-backup">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.74 2006/08/15 18:26:58 tgl Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.75 2006/08/17 23:04:03 tgl Exp $ -->
|
||||||
|
|
||||||
<chapter Id="runtime-config">
|
<chapter Id="runtime-config">
|
||||||
<title>Server Configuration</title>
|
<title>Server Configuration</title>
|
||||||
|
@ -1584,6 +1584,35 @@ archive_command = 'copy "%p" /mnt/server/archivedir/"%f"' # Windows
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="guc-archive-timeout" xreflabel="archive_timeout">
|
||||||
|
<term><varname>archive_timeout</varname> (<type>integer</type>)</term>
|
||||||
|
<indexterm>
|
||||||
|
<primary><varname>archive_timeout</> configuration parameter</primary>
|
||||||
|
</indexterm>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The <xref linkend="guc-archive-command"> is only invoked on completed
|
||||||
|
WAL segments. Hence,
|
||||||
|
if your server generates only little WAL traffic (or has slack periods
|
||||||
|
where it does so), there could be a long delay between the completion
|
||||||
|
of a transaction and its safe recording in archive storage. To put
|
||||||
|
a limit on how old unarchived data can be, you can set
|
||||||
|
<varname>archive_timeout</> to force the server to switch
|
||||||
|
to a new WAL segment file periodically. When this parameter is
|
||||||
|
greater than zero, the server will switch to a new segment file
|
||||||
|
whenever this many seconds elapse since the last segment file switch.
|
||||||
|
Note that archived
|
||||||
|
files that are ended early due to a forced switch are still the same
|
||||||
|
length as completely full files. It is therefore unwise to set a very
|
||||||
|
short <varname>archive_timeout</> — it will bloat your archive
|
||||||
|
storage. <varname>archive_timeout</> settings of a minute or so are
|
||||||
|
usually reasonable.
|
||||||
|
This parameter can only be set in the <filename>postgresql.conf</>
|
||||||
|
file or on the server command line.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</sect2>
|
</sect2>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.329 2006/08/06 03:53:43 tgl Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.330 2006/08/17 23:04:03 tgl Exp $ -->
|
||||||
|
|
||||||
<chapter id="functions">
|
<chapter id="functions">
|
||||||
<title>Functions and Operators</title>
|
<title>Functions and Operators</title>
|
||||||
|
@ -10148,6 +10148,9 @@ SELECT set_config('log_statement_stats', 'off', false);
|
||||||
<indexterm zone="functions-admin">
|
<indexterm zone="functions-admin">
|
||||||
<primary>pg_current_xlog_location</primary>
|
<primary>pg_current_xlog_location</primary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
<indexterm zone="functions-admin">
|
||||||
|
<primary>pg_current_xlog_insert_location</primary>
|
||||||
|
</indexterm>
|
||||||
<indexterm zone="functions-admin">
|
<indexterm zone="functions-admin">
|
||||||
<primary>pg_xlogfile_name_offset</primary>
|
<primary>pg_xlogfile_name_offset</primary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
@ -10199,13 +10202,20 @@ SELECT set_config('log_statement_stats', 'off', false);
|
||||||
<literal><function>pg_current_xlog_location</function>()</literal>
|
<literal><function>pg_current_xlog_location</function>()</literal>
|
||||||
</entry>
|
</entry>
|
||||||
<entry><type>text</type></entry>
|
<entry><type>text</type></entry>
|
||||||
<entry>Get current xlog location</entry>
|
<entry>Get current xlog write location</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<literal><function>pg_current_xlog_insert_location</function>()</literal>
|
||||||
|
</entry>
|
||||||
|
<entry><type>text</type></entry>
|
||||||
|
<entry>Get current xlog insert location</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<entry>
|
||||||
<literal><function>pg_xlogfile_name_offset</function>(<parameter>location</> <type>text</>)</literal>
|
<literal><function>pg_xlogfile_name_offset</function>(<parameter>location</> <type>text</>)</literal>
|
||||||
</entry>
|
</entry>
|
||||||
<entry><type>text</type></entry>
|
<entry><type>text</>, <type>integer</></entry>
|
||||||
<entry>Convert xlog location string to filename and decimal byte offset within file</entry>
|
<entry>Convert xlog location string to filename and decimal byte offset within file</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
|
@ -10258,9 +10268,17 @@ postgres=# select pg_start_backup('label_goes_here');
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<function>pg_current_xlog_location</> displays the current xlog insertion
|
<function>pg_current_xlog_location</> displays the current xlog write
|
||||||
point in the same format used by the above functions. This is a
|
location in the same format used by the above functions. Similarly
|
||||||
read-only operation and does not require superuser permissions.
|
<function>pg_current_xlog_insert_location</> displays the current xlog
|
||||||
|
insertion point. The insertion point is the <quote>logical</> end of xlog
|
||||||
|
at any instant, while the write location is the end of what has actually
|
||||||
|
been written out from the server's internal buffers. The write location
|
||||||
|
is the end of what can be examined from outside the server, and is usually
|
||||||
|
what you want if you are interested in archiving partially-complete xlog
|
||||||
|
files. The insertion point is made available primarily for server
|
||||||
|
debugging purposes. These are both read-only operations and do not
|
||||||
|
require superuser permissions.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
@ -10268,10 +10286,10 @@ postgres=# select pg_start_backup('label_goes_here');
|
||||||
corresponding xlog filename and byte offset from the results of any of the
|
corresponding xlog filename and byte offset from the results of any of the
|
||||||
above functions. For example:
|
above functions. For example:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
postgres=# select pg_xlogfile_name_offset(pg_stop_backup());
|
postgres=# select * from pg_xlogfile_name_offset(pg_stop_backup());
|
||||||
pg_xlogfile_name_offset
|
file_name | file_offset
|
||||||
----------------------------------
|
--------------------------+-------------
|
||||||
00000001000000000000000D 4039624
|
00000001000000000000000D | 4039624
|
||||||
(1 row)
|
(1 row)
|
||||||
</programlisting>
|
</programlisting>
|
||||||
Similarly, <function>pg_xlogfile_name</> extracts just the xlog filename.
|
Similarly, <function>pg_xlogfile_name</> extracts just the xlog filename.
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.247 2006/08/07 16:57:56 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.248 2006/08/17 23:04:05 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include "access/clog.h"
|
#include "access/clog.h"
|
||||||
|
#include "access/heapam.h"
|
||||||
#include "access/multixact.h"
|
#include "access/multixact.h"
|
||||||
#include "access/subtrans.h"
|
#include "access/subtrans.h"
|
||||||
#include "access/transam.h"
|
#include "access/transam.h"
|
||||||
|
@ -32,6 +33,8 @@
|
||||||
#include "access/xlogutils.h"
|
#include "access/xlogutils.h"
|
||||||
#include "catalog/catversion.h"
|
#include "catalog/catversion.h"
|
||||||
#include "catalog/pg_control.h"
|
#include "catalog/pg_control.h"
|
||||||
|
#include "catalog/pg_type.h"
|
||||||
|
#include "funcapi.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "pgstat.h"
|
#include "pgstat.h"
|
||||||
#include "postmaster/bgwriter.h"
|
#include "postmaster/bgwriter.h"
|
||||||
|
@ -128,6 +131,7 @@
|
||||||
/* User-settable parameters */
|
/* User-settable parameters */
|
||||||
int CheckPointSegments = 3;
|
int CheckPointSegments = 3;
|
||||||
int XLOGbuffers = 8;
|
int XLOGbuffers = 8;
|
||||||
|
int XLogArchiveTimeout = 0;
|
||||||
char *XLogArchiveCommand = NULL;
|
char *XLogArchiveCommand = NULL;
|
||||||
char *XLOG_sync_method = NULL;
|
char *XLOG_sync_method = NULL;
|
||||||
const char XLOG_sync_method_default[] = DEFAULT_SYNC_METHOD_STR;
|
const char XLOG_sync_method_default[] = DEFAULT_SYNC_METHOD_STR;
|
||||||
|
@ -347,8 +351,9 @@ typedef struct XLogCtlInsert
|
||||||
*/
|
*/
|
||||||
typedef struct XLogCtlWrite
|
typedef struct XLogCtlWrite
|
||||||
{
|
{
|
||||||
XLogwrtResult LogwrtResult; /* current value of LogwrtResult */
|
XLogwrtResult LogwrtResult; /* current value of LogwrtResult */
|
||||||
int curridx; /* cache index of next block to write */
|
int curridx; /* cache index of next block to write */
|
||||||
|
time_t lastSegSwitchTime; /* time of last xlog segment switch */
|
||||||
} XLogCtlWrite;
|
} XLogCtlWrite;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1660,7 +1665,8 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
|
||||||
* switch.
|
* switch.
|
||||||
*
|
*
|
||||||
* This is also the right place to notify the Archiver that the
|
* This is also the right place to notify the Archiver that the
|
||||||
* segment is ready to copy to archival storage.
|
* segment is ready to copy to archival storage, and to update
|
||||||
|
* the timer for archive_timeout.
|
||||||
*/
|
*/
|
||||||
if (finishing_seg || (xlog_switch && last_iteration))
|
if (finishing_seg || (xlog_switch && last_iteration))
|
||||||
{
|
{
|
||||||
|
@ -1669,6 +1675,8 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
|
||||||
|
|
||||||
if (XLogArchivingActive())
|
if (XLogArchivingActive())
|
||||||
XLogArchiveNotifySeg(openLogId, openLogSeg);
|
XLogArchiveNotifySeg(openLogId, openLogSeg);
|
||||||
|
|
||||||
|
Write->lastSegSwitchTime = time(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5124,6 +5132,9 @@ StartupXLOG(void)
|
||||||
ControlFile->time = time(NULL);
|
ControlFile->time = time(NULL);
|
||||||
UpdateControlFile();
|
UpdateControlFile();
|
||||||
|
|
||||||
|
/* start the archive_timeout timer running */
|
||||||
|
XLogCtl->Write.lastSegSwitchTime = ControlFile->time;
|
||||||
|
|
||||||
/* Start up the commit log and related stuff, too */
|
/* Start up the commit log and related stuff, too */
|
||||||
StartupCLOG();
|
StartupCLOG();
|
||||||
StartupSUBTRANS(oldestActiveXID);
|
StartupSUBTRANS(oldestActiveXID);
|
||||||
|
@ -5307,6 +5318,22 @@ GetRedoRecPtr(void)
|
||||||
return RedoRecPtr;
|
return RedoRecPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the time of the last xlog segment switch
|
||||||
|
*/
|
||||||
|
time_t
|
||||||
|
GetLastSegSwitchTime(void)
|
||||||
|
{
|
||||||
|
time_t result;
|
||||||
|
|
||||||
|
/* Need WALWriteLock, but shared lock is sufficient */
|
||||||
|
LWLockAcquire(WALWriteLock, LW_SHARED);
|
||||||
|
result = XLogCtl->Write.lastSegSwitchTime;
|
||||||
|
LWLockRelease(WALWriteLock);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GetRecentNextXid - get the nextXid value saved by the most recent checkpoint
|
* GetRecentNextXid - get the nextXid value saved by the most recent checkpoint
|
||||||
*
|
*
|
||||||
|
@ -5728,7 +5755,7 @@ XLogPutNextOid(Oid nextOid)
|
||||||
* or the end+1 address of the prior segment if we did not need to
|
* or the end+1 address of the prior segment if we did not need to
|
||||||
* write a switch record because we are already at segment start.
|
* write a switch record because we are already at segment start.
|
||||||
*/
|
*/
|
||||||
static XLogRecPtr
|
XLogRecPtr
|
||||||
RequestXLogSwitch(void)
|
RequestXLogSwitch(void)
|
||||||
{
|
{
|
||||||
XLogRecPtr RecPtr;
|
XLogRecPtr RecPtr;
|
||||||
|
@ -6335,10 +6362,43 @@ pg_switch_xlog(PG_FUNCTION_ARGS)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Report the current WAL location (same format as pg_start_backup etc)
|
* Report the current WAL write location (same format as pg_start_backup etc)
|
||||||
|
*
|
||||||
|
* This is useful for determining how much of WAL is visible to an external
|
||||||
|
* archiving process. Note that the data before this point is written out
|
||||||
|
* to the kernel, but is not necessarily synced to disk.
|
||||||
*/
|
*/
|
||||||
Datum
|
Datum
|
||||||
pg_current_xlog_location(PG_FUNCTION_ARGS)
|
pg_current_xlog_location(PG_FUNCTION_ARGS)
|
||||||
|
{
|
||||||
|
text *result;
|
||||||
|
char location[MAXFNAMELEN];
|
||||||
|
|
||||||
|
/* Make sure we have an up-to-date local LogwrtResult */
|
||||||
|
{
|
||||||
|
/* use volatile pointer to prevent code rearrangement */
|
||||||
|
volatile XLogCtlData *xlogctl = XLogCtl;
|
||||||
|
|
||||||
|
SpinLockAcquire(&xlogctl->info_lck);
|
||||||
|
LogwrtResult = xlogctl->LogwrtResult;
|
||||||
|
SpinLockRelease(&xlogctl->info_lck);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(location, sizeof(location), "%X/%X",
|
||||||
|
LogwrtResult.Write.xlogid, LogwrtResult.Write.xrecoff);
|
||||||
|
|
||||||
|
result = DatumGetTextP(DirectFunctionCall1(textin,
|
||||||
|
CStringGetDatum(location)));
|
||||||
|
PG_RETURN_TEXT_P(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Report the current WAL insert location (same format as pg_start_backup etc)
|
||||||
|
*
|
||||||
|
* This function is mostly for debugging purposes.
|
||||||
|
*/
|
||||||
|
Datum
|
||||||
|
pg_current_xlog_insert_location(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *result;
|
text *result;
|
||||||
XLogCtlInsert *Insert = &XLogCtl->Insert;
|
XLogCtlInsert *Insert = &XLogCtl->Insert;
|
||||||
|
@ -6372,7 +6432,6 @@ Datum
|
||||||
pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
|
pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *location = PG_GETARG_TEXT_P(0);
|
text *location = PG_GETARG_TEXT_P(0);
|
||||||
text *result;
|
|
||||||
char *locationstr;
|
char *locationstr;
|
||||||
unsigned int uxlogid;
|
unsigned int uxlogid;
|
||||||
unsigned int uxrecoff;
|
unsigned int uxrecoff;
|
||||||
|
@ -6381,7 +6440,15 @@ pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
|
||||||
uint32 xrecoff;
|
uint32 xrecoff;
|
||||||
XLogRecPtr locationpoint;
|
XLogRecPtr locationpoint;
|
||||||
char xlogfilename[MAXFNAMELEN];
|
char xlogfilename[MAXFNAMELEN];
|
||||||
|
Datum values[2];
|
||||||
|
bool isnull[2];
|
||||||
|
TupleDesc resultTupleDesc;
|
||||||
|
HeapTuple resultHeapTuple;
|
||||||
|
Datum result;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read input and parse
|
||||||
|
*/
|
||||||
locationstr = DatumGetCString(DirectFunctionCall1(textout,
|
locationstr = DatumGetCString(DirectFunctionCall1(textout,
|
||||||
PointerGetDatum(location)));
|
PointerGetDatum(location)));
|
||||||
|
|
||||||
|
@ -6394,18 +6461,44 @@ pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
|
||||||
locationpoint.xlogid = uxlogid;
|
locationpoint.xlogid = uxlogid;
|
||||||
locationpoint.xrecoff = uxrecoff;
|
locationpoint.xrecoff = uxrecoff;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Construct a tuple descriptor for the result row. This must match
|
||||||
|
* this function's pg_proc entry!
|
||||||
|
*/
|
||||||
|
resultTupleDesc = CreateTemplateTupleDesc(2, false);
|
||||||
|
TupleDescInitEntry(resultTupleDesc, (AttrNumber) 1, "file_name",
|
||||||
|
TEXTOID, -1, 0);
|
||||||
|
TupleDescInitEntry(resultTupleDesc, (AttrNumber) 2, "file_offset",
|
||||||
|
INT4OID, -1, 0);
|
||||||
|
|
||||||
|
resultTupleDesc = BlessTupleDesc(resultTupleDesc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* xlogfilename
|
||||||
|
*/
|
||||||
XLByteToPrevSeg(locationpoint, xlogid, xlogseg);
|
XLByteToPrevSeg(locationpoint, xlogid, xlogseg);
|
||||||
XLogFileName(xlogfilename, ThisTimeLineID, xlogid, xlogseg);
|
XLogFileName(xlogfilename, ThisTimeLineID, xlogid, xlogseg);
|
||||||
|
|
||||||
xrecoff = locationpoint.xrecoff - xlogseg * XLogSegSize;
|
values[0] = DirectFunctionCall1(textin,
|
||||||
snprintf(xlogfilename + strlen(xlogfilename),
|
CStringGetDatum(xlogfilename));
|
||||||
sizeof(xlogfilename) - strlen(xlogfilename),
|
isnull[0] = false;
|
||||||
" %u",
|
|
||||||
(unsigned int) xrecoff);
|
|
||||||
|
|
||||||
result = DatumGetTextP(DirectFunctionCall1(textin,
|
/*
|
||||||
CStringGetDatum(xlogfilename)));
|
* offset
|
||||||
PG_RETURN_TEXT_P(result);
|
*/
|
||||||
|
xrecoff = locationpoint.xrecoff - xlogseg * XLogSegSize;
|
||||||
|
|
||||||
|
values[1] = UInt32GetDatum(xrecoff);
|
||||||
|
isnull[1] = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tuple jam: Having first prepared your Datums, then squash together
|
||||||
|
*/
|
||||||
|
resultHeapTuple = heap_form_tuple(resultTupleDesc, values, isnull);
|
||||||
|
|
||||||
|
result = HeapTupleGetDatum(resultHeapTuple);
|
||||||
|
|
||||||
|
PG_RETURN_DATUM(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/postmaster/bgwriter.c,v 1.26 2006/07/14 14:52:22 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/postmaster/bgwriter.c,v 1.27 2006/08/17 23:04:06 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -46,6 +46,7 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "access/xlog_internal.h"
|
||||||
#include "libpq/pqsignal.h"
|
#include "libpq/pqsignal.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "postmaster/bgwriter.h"
|
#include "postmaster/bgwriter.h"
|
||||||
|
@ -144,6 +145,7 @@ static bool am_bg_writer = false;
|
||||||
static bool ckpt_active = false;
|
static bool ckpt_active = false;
|
||||||
|
|
||||||
static time_t last_checkpoint_time;
|
static time_t last_checkpoint_time;
|
||||||
|
static time_t last_xlog_switch_time;
|
||||||
|
|
||||||
|
|
||||||
static void bg_quickdie(SIGNAL_ARGS);
|
static void bg_quickdie(SIGNAL_ARGS);
|
||||||
|
@ -205,10 +207,10 @@ BackgroundWriterMain(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize so that first time-driven checkpoint happens at the correct
|
* Initialize so that first time-driven event happens at the correct
|
||||||
* time.
|
* time.
|
||||||
*/
|
*/
|
||||||
last_checkpoint_time = time(NULL);
|
last_checkpoint_time = last_xlog_switch_time = time(NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a resource owner to keep track of our resources (currently
|
* Create a resource owner to keep track of our resources (currently
|
||||||
|
@ -403,6 +405,49 @@ BackgroundWriterMain(void)
|
||||||
else
|
else
|
||||||
BgBufferSync();
|
BgBufferSync();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for archive_timeout, if so, switch xlog files. First
|
||||||
|
* we do a quick check using possibly-stale local state.
|
||||||
|
*/
|
||||||
|
if (XLogArchiveTimeout > 0 &&
|
||||||
|
(int) (now - last_xlog_switch_time) >= XLogArchiveTimeout)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Update local state ... note that last_xlog_switch_time is
|
||||||
|
* the last time a switch was performed *or requested*.
|
||||||
|
*/
|
||||||
|
time_t last_time = GetLastSegSwitchTime();
|
||||||
|
|
||||||
|
last_xlog_switch_time = Max(last_xlog_switch_time, last_time);
|
||||||
|
|
||||||
|
/* if we did a checkpoint, 'now' might be stale too */
|
||||||
|
if (do_checkpoint)
|
||||||
|
now = time(NULL);
|
||||||
|
|
||||||
|
/* Now we can do the real check */
|
||||||
|
if ((int) (now - last_xlog_switch_time) >= XLogArchiveTimeout)
|
||||||
|
{
|
||||||
|
XLogRecPtr switchpoint;
|
||||||
|
|
||||||
|
/* OK, it's time to switch */
|
||||||
|
switchpoint = RequestXLogSwitch();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the returned pointer points exactly to a segment
|
||||||
|
* boundary, assume nothing happened.
|
||||||
|
*/
|
||||||
|
if ((switchpoint.xrecoff % XLogSegSize) != 0)
|
||||||
|
ereport(DEBUG1,
|
||||||
|
(errmsg("xlog switch forced (archive_timeout=%d)",
|
||||||
|
XLogArchiveTimeout)));
|
||||||
|
/*
|
||||||
|
* Update state in any case, so we don't retry constantly
|
||||||
|
* when the system is idle.
|
||||||
|
*/
|
||||||
|
last_xlog_switch_time = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Nap for the configured time, or sleep for 10 seconds if there is no
|
* Nap for the configured time, or sleep for 10 seconds if there is no
|
||||||
* bgwriter activity configured.
|
* bgwriter activity configured.
|
||||||
|
@ -417,9 +462,12 @@ BackgroundWriterMain(void)
|
||||||
if ((bgwriter_all_percent > 0.0 && bgwriter_all_maxpages > 0) ||
|
if ((bgwriter_all_percent > 0.0 && bgwriter_all_maxpages > 0) ||
|
||||||
(bgwriter_lru_percent > 0.0 && bgwriter_lru_maxpages > 0))
|
(bgwriter_lru_percent > 0.0 && bgwriter_lru_maxpages > 0))
|
||||||
udelay = BgWriterDelay * 1000L;
|
udelay = BgWriterDelay * 1000L;
|
||||||
|
else if (XLogArchiveTimeout > 0)
|
||||||
|
udelay = 1000000L; /* One second */
|
||||||
else
|
else
|
||||||
udelay = 10000000L;
|
udelay = 10000000L; /* Ten seconds */
|
||||||
while (udelay > 1000000L)
|
|
||||||
|
while (udelay > 999999L)
|
||||||
{
|
{
|
||||||
if (got_SIGHUP || checkpoint_requested || shutdown_requested)
|
if (got_SIGHUP || checkpoint_requested || shutdown_requested)
|
||||||
break;
|
break;
|
||||||
|
@ -427,6 +475,7 @@ BackgroundWriterMain(void)
|
||||||
AbsorbFsyncRequests();
|
AbsorbFsyncRequests();
|
||||||
udelay -= 1000000L;
|
udelay -= 1000000L;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(got_SIGHUP || checkpoint_requested || shutdown_requested))
|
if (!(got_SIGHUP || checkpoint_requested || shutdown_requested))
|
||||||
pg_usleep(udelay);
|
pg_usleep(udelay);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.342 2006/08/15 18:26:59 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.343 2006/08/17 23:04:06 tgl Exp $
|
||||||
*
|
*
|
||||||
*--------------------------------------------------------------------
|
*--------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -1001,7 +1001,7 @@ static struct config_bool ConfigureNamesBool[] =
|
||||||
|
|
||||||
{
|
{
|
||||||
{"ignore_system_indexes", PGC_BACKEND, DEVELOPER_OPTIONS,
|
{"ignore_system_indexes", PGC_BACKEND, DEVELOPER_OPTIONS,
|
||||||
gettext_noop("Disabled reading from system indexes."),
|
gettext_noop("Disables reading from system indexes."),
|
||||||
gettext_noop("It does not prevent updating the indexes, so it is safe "
|
gettext_noop("It does not prevent updating the indexes, so it is safe "
|
||||||
"to use. The worst consequence is slowness."),
|
"to use. The worst consequence is slowness."),
|
||||||
GUC_NOT_IN_SAMPLE
|
GUC_NOT_IN_SAMPLE
|
||||||
|
@ -1019,6 +1019,16 @@ static struct config_bool ConfigureNamesBool[] =
|
||||||
|
|
||||||
static struct config_int ConfigureNamesInt[] =
|
static struct config_int ConfigureNamesInt[] =
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
{"archive_timeout", PGC_SIGHUP, WAL_SETTINGS,
|
||||||
|
gettext_noop("Forces a switch to the next xlog file if a "
|
||||||
|
"new file has not been started within N seconds."),
|
||||||
|
NULL,
|
||||||
|
GUC_UNIT_S
|
||||||
|
},
|
||||||
|
&XLogArchiveTimeout,
|
||||||
|
0, 0, INT_MAX, NULL, NULL
|
||||||
|
},
|
||||||
{
|
{
|
||||||
{"post_auth_delay", PGC_BACKEND, DEVELOPER_OPTIONS,
|
{"post_auth_delay", PGC_BACKEND, DEVELOPER_OPTIONS,
|
||||||
gettext_noop("Waits N seconds on connection startup after authentication."),
|
gettext_noop("Waits N seconds on connection startup after authentication."),
|
||||||
|
|
|
@ -167,8 +167,9 @@
|
||||||
|
|
||||||
# - Archiving -
|
# - Archiving -
|
||||||
|
|
||||||
#archive_command = '' # command to use to archive a logfile
|
#archive_command = '' # command to use to archive a logfile segment
|
||||||
# segment
|
#archive_timeout = 0 # force a logfile segment switch after this
|
||||||
|
# many seconds; 0 is off
|
||||||
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.72 2006/07/13 16:49:19 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.73 2006/08/17 23:04:08 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef XLOG_H
|
#ifndef XLOG_H
|
||||||
#define XLOG_H
|
#define XLOG_H
|
||||||
|
@ -139,6 +139,7 @@ extern XLogRecPtr ProcLastRecEnd;
|
||||||
extern int CheckPointSegments;
|
extern int CheckPointSegments;
|
||||||
extern int XLOGbuffers;
|
extern int XLOGbuffers;
|
||||||
extern char *XLogArchiveCommand;
|
extern char *XLogArchiveCommand;
|
||||||
|
extern int XLogArchiveTimeout;
|
||||||
extern char *XLOG_sync_method;
|
extern char *XLOG_sync_method;
|
||||||
extern const char XLOG_sync_method_default[];
|
extern const char XLOG_sync_method_default[];
|
||||||
|
|
||||||
|
|
|
@ -11,11 +11,13 @@
|
||||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.15 2006/08/07 16:57:57 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.16 2006/08/17 23:04:08 tgl Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef XLOG_INTERNAL_H
|
#ifndef XLOG_INTERNAL_H
|
||||||
#define XLOG_INTERNAL_H
|
#define XLOG_INTERNAL_H
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "access/xlog.h"
|
#include "access/xlog.h"
|
||||||
#include "fmgr.h"
|
#include "fmgr.h"
|
||||||
#include "storage/block.h"
|
#include "storage/block.h"
|
||||||
|
@ -237,6 +239,12 @@ typedef struct RmgrData
|
||||||
|
|
||||||
extern const RmgrData RmgrTable[];
|
extern const RmgrData RmgrTable[];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exported to support xlog switching from bgwriter
|
||||||
|
*/
|
||||||
|
extern time_t GetLastSegSwitchTime(void);
|
||||||
|
extern XLogRecPtr RequestXLogSwitch(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These aren't in xlog.h because I'd rather not include fmgr.h there.
|
* These aren't in xlog.h because I'd rather not include fmgr.h there.
|
||||||
*/
|
*/
|
||||||
|
@ -244,6 +252,7 @@ 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_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_xlogfile_name_offset(PG_FUNCTION_ARGS);
|
extern Datum pg_xlogfile_name_offset(PG_FUNCTION_ARGS);
|
||||||
extern Datum pg_xlogfile_name(PG_FUNCTION_ARGS);
|
extern Datum pg_xlogfile_name(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.349 2006/08/12 02:52:06 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.350 2006/08/17 23:04:08 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -53,6 +53,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 200608101
|
#define CATALOG_VERSION_NO 200608171
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.420 2006/08/06 03:53:44 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.421 2006/08/17 23:04:10 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* The script catalog/genbki.sh reads this file and generates .bki
|
* The script catalog/genbki.sh reads this file and generates .bki
|
||||||
|
@ -3104,8 +3104,10 @@ DESCR("Finish taking an online backup");
|
||||||
DATA(insert OID = 2848 ( pg_switch_xlog PGNSP PGUID 12 f f t f v 0 25 "" _null_ _null_ _null_ pg_switch_xlog - _null_ ));
|
DATA(insert OID = 2848 ( pg_switch_xlog PGNSP PGUID 12 f f t f v 0 25 "" _null_ _null_ _null_ pg_switch_xlog - _null_ ));
|
||||||
DESCR("Switch to new xlog file");
|
DESCR("Switch to new xlog file");
|
||||||
DATA(insert OID = 2849 ( pg_current_xlog_location PGNSP PGUID 12 f f t f v 0 25 "" _null_ _null_ _null_ pg_current_xlog_location - _null_ ));
|
DATA(insert OID = 2849 ( pg_current_xlog_location PGNSP PGUID 12 f f t f v 0 25 "" _null_ _null_ _null_ pg_current_xlog_location - _null_ ));
|
||||||
DESCR("current xlog location");
|
DESCR("current xlog write location");
|
||||||
DATA(insert OID = 2850 ( pg_xlogfile_name_offset PGNSP PGUID 12 f f t f i 1 25 "25" _null_ _null_ _null_ pg_xlogfile_name_offset - _null_ ));
|
DATA(insert OID = 2852 ( pg_current_xlog_insert_location PGNSP PGUID 12 f f t f v 0 25 "" _null_ _null_ _null_ pg_current_xlog_insert_location - _null_ ));
|
||||||
|
DESCR("current xlog insert location");
|
||||||
|
DATA(insert OID = 2850 ( pg_xlogfile_name_offset PGNSP PGUID 12 f f t f i 1 2249 "25" "{25,25,23}" "{i,o,o}" "{wal_location,file_name,file_offset}" pg_xlogfile_name_offset - _null_ ));
|
||||||
DESCR("xlog filename and byte offset, given an xlog location");
|
DESCR("xlog filename and byte offset, given an xlog location");
|
||||||
DATA(insert OID = 2851 ( pg_xlogfile_name PGNSP PGUID 12 f f t f i 1 25 "25" _null_ _null_ _null_ pg_xlogfile_name - _null_ ));
|
DATA(insert OID = 2851 ( pg_xlogfile_name PGNSP PGUID 12 f f t f i 1 25 "25" _null_ _null_ _null_ pg_xlogfile_name - _null_ ));
|
||||||
DESCR("xlog filename, given an xlog location");
|
DESCR("xlog filename, given an xlog location");
|
||||||
|
|
Loading…
Reference in New Issue