Commit 48188e16 authored by Tom Lane's avatar Tom Lane

Fix recently-understood problems with handling of XID freezing, particularly

in PITR scenarios.  We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases.  Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId.  Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done.  Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database.  initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs.  Heikki Linnakangas, Simon Riggs, and Tom Lane.
parent 10c70b86
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.135 2006/10/23 18:10:30 petere Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.136 2006/11/05 22:42:06 tgl Exp $ -->
<!-- <!--
Documentation of the system catalogs, directed toward PostgreSQL developers Documentation of the system catalogs, directed toward PostgreSQL developers
--> -->
...@@ -1241,6 +1241,20 @@ ...@@ -1241,6 +1241,20 @@
<entry></entry> <entry></entry>
<entry>Custom <varname>vacuum_cost_limit</> parameter</entry> <entry>Custom <varname>vacuum_cost_limit</> parameter</entry>
</row> </row>
<row>
<entry><structfield>freeze_min_age</structfield></entry>
<entry><type>integer</type></entry>
<entry></entry>
<entry>Custom <varname>vacuum_freeze_min_age</> parameter</entry>
</row>
<row>
<entry><structfield>freeze_max_age</structfield></entry>
<entry><type>integer</type></entry>
<entry></entry>
<entry>Custom <varname>autovacuum_freeze_max_age</> parameter</entry>
</row>
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
...@@ -1258,6 +1272,17 @@ ...@@ -1258,6 +1272,17 @@
live tuples currently estimated to be in the relation. live tuples currently estimated to be in the relation.
</para> </para>
<para>
Also, the autovacuum daemon will perform a <command>VACUUM</> operation
to prevent transaction ID wraparound if the table's
<structname>pg_class</>.<structfield>relfrozenxid</> field attains an age
of more than <structfield>freeze_max_age</> transactions, whether the table
has been changed or not. The system will launch autovacuum to perform
such <command>VACUUM</>s even if autovacuum is otherwise disabled.
See <xref linkend="vacuum-for-wraparound"> for more about wraparound
prevention.
</para>
<para> <para>
Any of the numerical fields can contain <literal>-1</> (or indeed Any of the numerical fields can contain <literal>-1</> (or indeed
any negative value) to indicate that the system-wide default should any negative value) to indicate that the system-wide default should
...@@ -1266,6 +1291,10 @@ ...@@ -1266,6 +1291,10 @@
<varname>autovacuum_vacuum_cost_delay</> configuration parameter, <varname>autovacuum_vacuum_cost_delay</> configuration parameter,
or from <varname>vacuum_cost_delay</> if the former is set to a negative or from <varname>vacuum_cost_delay</> if the former is set to a negative
value. The same applies to <structfield>vac_cost_limit</>. value. The same applies to <structfield>vac_cost_limit</>.
Also, autovacuum will ignore attempts to set a per-table
freeze_max_age larger than the system-wide setting (it can only be set
smaller), and the freeze_min_age value will be limited to half the
system-wide <varname>autovacuum_freeze_max_age</> setting.
</para> </para>
</sect1> </sect1>
...@@ -1633,26 +1662,15 @@ ...@@ -1633,26 +1662,15 @@
</row> </row>
<row> <row>
<entry><structfield>relminxid</structfield></entry> <entry><structfield>relfrozenxid</structfield></entry>
<entry><type>xid</type></entry> <entry><type>xid</type></entry>
<entry></entry> <entry></entry>
<entry> <entry>
The minimum transaction ID present in all rows in this table. This All transaction IDs before this one have been replaced with a permanent
value is used to determine the database-global (<quote>frozen</>) transaction ID in this table. This is used to track
<structname>pg_database</>.<structfield>datminxid</> value. whether the table needs to be vacuumed in order to prevent transaction
</entry> ID wraparound or to allow <literal>pg_clog</> to be shrunk. Zero
</row> (<symbol>InvalidTransactionId</symbol>) if the relation is not a table.
<row>
<entry><structfield>relvacuumxid</structfield></entry>
<entry><type>xid</type></entry>
<entry></entry>
<entry>
The transaction ID that was used as cleaning point as of the last vacuum
operation. All rows inserted, updated or deleted in this table by
transactions whose IDs are below this one have been marked as known good
or deleted. This is used to determine the database-global
<structname>pg_database</>.<structfield>datvacuumxid</> value.
</entry> </entry>
</row> </row>
...@@ -2035,31 +2053,16 @@ ...@@ -2035,31 +2053,16 @@
</row> </row>
<row> <row>
<entry><structfield>datvacuumxid</structfield></entry> <entry><structfield>datfrozenxid</structfield></entry>
<entry><type>xid</type></entry>
<entry></entry>
<entry>
The transaction ID that was used as cleaning point as of the last vacuum
operation. All rows inserted or deleted by transaction IDs before this one
have been marked as known good or deleted. This
is used to determine when commit-log space can be recycled.
If <symbol>InvalidTransactionId</symbol>, then the minimum is unknown and can be
determined by scanning <structname>pg_class</>.<structfield>relvacuumxid</>.
</entry>
</row>
<row>
<entry><structfield>datminxid</structfield></entry>
<entry><type>xid</type></entry> <entry><type>xid</type></entry>
<entry></entry> <entry></entry>
<entry> <entry>
The minimum transaction ID present in all tables in this database. All transaction IDs before this one have been replaced with a permanent
All rows inserted by transaction IDs before this one have been (<quote>frozen</>) transaction ID in this database. This is used to
relabeled with a permanent (<quote>frozen</>) transaction ID in this track whether the database needs to be vacuumed in order to prevent
database. This is useful to check whether a database must be transaction ID wraparound or to allow <literal>pg_clog</> to be shrunk.
vacuumed soon to avoid transaction ID wrap-around problems. It is the minimum of the per-table
If <symbol>InvalidTransactionId</symbol>, then the minimum is unknown and can be <structname>pg_class</>.<structfield>relfrozenxid</> values.
determined by scanning <structname>pg_class</>.<structfield>relminxid</>.
</entry> </entry>
</row> </row>
......
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.93 2006/11/04 18:20:27 tgl Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.94 2006/11/05 22:42:07 tgl Exp $ -->
<chapter Id="runtime-config"> <chapter Id="runtime-config">
<title>Server Configuration</title> <title>Server Configuration</title>
...@@ -3217,6 +3217,28 @@ SELECT * FROM parent WHERE key = 2400; ...@@ -3217,6 +3217,28 @@ SELECT * FROM parent WHERE key = 2400;
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry id="guc-autovacuum-freeze-max-age" xreflabel="autovacuum_freeze_max_age">
<term><varname>autovacuum_freeze_max_age</varname> (<type>integer</type>)</term>
<indexterm>
<primary><varname>autovacuum_freeze_max_age</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
Specifies the maximum age (in transactions) that a table's
<structname>pg_class</>.<structfield>relfrozenxid</> field can
attain before a <command>VACUUM</> operation is forced to prevent
transaction ID wraparound within the table. Note that the system
will launch autovacuum processes to prevent wraparound even when
autovacuum is otherwise disabled.
The default is 200000000 (200 million).
This parameter can only be set at server start, but the setting
can be reduced for individual tables by entries in
<structname>pg_autovacuum</>.
For more information see <xref linkend="vacuum-for-wraparound">.
</para>
</listitem>
</varlistentry>
<varlistentry id="guc-autovacuum-vacuum-cost-delay" xreflabel="autovacuum_vacuum_cost_delay"> <varlistentry id="guc-autovacuum-vacuum-cost-delay" xreflabel="autovacuum_vacuum_cost_delay">
<term><varname>autovacuum_vacuum_cost_delay</varname> (<type>integer</type>)</term> <term><varname>autovacuum_vacuum_cost_delay</varname> (<type>integer</type>)</term>
<indexterm> <indexterm>
...@@ -3427,7 +3449,7 @@ SELECT * FROM parent WHERE key = 2400; ...@@ -3427,7 +3449,7 @@ SELECT * FROM parent WHERE key = 2400;
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry id="guc-statement-timeout" xreflabel="statement_timeout"> <varlistentry id="guc-statement-timeout" xreflabel="statement_timeout">
<term><varname>statement_timeout</varname> (<type>integer</type>)</term> <term><varname>statement_timeout</varname> (<type>integer</type>)</term>
<indexterm> <indexterm>
...@@ -3444,6 +3466,26 @@ SELECT * FROM parent WHERE key = 2400; ...@@ -3444,6 +3466,26 @@ SELECT * FROM parent WHERE key = 2400;
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry id="guc-vacuum-freeze-min-age" xreflabel="vacuum_freeze_min_age">
<term><varname>vacuum_freeze_min_age</varname> (<type>integer</type>)</term>
<indexterm>
<primary><varname>vacuum_freeze_min_age</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
Specifies the cutoff age (in transactions) that <command>VACUUM</>
should use to decide whether to replace transaction IDs with
<literal>FrozenXID</> while scanning a table.
The default is 100000000 (100 million). Although users can set this
value anywhere from zero to 1000000000, <command>VACUUM</> will
silently limit the effective value to half the value of <xref
linkend="guc-autovacuum-freeze-max-age">, so that there is not an
unreasonably short time between forced autovacuums.
For more information see <xref linkend="vacuum-for-wraparound">.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</sect2> </sect2>
......
This diff is collapsed.
<!-- $PostgreSQL: pgsql/doc/src/sgml/manage-ag.sgml,v 2.48 2006/09/16 00:30:14 momjian Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/manage-ag.sgml,v 2.49 2006/11/05 22:42:07 tgl Exp $ -->
<chapter id="managing-databases"> <chapter id="managing-databases">
<title>Managing Databases</title> <title>Managing Databases</title>
...@@ -249,19 +249,6 @@ createdb -T template0 <replaceable>dbname</> ...@@ -249,19 +249,6 @@ createdb -T template0 <replaceable>dbname</>
should always be marked with <literal>datistemplate = true</>. should always be marked with <literal>datistemplate = true</>.
</para> </para>
<para>
After preparing a template database, or making any changes to one,
it is a good idea to perform <command>VACUUM FREEZE</> in that
database. If this is done when there are no other open transactions
in the same database, then it is guaranteed that all rows in the
database are <quote>frozen</> and will not be subject to transaction
ID wraparound problems. This is particularly important for a database
that will have <literal>datallowconn</literal> set to false, since it
will be impossible to do routine maintenance <command>VACUUM</> in
such a database.
See <xref linkend="vacuum-for-wraparound"> for more information.
</para>
<note> <note>
<para> <para>
<literal>template1</> and <literal>template0</> do not have any special <literal>template1</> and <literal>template0</> do not have any special
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/vacuum.sgml,v 1.42 2006/10/31 01:52:31 neilc Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/vacuum.sgml,v 1.43 2006/11/05 22:42:07 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -20,8 +20,8 @@ PostgreSQL documentation ...@@ -20,8 +20,8 @@ PostgreSQL documentation
<refsynopsisdiv> <refsynopsisdiv>
<synopsis> <synopsis>
VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ <replaceable class="PARAMETER">table</replaceable> ] VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ <replaceable class="PARAMETER">table</replaceable> ]
VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">table</replaceable> [ (<replaceable class="PARAMETER">column</replaceable> [, ...] ) ] ] VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">table</replaceable> [ (<replaceable class="PARAMETER">column</replaceable> [, ...] ) ] ]
</synopsis> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
...@@ -62,21 +62,6 @@ VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">ta ...@@ -62,21 +62,6 @@ VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">ta
blocks. This form is much slower and requires an exclusive lock on each blocks. This form is much slower and requires an exclusive lock on each
table while it is being processed. table while it is being processed.
</para> </para>
<para>
<literal>FREEZE</literal> is a special-purpose option that
causes tuples to be marked <quote>frozen</quote> as soon as possible,
rather than waiting until they are quite old. If this is done when there
are no other open transactions in the same database, then it is guaranteed
that all tuples in the database are <quote>frozen</> and will not be
subject to transaction ID wraparound problems, no matter how long the
database is left unvacuumed.
<literal>FREEZE</literal> is not recommended for routine use. Its only
intended usage is in connection with preparation of user-defined template
databases, or other databases that are completely read-only and will not
receive routine maintenance <command>VACUUM</> operations.
See <xref linkend="maintenance"> for details.
</para>
</refsect1> </refsect1>
<refsect1> <refsect1>
...@@ -98,6 +83,11 @@ VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">ta ...@@ -98,6 +83,11 @@ VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">ta
<listitem> <listitem>
<para> <para>
Selects aggressive <quote>freezing</quote> of tuples. Selects aggressive <quote>freezing</quote> of tuples.
Specifying <literal>FREEZE</literal> is equivalent to performing
<command>VACUUM</command> with the
<xref linkend="guc-vacuum-freeze-min-age"> parameter
set to zero. The <literal>FREEZE</literal> option is deprecated and
will be removed in a future release; set the parameter instead.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -185,6 +175,13 @@ VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">ta ...@@ -185,6 +175,13 @@ VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">ta
it is sometimes advisable to use the cost-based vacuum delay feature. it is sometimes advisable to use the cost-based vacuum delay feature.
See <xref linkend="runtime-config-resource-vacuum-cost"> for details. See <xref linkend="runtime-config-resource-vacuum-cost"> for details.
</para> </para>
<para>
<productname>PostgreSQL</productname> includes an <quote>autovacuum</>
facility which can automate routine vacuum maintenance. For more
information about automatic and manual vacuuming, see
<xref linkend="routine-vacuuming">.
</para>
</refsect1> </refsect1>
<refsect1> <refsect1>
......
This diff is collapsed.
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,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/clog.c,v 1.40 2006/10/04 00:29:49 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/clog.c,v 1.41 2006/11/05 22:42:07 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -69,6 +69,7 @@ static SlruCtlData ClogCtlData; ...@@ -69,6 +69,7 @@ static SlruCtlData ClogCtlData;
static int ZeroCLOGPage(int pageno, bool writeXlog); static int ZeroCLOGPage(int pageno, bool writeXlog);
static bool CLOGPagePrecedes(int page1, int page2); static bool CLOGPagePrecedes(int page1, int page2);
static void WriteZeroPageXlogRec(int pageno); static void WriteZeroPageXlogRec(int pageno);
static void WriteTruncateXlogRec(int pageno);
/* /*
...@@ -309,16 +310,17 @@ ExtendCLOG(TransactionId newestXact) ...@@ -309,16 +310,17 @@ ExtendCLOG(TransactionId newestXact)
/* /*
* Remove all CLOG segments before the one holding the passed transaction ID * Remove all CLOG segments before the one holding the passed transaction ID
* *
* When this is called, we know that the database logically contains no * Before removing any CLOG data, we must flush XLOG to disk, to ensure
* reference to transaction IDs older than oldestXact. However, we must * that any recently-emitted HEAP_FREEZE records have reached disk; otherwise
* not truncate the CLOG until we have performed a checkpoint, to ensure * a crash and restart might leave us with some unfrozen tuples referencing
* that no such references remain on disk either; else a crash just after * removed CLOG data. We choose to emit a special TRUNCATE XLOG record too.
* the truncation might leave us with a problem. Since CLOG segments hold * Replaying the deletion from XLOG is not critical, since the files could
* a large number of transactions, the opportunity to actually remove a * just as well be removed later, but doing so prevents a long-running hot
* segment is fairly rare, and so it seems best not to do the checkpoint * standby server from acquiring an unreasonably bloated CLOG directory.
* unless we have confirmed that there is a removable segment. Therefore *
* we issue the checkpoint command here, not in higher-level code as might * Since CLOG segments hold a large number of transactions, the opportunity to
* seem cleaner. * actually remove a segment is fairly rare, and so it seems best not to do
* the XLOG flush unless we have confirmed that there is a removable segment.
*/ */
void void
TruncateCLOG(TransactionId oldestXact) TruncateCLOG(TransactionId oldestXact)
...@@ -335,8 +337,8 @@ TruncateCLOG(TransactionId oldestXact) ...@@ -335,8 +337,8 @@ TruncateCLOG(TransactionId oldestXact)
if (!SlruScanDirectory(ClogCtl, cutoffPage, false)) if (!SlruScanDirectory(ClogCtl, cutoffPage, false))
return; /* nothing to remove */ return; /* nothing to remove */
/* Perform a CHECKPOINT */ /* Write XLOG record and flush XLOG to disk */
RequestCheckpoint(true, false); WriteTruncateXlogRec(cutoffPage);
/* Now we can remove the old CLOG segment(s) */ /* Now we can remove the old CLOG segment(s) */
SimpleLruTruncate(ClogCtl, cutoffPage); SimpleLruTruncate(ClogCtl, cutoffPage);
...@@ -386,6 +388,29 @@ WriteZeroPageXlogRec(int pageno) ...@@ -386,6 +388,29 @@ WriteZeroPageXlogRec(int pageno)
(void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE | XLOG_NO_TRAN, &rdata); (void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE | XLOG_NO_TRAN, &rdata);
} }
/*
* Write a TRUNCATE xlog record
*
* We must flush the xlog record to disk before returning --- see notes
* in TruncateCLOG().
*
* Note: xlog record is marked as outside transaction control, since we
* want it to be redone whether the invoking transaction commits or not.
*/
static void
WriteTruncateXlogRec(int pageno)
{
XLogRecData rdata;
XLogRecPtr recptr;
rdata.data = (char *) (&pageno);
rdata.len = sizeof(int);
rdata.buffer = InvalidBuffer;
rdata.next = NULL;
recptr = XLogInsert(RM_CLOG_ID, CLOG_TRUNCATE | XLOG_NO_TRAN, &rdata);
XLogFlush(recptr);
}
/* /*
* CLOG resource manager's routines * CLOG resource manager's routines
*/ */
...@@ -409,6 +434,22 @@ clog_redo(XLogRecPtr lsn, XLogRecord *record) ...@@ -409,6 +434,22 @@ clog_redo(XLogRecPtr lsn, XLogRecord *record)
LWLockRelease(CLogControlLock); LWLockRelease(CLogControlLock);
} }
else if (info == CLOG_TRUNCATE)
{
int pageno;
memcpy(&pageno, XLogRecGetData(record), sizeof(int));
/*
* During XLOG replay, latest_page_number isn't set up yet; insert
* a suitable value to bypass the sanity test in SimpleLruTruncate.
*/
ClogCtl->shared->latest_page_number = pageno;
SimpleLruTruncate(ClogCtl, pageno);
}
else
elog(PANIC, "clog_redo: unknown op code %u", info);
} }
void void
...@@ -423,6 +464,13 @@ clog_desc(StringInfo buf, uint8 xl_info, char *rec) ...@@ -423,6 +464,13 @@ clog_desc(StringInfo buf, uint8 xl_info, char *rec)
memcpy(&pageno, rec, sizeof(int)); memcpy(&pageno, rec, sizeof(int));
appendStringInfo(buf, "zeropage: %d", pageno); appendStringInfo(buf, "zeropage: %d", pageno);
} }
else if (info == CLOG_TRUNCATE)
{
int pageno;
memcpy(&pageno, rec, sizeof(int));
appendStringInfo(buf, "truncate before: %d", pageno);
}
else else
appendStringInfo(buf, "UNKNOWN"); appendStringInfo(buf, "UNKNOWN");
} }
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Resource managers definition * Resource managers definition
* *
* $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.24 2006/08/07 16:57:56 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.25 2006/11/05 22:42:07 tgl Exp $
*/ */
#include "postgres.h" #include "postgres.h"
...@@ -32,7 +32,7 @@ const RmgrData RmgrTable[RM_MAX_ID + 1] = { ...@@ -32,7 +32,7 @@ const RmgrData RmgrTable[RM_MAX_ID + 1] = {
{"MultiXact", multixact_redo, multixact_desc, NULL, NULL, NULL}, {"MultiXact", multixact_redo, multixact_desc, NULL, NULL, NULL},
{"Reserved 7", NULL, NULL, NULL, NULL, NULL}, {"Reserved 7", NULL, NULL, NULL, NULL, NULL},
{"Reserved 8", NULL, NULL, NULL, NULL, NULL}, {"Reserved 8", NULL, NULL, NULL, NULL, NULL},
{"Reserved 9", NULL, NULL, NULL, NULL, NULL}, {"Heap2", heap2_redo, heap2_desc, NULL, NULL, NULL},
{"Heap", heap_redo, heap_desc, NULL, NULL, NULL}, {"Heap", heap_redo, heap_desc, NULL, NULL, NULL},
{"Btree", btree_redo, btree_desc, btree_xlog_startup, btree_xlog_cleanup, btree_safe_restartpoint}, {"Btree", btree_redo, btree_desc, btree_xlog_startup, btree_xlog_cleanup, btree_safe_restartpoint},
{"Hash", hash_redo, hash_desc, NULL, NULL, NULL}, {"Hash", hash_redo, hash_desc, NULL, NULL, NULL},
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Copyright (c) 2000-2006, PostgreSQL Global Development Group * Copyright (c) 2000-2006, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.75 2006/10/04 00:29:49 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.76 2006/11/05 22:42:07 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include "access/subtrans.h" #include "access/subtrans.h"
#include "access/transam.h" #include "access/transam.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "postmaster/autovacuum.h"
#include "storage/pmsignal.h"
#include "storage/proc.h" #include "storage/proc.h"
#include "utils/builtins.h" #include "utils/builtins.h"
...@@ -47,20 +49,31 @@ GetNewTransactionId(bool isSubXact) ...@@ -47,20 +49,31 @@ GetNewTransactionId(bool isSubXact)
xid = ShmemVariableCache->nextXid; xid = ShmemVariableCache->nextXid;
/* /*----------
* Check to see if it's safe to assign another XID. This protects against * Check to see if it's safe to assign another XID. This protects against
* catastrophic data loss due to XID wraparound. The basic rules are: * catastrophic data loss due to XID wraparound. The basic rules are:
* warn if we're past xidWarnLimit, and refuse to execute transactions if *
* we're past xidStopLimit, unless we are running in a standalone backend * If we're past xidVacLimit, start trying to force autovacuum cycles.
* (which gives an escape hatch to the DBA who ignored all those * If we're past xidWarnLimit, start issuing warnings.
* warnings). * If we're past xidStopLimit, refuse to execute transactions, unless
* we are running in a standalone backend (which gives an escape hatch
* to the DBA who somehow got past the earlier defenses).
* *
* Test is coded to fall out as fast as possible during normal operation, * Test is coded to fall out as fast as possible during normal operation,
* ie, when the warn limit is set and we haven't violated it. * ie, when the vac limit is set and we haven't violated it.
*----------
*/ */
if (TransactionIdFollowsOrEquals(xid, ShmemVariableCache->xidWarnLimit) && if (TransactionIdFollowsOrEquals(xid, ShmemVariableCache->xidVacLimit) &&
TransactionIdIsValid(ShmemVariableCache->xidWarnLimit)) TransactionIdIsValid(ShmemVariableCache->xidVacLimit))
{ {
/*
* To avoid swamping the postmaster with signals, we issue the
* autovac request only once per 64K transaction starts. This
* still gives plenty of chances before we get into real trouble.
*/
if (IsUnderPostmaster && (xid % 65536) == 0)
SendPostmasterSignal(PMSIGNAL_START_AUTOVAC);
if (IsUnderPostmaster && if (IsUnderPostmaster &&
TransactionIdFollowsOrEquals(xid, ShmemVariableCache->xidStopLimit)) TransactionIdFollowsOrEquals(xid, ShmemVariableCache->xidStopLimit))
ereport(ERROR, ereport(ERROR,
...@@ -69,7 +82,7 @@ GetNewTransactionId(bool isSubXact) ...@@ -69,7 +82,7 @@ GetNewTransactionId(bool isSubXact)
NameStr(ShmemVariableCache->limit_datname)), NameStr(ShmemVariableCache->limit_datname)),
errhint("Stop the postmaster and use a standalone backend to vacuum database \"%s\".", errhint("Stop the postmaster and use a standalone backend to vacuum database \"%s\".",
NameStr(ShmemVariableCache->limit_datname)))); NameStr(ShmemVariableCache->limit_datname))));
else else if (TransactionIdFollowsOrEquals(xid, ShmemVariableCache->xidWarnLimit))
ereport(WARNING, ereport(WARNING,
(errmsg("database \"%s\" must be vacuumed within %u transactions", (errmsg("database \"%s\" must be vacuumed within %u transactions",
NameStr(ShmemVariableCache->limit_datname), NameStr(ShmemVariableCache->limit_datname),
...@@ -178,28 +191,29 @@ ReadNewTransactionId(void) ...@@ -178,28 +191,29 @@ ReadNewTransactionId(void)
/* /*
* Determine the last safe XID to allocate given the currently oldest * Determine the last safe XID to allocate given the currently oldest
* datminxid (ie, the oldest XID that might exist in any database * datfrozenxid (ie, the oldest XID that might exist in any database
* of our cluster). * of our cluster).
*/ */
void void
SetTransactionIdLimit(TransactionId oldest_datminxid, SetTransactionIdLimit(TransactionId oldest_datfrozenxid,
Name oldest_datname) Name oldest_datname)
{ {
TransactionId xidVacLimit;
TransactionId xidWarnLimit; TransactionId xidWarnLimit;
TransactionId xidStopLimit; TransactionId xidStopLimit;
TransactionId xidWrapLimit; TransactionId xidWrapLimit;
TransactionId curXid; TransactionId curXid;
Assert(TransactionIdIsValid(oldest_datminxid)); Assert(TransactionIdIsNormal(oldest_datfrozenxid));
/* /*
* The place where we actually get into deep trouble is halfway around * The place where we actually get into deep trouble is halfway around
* from the oldest existing XID. (This calculation is probably off by one * from the oldest potentially-existing XID. (This calculation is
* or two counts, because the special XIDs reduce the size of the loop a * probably off by one or two counts, because the special XIDs reduce the
* little bit. But we throw in plenty of slop below, so it doesn't * size of the loop a little bit. But we throw in plenty of slop below,
* matter.) * so it doesn't matter.)
*/ */
xidWrapLimit = oldest_datminxid + (MaxTransactionId >> 1); xidWrapLimit = oldest_datfrozenxid + (MaxTransactionId >> 1);
if (xidWrapLimit < FirstNormalTransactionId) if (xidWrapLimit < FirstNormalTransactionId)
xidWrapLimit += FirstNormalTransactionId; xidWrapLimit += FirstNormalTransactionId;
...@@ -229,8 +243,28 @@ SetTransactionIdLimit(TransactionId oldest_datminxid, ...@@ -229,8 +243,28 @@ SetTransactionIdLimit(TransactionId oldest_datminxid,
if (xidWarnLimit < FirstNormalTransactionId) if (xidWarnLimit < FirstNormalTransactionId)
xidWarnLimit -= FirstNormalTransactionId; xidWarnLimit -= FirstNormalTransactionId;
/*
* We'll start trying to force autovacuums when oldest_datfrozenxid
* gets to be more than autovacuum_freeze_max_age transactions old.
*
* Note: guc.c ensures that autovacuum_freeze_max_age is in a sane
* range, so that xidVacLimit will be well before xidWarnLimit.
*
* Note: autovacuum_freeze_max_age is a PGC_POSTMASTER parameter so that
* we don't have to worry about dealing with on-the-fly changes in its
* value. It doesn't look practical to update shared state from a GUC
* assign hook (too many processes would try to execute the hook,
* resulting in race conditions as well as crashes of those not
* connected to shared memory). Perhaps this can be improved someday.
*/
xidVacLimit = oldest_datfrozenxid + autovacuum_freeze_max_age;
if (xidVacLimit < FirstNormalTransactionId)
xidVacLimit += FirstNormalTransactionId;
/* Grab lock for just long enough to set the new limit values */ /* Grab lock for just long enough to set the new limit values */
LWLockAcquire(XidGenLock, LW_EXCLUSIVE); LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
ShmemVariableCache->oldestXid = oldest_datfrozenxid;
ShmemVariableCache->xidVacLimit = xidVacLimit;
ShmemVariableCache->xidWarnLimit = xidWarnLimit; ShmemVariableCache->xidWarnLimit = xidWarnLimit;
ShmemVariableCache->xidStopLimit = xidStopLimit; ShmemVariableCache->xidStopLimit = xidStopLimit;
ShmemVariableCache->xidWrapLimit = xidWrapLimit; ShmemVariableCache->xidWrapLimit = xidWrapLimit;
...@@ -242,6 +276,18 @@ SetTransactionIdLimit(TransactionId oldest_datminxid, ...@@ -242,6 +276,18 @@ SetTransactionIdLimit(TransactionId oldest_datminxid,
ereport(DEBUG1, ereport(DEBUG1,
(errmsg("transaction ID wrap limit is %u, limited by database \"%s\"", (errmsg("transaction ID wrap limit is %u, limited by database \"%s\"",
xidWrapLimit, NameStr(*oldest_datname)))); xidWrapLimit, NameStr(*oldest_datname))));
/*
* If past the autovacuum force point, immediately signal an autovac
* request. The reason for this is that autovac only processes one
* database per invocation. Once it's finished cleaning up the oldest
* database, it'll call here, and we'll signal the postmaster to start
* another iteration immediately if there are still any old databases.
*/
if (TransactionIdFollowsOrEquals(curXid, xidVacLimit) &&
IsUnderPostmaster)
SendPostmasterSignal(PMSIGNAL_START_AUTOVAC);
/* Give an immediate warning if past the wrap warn point */ /* Give an immediate warning if past the wrap warn point */
if (TransactionIdFollowsOrEquals(curXid, xidWarnLimit)) if (TransactionIdFollowsOrEquals(curXid, xidWarnLimit))
ereport(WARNING, ereport(WARNING,
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.227 2006/10/04 00:29:49 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.228 2006/11/05 22:42:07 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -468,8 +468,12 @@ TransactionIdIsCurrentTransactionId(TransactionId xid) ...@@ -468,8 +468,12 @@ TransactionIdIsCurrentTransactionId(TransactionId xid)
* is what we need during bootstrap. (Bootstrap mode only inserts tuples, * is what we need during bootstrap. (Bootstrap mode only inserts tuples,
* it never updates or deletes them, so all tuples can be presumed good * it never updates or deletes them, so all tuples can be presumed good
* immediately.) * immediately.)
*
* Likewise, InvalidTransactionId and FrozenTransactionId are certainly
* not my transaction ID, so we can just return "false" immediately for
* any non-normal XID.
*/ */
if (xid == BootstrapTransactionId) if (!TransactionIdIsNormal(xid))
return false; return false;
/* /*
......
...@@ -7,7 +7,7 @@ ...@@ -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.252 2006/10/18 22:44:11 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.253 2006/11/05 22:42:08 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -5343,36 +5343,6 @@ GetLastSegSwitchTime(void) ...@@ -5343,36 +5343,6 @@ GetLastSegSwitchTime(void)
return result; return result;
} }
/*
* GetRecentNextXid - get the nextXid value saved by the most recent checkpoint
*
* This is currently used only by the autovacuum daemon. To check for
* impending XID wraparound, autovac needs an approximate idea of the current
* XID counter, and it needs it before choosing which DB to attach to, hence
* before it sets up a PGPROC, hence before it can take any LWLocks. But it
* has attached to shared memory, and so we can let it reach into the shared
* ControlFile structure and pull out the last checkpoint nextXID.
*
* Since we don't take any sort of lock, we have to assume that reading a
* TransactionId is atomic ... but that assumption is made elsewhere, too,
* and in any case the worst possible consequence of a bogus result is that
* autovac issues an unnecessary database-wide VACUUM.
*
* Note: we could also choose to read ShmemVariableCache->nextXid in an
* unlocked fashion, thus getting a more up-to-date result; but since that
* changes far more frequently than the controlfile checkpoint copy, it would
* pose a far higher risk of bogus result if we did have a nonatomic-read
* problem.
*
* A (theoretically) completely safe answer is to read the actual pg_control
* file into local process memory, but that certainly seems like overkill.
*/
TransactionId
GetRecentNextXid(void)
{
return ControlFile->checkPointCopy.nextXid;
}
/* /*
* GetNextXidAndEpoch - get the current nextXid value and associated epoch * GetNextXidAndEpoch - get the current nextXid value and associated epoch
* *
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.313 2006/10/04 00:29:50 momjian Exp $ * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.314 2006/11/05 22:42:08 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -595,8 +595,7 @@ InsertPgClassTuple(Relation pg_class_desc, ...@@ -595,8 +595,7 @@ InsertPgClassTuple(Relation pg_class_desc,
values[Anum_pg_class_relhaspkey - 1] = BoolGetDatum(rd_rel->relhaspkey); values[Anum_pg_class_relhaspkey - 1] = BoolGetDatum(rd_rel->relhaspkey);
values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules); values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass); values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
values[Anum_pg_class_relminxid - 1] = TransactionIdGetDatum(rd_rel->relminxid); values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
values[Anum_pg_class_relvacuumxid - 1] = TransactionIdGetDatum(rd_rel->relvacuumxid);
/* start out with empty permissions */ /* start out with empty permissions */
nulls[Anum_pg_class_relacl - 1] = 'n'; nulls[Anum_pg_class_relacl - 1] = 'n';
if (reloptions != (Datum) 0) if (reloptions != (Datum) 0)
...@@ -644,35 +643,6 @@ AddNewRelationTuple(Relation pg_class_desc, ...@@ -644,35 +643,6 @@ AddNewRelationTuple(Relation pg_class_desc,
*/ */
new_rel_reltup = new_rel_desc->rd_rel; new_rel_reltup = new_rel_desc->rd_rel;
/* Initialize relminxid and relvacuumxid */
if (relkind == RELKIND_RELATION ||
relkind == RELKIND_TOASTVALUE)
{
/*
* Only real tables have Xids stored in them; initialize our known
* value to the minimum Xid that could put tuples in the new table.
*/
if (!IsBootstrapProcessingMode())
{
new_rel_reltup->relminxid = RecentXmin;
new_rel_reltup->relvacuumxid = RecentXmin;
}
else
{
new_rel_reltup->relminxid = FirstNormalTransactionId;
new_rel_reltup->relvacuumxid = FirstNormalTransactionId;
}
}
else
{
/*
* Other relations will not have Xids in them, so set the initial
* value to InvalidTransactionId.
*/
new_rel_reltup->relminxid = InvalidTransactionId;
new_rel_reltup->relvacuumxid = InvalidTransactionId;
}
switch (relkind) switch (relkind)
{ {
case RELKIND_RELATION: case RELKIND_RELATION:
...@@ -694,6 +664,31 @@ AddNewRelationTuple(Relation pg_class_desc, ...@@ -694,6 +664,31 @@ AddNewRelationTuple(Relation pg_class_desc,
break; break;
} }
/* Initialize relfrozenxid */
if (relkind == RELKIND_RELATION ||
relkind == RELKIND_TOASTVALUE)
{
/*
* Initialize to the minimum XID that could put tuples in the table.
* We know that no xacts older than RecentXmin are still running,
* so that will do.
*/
if (!IsBootstrapProcessingMode())
new_rel_reltup->relfrozenxid = RecentXmin;
else
new_rel_reltup->relfrozenxid = FirstNormalTransactionId;
}
else
{
/*
* Other relation types will not contain XIDs, so set relfrozenxid
* to InvalidTransactionId. (Note: a sequence does contain a tuple,
* but we force its xmin to be FrozenTransactionId always; see
* commands/sequence.c.)
*/
new_rel_reltup->relfrozenxid = InvalidTransactionId;
}
new_rel_reltup->relowner = relowner; new_rel_reltup->relowner = relowner;
new_rel_reltup->reltype = new_type_oid; new_rel_reltup->reltype = new_type_oid;
new_rel_reltup->relkind = relkind; new_rel_reltup->relkind = relkind;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.100 2006/10/05 17:57:40 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.101 2006/11/05 22:42:08 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -421,7 +421,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt) ...@@ -421,7 +421,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
vac_update_relstats(RelationGetRelid(onerel), vac_update_relstats(RelationGetRelid(onerel),
RelationGetNumberOfBlocks(onerel), RelationGetNumberOfBlocks(onerel),
totalrows, hasindex, totalrows, hasindex,
InvalidTransactionId, InvalidTransactionId); InvalidTransactionId);
for (ind = 0; ind < nindexes; ind++) for (ind = 0; ind < nindexes; ind++)
{ {
...@@ -432,7 +432,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt) ...@@ -432,7 +432,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
vac_update_relstats(RelationGetRelid(Irel[ind]), vac_update_relstats(RelationGetRelid(Irel[ind]),
RelationGetNumberOfBlocks(Irel[ind]), RelationGetNumberOfBlocks(Irel[ind]),
totalindexrows, false, totalindexrows, false,
InvalidTransactionId, InvalidTransactionId); InvalidTransactionId);
} }
/* report results to the stats collector, too */ /* report results to the stats collector, too */
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.186 2006/10/18 22:44:12 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.187 2006/11/05 22:42:08 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,8 +53,7 @@ ...@@ -53,8 +53,7 @@
static bool get_db_info(const char *name, LOCKMODE lockmode, static bool get_db_info(const char *name, LOCKMODE lockmode,
Oid *dbIdP, Oid *ownerIdP, Oid *dbIdP, Oid *ownerIdP,
int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP, int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP,
Oid *dbLastSysOidP, Oid *dbLastSysOidP, TransactionId *dbFrozenXidP,
TransactionId *dbVacuumXidP, TransactionId *dbMinXidP,
Oid *dbTablespace); Oid *dbTablespace);
static bool have_createdb_privilege(void); static bool have_createdb_privilege(void);
static void remove_dbtablespaces(Oid db_id); static void remove_dbtablespaces(Oid db_id);
...@@ -75,8 +74,7 @@ createdb(const CreatedbStmt *stmt) ...@@ -75,8 +74,7 @@ createdb(const CreatedbStmt *stmt)
bool src_istemplate; bool src_istemplate;
bool src_allowconn; bool src_allowconn;
Oid src_lastsysoid; Oid src_lastsysoid;
TransactionId src_vacuumxid; TransactionId src_frozenxid;
TransactionId src_minxid;
Oid src_deftablespace; Oid src_deftablespace;
volatile Oid dst_deftablespace; volatile Oid dst_deftablespace;
Relation pg_database_rel; Relation pg_database_rel;
...@@ -228,7 +226,7 @@ createdb(const CreatedbStmt *stmt) ...@@ -228,7 +226,7 @@ createdb(const CreatedbStmt *stmt)
if (!get_db_info(dbtemplate, ShareLock, if (!get_db_info(dbtemplate, ShareLock,
&src_dboid, &src_owner, &src_encoding, &src_dboid, &src_owner, &src_encoding,
&src_istemplate, &src_allowconn, &src_lastsysoid, &src_istemplate, &src_allowconn, &src_lastsysoid,
&src_vacuumxid, &src_minxid, &src_deftablespace)) &src_frozenxid, &src_deftablespace))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_DATABASE), (errcode(ERRCODE_UNDEFINED_DATABASE),
errmsg("template database \"%s\" does not exist", errmsg("template database \"%s\" does not exist",
...@@ -366,8 +364,7 @@ createdb(const CreatedbStmt *stmt) ...@@ -366,8 +364,7 @@ createdb(const CreatedbStmt *stmt)
new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(true); new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(true);
new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit); new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit);
new_record[Anum_pg_database_datlastsysoid - 1] = ObjectIdGetDatum(src_lastsysoid); new_record[Anum_pg_database_datlastsysoid - 1] = ObjectIdGetDatum(src_lastsysoid);
new_record[Anum_pg_database_datvacuumxid - 1] = TransactionIdGetDatum(src_vacuumxid); new_record[Anum_pg_database_datfrozenxid - 1] = TransactionIdGetDatum(src_frozenxid);
new_record[Anum_pg_database_datminxid - 1] = TransactionIdGetDatum(src_minxid);
new_record[Anum_pg_database_dattablespace - 1] = ObjectIdGetDatum(dst_deftablespace); new_record[Anum_pg_database_dattablespace - 1] = ObjectIdGetDatum(dst_deftablespace);
/* /*
...@@ -565,7 +562,7 @@ dropdb(const char *dbname, bool missing_ok) ...@@ -565,7 +562,7 @@ dropdb(const char *dbname, bool missing_ok)
pgdbrel = heap_open(DatabaseRelationId, RowExclusiveLock); pgdbrel = heap_open(DatabaseRelationId, RowExclusiveLock);
if (!get_db_info(dbname, AccessExclusiveLock, &db_id, NULL, NULL, if (!get_db_info(dbname, AccessExclusiveLock, &db_id, NULL, NULL,
&db_istemplate, NULL, NULL, NULL, NULL, NULL)) &db_istemplate, NULL, NULL, NULL, NULL))
{ {
if (!missing_ok) if (!missing_ok)
{ {
...@@ -689,7 +686,7 @@ RenameDatabase(const char *oldname, const char *newname) ...@@ -689,7 +686,7 @@ RenameDatabase(const char *oldname, const char *newname)
rel = heap_open(DatabaseRelationId, RowExclusiveLock); rel = heap_open(DatabaseRelationId, RowExclusiveLock);
if (!get_db_info(oldname, AccessExclusiveLock, &db_id, NULL, NULL, if (!get_db_info(oldname, AccessExclusiveLock, &db_id, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL)) NULL, NULL, NULL, NULL, NULL))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_DATABASE), (errcode(ERRCODE_UNDEFINED_DATABASE),
errmsg("database \"%s\" does not exist", oldname))); errmsg("database \"%s\" does not exist", oldname)));
...@@ -1067,8 +1064,7 @@ static bool ...@@ -1067,8 +1064,7 @@ static bool
get_db_info(const char *name, LOCKMODE lockmode, get_db_info(const char *name, LOCKMODE lockmode,
Oid *dbIdP, Oid *ownerIdP, Oid *dbIdP, Oid *ownerIdP,
int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP, int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP,
Oid *dbLastSysOidP, Oid *dbLastSysOidP, TransactionId *dbFrozenXidP,
TransactionId *dbVacuumXidP, TransactionId *dbMinXidP,
Oid *dbTablespace) Oid *dbTablespace)
{ {
bool result = false; bool result = false;
...@@ -1154,12 +1150,9 @@ get_db_info(const char *name, LOCKMODE lockmode, ...@@ -1154,12 +1150,9 @@ get_db_info(const char *name, LOCKMODE lockmode,
/* last system OID used in database */ /* last system OID used in database */
if (dbLastSysOidP) if (dbLastSysOidP)
*dbLastSysOidP = dbform->datlastsysoid; *dbLastSysOidP = dbform->datlastsysoid;
/* limit of vacuumed XIDs */ /* limit of frozen XIDs */
if (dbVacuumXidP) if (dbFrozenXidP)
*dbVacuumXidP = dbform->datvacuumxid; *dbFrozenXidP = dbform->datfrozenxid;
/* limit of min XIDs */
if (dbMinXidP)
*dbMinXidP = dbform->datminxid;
/* default tablespace for this database */ /* default tablespace for this database */
if (dbTablespace) if (dbTablespace)
*dbTablespace = dbform->dattablespace; *dbTablespace = dbform->dattablespace;
......
This diff is collapsed.
This diff is collapsed.
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.156 2006/10/04 00:29:53 momjian Exp $ * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.157 2006/11/05 22:42:08 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1004,16 +1004,14 @@ load_hba(void) ...@@ -1004,16 +1004,14 @@ load_hba(void)
* dbname: gets database name (must be of size NAMEDATALEN bytes) * dbname: gets database name (must be of size NAMEDATALEN bytes)
* dboid: gets database OID * dboid: gets database OID
* dbtablespace: gets database's default tablespace's OID * dbtablespace: gets database's default tablespace's OID
* dbminxid: gets database's minimum XID * dbfrozenxid: gets database's frozen XID
* dbvacuumxid: gets database's vacuum XID
* *
* This is not much related to the other functions in hba.c, but we put it * This is not much related to the other functions in hba.c, but we put it
* here because it uses the next_token() infrastructure. * here because it uses the next_token() infrastructure.
*/ */
bool bool
read_pg_database_line(FILE *fp, char *dbname, Oid *dboid, read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
Oid *dbtablespace, TransactionId *dbminxid, Oid *dbtablespace, TransactionId *dbfrozenxid)
TransactionId *dbvacuumxid)
{ {
char buf[MAX_TOKEN]; char buf[MAX_TOKEN];
...@@ -1035,11 +1033,7 @@ read_pg_database_line(FILE *fp, char *dbname, Oid *dboid, ...@@ -1035,11 +1033,7 @@ read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
next_token(fp, buf, sizeof(buf)); next_token(fp, buf, sizeof(buf));
if (!isdigit((unsigned char) buf[0])) if (!isdigit((unsigned char) buf[0]))
elog(FATAL, "bad data in flat pg_database file"); elog(FATAL, "bad data in flat pg_database file");
*dbminxid = atoxid(buf); *dbfrozenxid = atoxid(buf);
next_token(fp, buf, sizeof(buf));
if (!isdigit((unsigned char) buf[0]))
elog(FATAL, "bad data in flat pg_database file");
*dbvacuumxid = atoxid(buf);
/* expect EOL next */ /* expect EOL next */
if (next_token(fp, buf, sizeof(buf))) if (next_token(fp, buf, sizeof(buf)))
elog(FATAL, "bad data in flat pg_database file"); elog(FATAL, "bad data in flat pg_database file");
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.352 2006/10/13 21:43:18 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.353 2006/11/05 22:42:08 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2350,8 +2350,8 @@ _copyVacuumStmt(VacuumStmt *from) ...@@ -2350,8 +2350,8 @@ _copyVacuumStmt(VacuumStmt *from)
COPY_SCALAR_FIELD(vacuum); COPY_SCALAR_FIELD(vacuum);
COPY_SCALAR_FIELD(full); COPY_SCALAR_FIELD(full);
COPY_SCALAR_FIELD(analyze); COPY_SCALAR_FIELD(analyze);
COPY_SCALAR_FIELD(freeze);
COPY_SCALAR_FIELD(verbose); COPY_SCALAR_FIELD(verbose);
COPY_SCALAR_FIELD(freeze_min_age);
COPY_NODE_FIELD(relation); COPY_NODE_FIELD(relation);
COPY_NODE_FIELD(va_cols); COPY_NODE_FIELD(va_cols);
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.286 2006/10/13 21:43:18 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.287 2006/11/05 22:42:08 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1215,8 +1215,8 @@ _equalVacuumStmt(VacuumStmt *a, VacuumStmt *b) ...@@ -1215,8 +1215,8 @@ _equalVacuumStmt(VacuumStmt *a, VacuumStmt *b)
COMPARE_SCALAR_FIELD(vacuum); COMPARE_SCALAR_FIELD(vacuum);
COMPARE_SCALAR_FIELD(full); COMPARE_SCALAR_FIELD(full);
COMPARE_SCALAR_FIELD(analyze); COMPARE_SCALAR_FIELD(analyze);
COMPARE_SCALAR_FIELD(freeze);
COMPARE_SCALAR_FIELD(verbose); COMPARE_SCALAR_FIELD(verbose);
COMPARE_SCALAR_FIELD(freeze_min_age);
COMPARE_NODE_FIELD(relation); COMPARE_NODE_FIELD(relation);
COMPARE_NODE_FIELD(va_cols); COMPARE_NODE_FIELD(va_cols);
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.567 2006/10/13 21:43:19 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.568 2006/11/05 22:42:09 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -5158,7 +5158,7 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose ...@@ -5158,7 +5158,7 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
n->vacuum = true; n->vacuum = true;
n->analyze = false; n->analyze = false;
n->full = $2; n->full = $2;
n->freeze = $3; n->freeze_min_age = $3 ? 0 : -1;
n->verbose = $4; n->verbose = $4;
n->relation = NULL; n->relation = NULL;
n->va_cols = NIL; n->va_cols = NIL;
...@@ -5170,7 +5170,7 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose ...@@ -5170,7 +5170,7 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
n->vacuum = true; n->vacuum = true;
n->analyze = false; n->analyze = false;
n->full = $2; n->full = $2;
n->freeze = $3; n->freeze_min_age = $3 ? 0 : -1;
n->verbose = $4; n->verbose = $4;
n->relation = $5; n->relation = $5;
n->va_cols = NIL; n->va_cols = NIL;
...@@ -5181,7 +5181,7 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose ...@@ -5181,7 +5181,7 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
VacuumStmt *n = (VacuumStmt *) $5; VacuumStmt *n = (VacuumStmt *) $5;
n->vacuum = true; n->vacuum = true;
n->full = $2; n->full = $2;
n->freeze = $3; n->freeze_min_age = $3 ? 0 : -1;
n->verbose |= $4; n->verbose |= $4;
$$ = (Node *)n; $$ = (Node *)n;
} }
...@@ -5194,7 +5194,7 @@ AnalyzeStmt: ...@@ -5194,7 +5194,7 @@ AnalyzeStmt:
n->vacuum = false; n->vacuum = false;
n->analyze = true; n->analyze = true;
n->full = false; n->full = false;
n->freeze = false; n->freeze_min_age = -1;
n->verbose = $2; n->verbose = $2;
n->relation = NULL; n->relation = NULL;
n->va_cols = NIL; n->va_cols = NIL;
...@@ -5206,7 +5206,7 @@ AnalyzeStmt: ...@@ -5206,7 +5206,7 @@ AnalyzeStmt:
n->vacuum = false; n->vacuum = false;
n->analyze = true; n->analyze = true;
n->full = false; n->full = false;
n->freeze = false; n->freeze_min_age = -1;
n->verbose = $2; n->verbose = $2;
n->relation = $3; n->relation = $3;
n->va_cols = $4; n->va_cols = $4;
......
This diff is collapsed.
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.500 2006/10/04 00:29:56 momjian Exp $ * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.501 2006/11/05 22:42:09 tgl Exp $
* *
* NOTES * NOTES
* *
...@@ -217,6 +217,8 @@ static bool FatalError = false; /* T if recovering from backend crash */ ...@@ -217,6 +217,8 @@ static bool FatalError = false; /* T if recovering from backend crash */
bool ClientAuthInProgress = false; /* T during new-client bool ClientAuthInProgress = false; /* T during new-client
* authentication */ * authentication */
static bool force_autovac = false; /* received START_AUTOVAC signal */
/* /*
* State for assigning random salts and cancel keys. * State for assigning random salts and cancel keys.
* Also, the global MyCancelKey passes the cancel key assigned to a given * Also, the global MyCancelKey passes the cancel key assigned to a given
...@@ -1231,9 +1233,13 @@ ServerLoop(void) ...@@ -1231,9 +1233,13 @@ ServerLoop(void)
* (It'll die relatively quickly.) We check that it's not started too * (It'll die relatively quickly.) We check that it's not started too
* frequently in autovac_start. * frequently in autovac_start.
*/ */
if (AutoVacuumingActive() && AutoVacPID == 0 && if ((AutoVacuumingActive() || force_autovac) && AutoVacPID == 0 &&
StartupPID == 0 && !FatalError && Shutdown == NoShutdown) StartupPID == 0 && !FatalError && Shutdown == NoShutdown)
{
AutoVacPID = autovac_start(); AutoVacPID = autovac_start();
if (AutoVacPID != 0)
force_autovac = false; /* signal successfully processed */
}
/* If we have lost the archiver, try to start a new one */ /* If we have lost the archiver, try to start a new one */
if (XLogArchivingActive() && PgArchPID == 0 && if (XLogArchivingActive() && PgArchPID == 0 &&
...@@ -2100,9 +2106,7 @@ reaper(SIGNAL_ARGS) ...@@ -2100,9 +2106,7 @@ reaper(SIGNAL_ARGS)
/* /*
* Was it the autovacuum process? Normal exit can be ignored; we'll * Was it the autovacuum process? Normal exit can be ignored; we'll
* start a new one at the next iteration of the postmaster's main * start a new one at the next iteration of the postmaster's main
* loop, if necessary. * loop, if necessary. An unexpected exit is treated as a crash.
*
* An unexpected exit must crash the system.
*/ */
if (AutoVacPID != 0 && pid == AutoVacPID) if (AutoVacPID != 0 && pid == AutoVacPID)
{ {
...@@ -3424,12 +3428,16 @@ sigusr1_handler(SIGNAL_ARGS) ...@@ -3424,12 +3428,16 @@ sigusr1_handler(SIGNAL_ARGS)
if (CheckPostmasterSignal(PMSIGNAL_START_AUTOVAC)) if (CheckPostmasterSignal(PMSIGNAL_START_AUTOVAC))
{ {
/* start one iteration of the autovacuum daemon */ /*
if (Shutdown == NoShutdown) * Start one iteration of the autovacuum daemon, even if autovacuuming
{ * is nominally not enabled. This is so we can have an active defense
Assert(!AutoVacuumingActive()); * against transaction ID wraparound. We set a flag for the main loop
AutoVacPID = autovac_start(); * to do it rather than trying to do it here --- this is because the
} * autovac process itself may send the signal, and we want to handle
* that by launching another iteration as soon as the current one
* completes.
*/
force_autovac = true;
} }
PG_SETMASK(&UnBlockSig); PG_SETMASK(&UnBlockSig);
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.18 2006/10/04 00:29:57 momjian Exp $ * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.19 2006/11/05 22:42:09 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -213,7 +213,9 @@ TransactionIdIsInProgress(TransactionId xid) ...@@ -213,7 +213,9 @@ TransactionIdIsInProgress(TransactionId xid)
/* /*
* Don't bother checking a transaction older than RecentXmin; it could not * Don't bother checking a transaction older than RecentXmin; it could not
* possibly still be running. * possibly still be running. (Note: in particular, this guarantees
* that we reject InvalidTransactionId, FrozenTransactionId, etc as
* not running.)
*/ */
if (TransactionIdPrecedes(xid, RecentXmin)) if (TransactionIdPrecedes(xid, RecentXmin))
{ {
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,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/utils/init/flatfiles.c,v 1.21 2006/07/14 14:52:25 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.22 2006/11/05 22:42:09 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -163,7 +163,7 @@ name_okay(const char *str) ...@@ -163,7 +163,7 @@ name_okay(const char *str)
/* /*
* write_database_file: update the flat database file * write_database_file: update the flat database file
* *
* A side effect is to determine the oldest database's datminxid * A side effect is to determine the oldest database's datfrozenxid
* so we can set or update the XID wrap limit. * so we can set or update the XID wrap limit.
*/ */
static void static void
...@@ -177,7 +177,7 @@ write_database_file(Relation drel) ...@@ -177,7 +177,7 @@ write_database_file(Relation drel)
HeapScanDesc scan; HeapScanDesc scan;
HeapTuple tuple; HeapTuple tuple;
NameData oldest_datname; NameData oldest_datname;
TransactionId oldest_datminxid = InvalidTransactionId; TransactionId oldest_datfrozenxid = InvalidTransactionId;
/* /*
* Create a temporary filename to be renamed later. This prevents the * Create a temporary filename to be renamed later. This prevents the
...@@ -208,27 +208,23 @@ write_database_file(Relation drel) ...@@ -208,27 +208,23 @@ write_database_file(Relation drel)
char *datname; char *datname;
Oid datoid; Oid datoid;
Oid dattablespace; Oid dattablespace;
TransactionId datminxid, TransactionId datfrozenxid;
datvacuumxid;
datname = NameStr(dbform->datname); datname = NameStr(dbform->datname);
datoid = HeapTupleGetOid(tuple); datoid = HeapTupleGetOid(tuple);
dattablespace = dbform->dattablespace; dattablespace = dbform->dattablespace;
datminxid = dbform->datminxid; datfrozenxid = dbform->datfrozenxid;
datvacuumxid = dbform->datvacuumxid;
/* /*
* Identify the oldest datminxid, ignoring databases that are not * Identify the oldest datfrozenxid. This must match
* connectable (we assume they are safely frozen). This must match
* the logic in vac_truncate_clog() in vacuum.c. * the logic in vac_truncate_clog() in vacuum.c.
*/ */
if (dbform->datallowconn && if (TransactionIdIsNormal(datfrozenxid))
TransactionIdIsNormal(datminxid))
{ {
if (oldest_datminxid == InvalidTransactionId || if (oldest_datfrozenxid == InvalidTransactionId ||
TransactionIdPrecedes(datminxid, oldest_datminxid)) TransactionIdPrecedes(datfrozenxid, oldest_datfrozenxid))
{ {
oldest_datminxid = datminxid; oldest_datfrozenxid = datfrozenxid;
namestrcpy(&oldest_datname, datname); namestrcpy(&oldest_datname, datname);
} }
} }
...@@ -244,14 +240,14 @@ write_database_file(Relation drel) ...@@ -244,14 +240,14 @@ write_database_file(Relation drel)
} }
/* /*
* The file format is: "dbname" oid tablespace minxid vacuumxid * The file format is: "dbname" oid tablespace frozenxid
* *
* The xids are not needed for backend startup, but are of use to * The xids are not needed for backend startup, but are of use to
* autovacuum, and might also be helpful for forensic purposes. * autovacuum, and might also be helpful for forensic purposes.
*/ */
fputs_quote(datname, fp); fputs_quote(datname, fp);
fprintf(fp, " %u %u %u %u\n", fprintf(fp, " %u %u %u\n",
datoid, dattablespace, datminxid, datvacuumxid); datoid, dattablespace, datfrozenxid);
} }
heap_endscan(scan); heap_endscan(scan);
...@@ -272,10 +268,10 @@ write_database_file(Relation drel) ...@@ -272,10 +268,10 @@ write_database_file(Relation drel)
tempname, filename))); tempname, filename)));
/* /*
* Set the transaction ID wrap limit using the oldest datminxid * Set the transaction ID wrap limit using the oldest datfrozenxid
*/ */
if (oldest_datminxid != InvalidTransactionId) if (oldest_datfrozenxid != InvalidTransactionId)
SetTransactionIdLimit(oldest_datminxid, &oldest_datname); SetTransactionIdLimit(oldest_datfrozenxid, &oldest_datname);
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.171 2006/10/04 00:30:02 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.172 2006/11/05 22:42:09 tgl Exp $
* *
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
...@@ -77,7 +77,7 @@ FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace) ...@@ -77,7 +77,7 @@ FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace)
char *filename; char *filename;
FILE *db_file; FILE *db_file;
char thisname[NAMEDATALEN]; char thisname[NAMEDATALEN];
TransactionId dummyxid; TransactionId db_frozenxid;
filename = database_getflatfilename(); filename = database_getflatfilename();
db_file = AllocateFile(filename, "r"); db_file = AllocateFile(filename, "r");
...@@ -87,8 +87,7 @@ FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace) ...@@ -87,8 +87,7 @@ FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace)
errmsg("could not open file \"%s\": %m", filename))); errmsg("could not open file \"%s\": %m", filename)));
while (read_pg_database_line(db_file, thisname, db_id, while (read_pg_database_line(db_file, thisname, db_id,
db_tablespace, &dummyxid, db_tablespace, &db_frozenxid))
&dummyxid))
{ {
if (strcmp(thisname, name) == 0) if (strcmp(thisname, name) == 0)
{ {
......
...@@ -10,7 +10,7 @@ ...@@ -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.357 2006/10/19 18:32:47 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.358 2006/11/05 22:42:09 tgl Exp $
* *
*-------------------------------------------------------------------- *--------------------------------------------------------------------
*/ */
...@@ -1330,6 +1330,15 @@ static struct config_int ConfigureNamesInt[] = ...@@ -1330,6 +1330,15 @@ static struct config_int ConfigureNamesInt[] =
0, 0, INT_MAX, NULL, NULL 0, 0, INT_MAX, NULL, NULL
}, },
{
{"vacuum_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
gettext_noop("Minimum age at which VACUUM should freeze a table row."),
NULL
},
&vacuum_freeze_min_age,
100000000, 0, 1000000000, NULL, NULL
},
{ {
{"max_fsm_relations", PGC_POSTMASTER, RESOURCES_FSM, {"max_fsm_relations", PGC_POSTMASTER, RESOURCES_FSM,
gettext_noop("Sets the maximum number of tables and indexes for which free space is tracked."), gettext_noop("Sets the maximum number of tables and indexes for which free space is tracked."),
...@@ -1576,6 +1585,15 @@ static struct config_int ConfigureNamesInt[] = ...@@ -1576,6 +1585,15 @@ static struct config_int ConfigureNamesInt[] =
&autovacuum_anl_thresh, &autovacuum_anl_thresh,
250, 0, INT_MAX, NULL, NULL 250, 0, INT_MAX, NULL, NULL
}, },
{
/* see varsup.c for why this is PGC_POSTMASTER not PGC_SIGHUP */
{"autovacuum_freeze_max_age", PGC_POSTMASTER, AUTOVACUUM,
gettext_noop("Age at which to autovacuum a table to prevent transacion ID wraparound."),
NULL
},
&autovacuum_freeze_max_age,
200000000, 100000000, 2000000000, NULL, NULL
},
{ {
{"tcp_keepalives_idle", PGC_USERSET, CLIENT_CONN_OTHER, {"tcp_keepalives_idle", PGC_USERSET, CLIENT_CONN_OTHER,
......
...@@ -373,6 +373,8 @@ ...@@ -373,6 +373,8 @@
# vacuum # vacuum
#autovacuum_analyze_scale_factor = 0.1 # fraction of rel size before #autovacuum_analyze_scale_factor = 0.1 # fraction of rel size before
# analyze # analyze
#autovacuum_freeze_max_age = 200000000 # maximum XID age before forced vacuum
# (change requires restart)
#autovacuum_vacuum_cost_delay = -1 # default vacuum cost delay for #autovacuum_vacuum_cost_delay = -1 # default vacuum cost delay for
# autovacuum, -1 means use # autovacuum, -1 means use
# vacuum_cost_delay # vacuum_cost_delay
...@@ -394,6 +396,7 @@ ...@@ -394,6 +396,7 @@
#default_transaction_isolation = 'read committed' #default_transaction_isolation = 'read committed'
#default_transaction_read_only = off #default_transaction_read_only = off
#statement_timeout = 0 # 0 is disabled #statement_timeout = 0 # 0 is disabled
#vacuum_freeze_min_age = 100000000
# - Locale and Formatting - # - Locale and Formatting -
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.98 2006/10/04 00:30:04 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.99 2006/11/05 22:42:09 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1099,9 +1099,11 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin, ...@@ -1099,9 +1099,11 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
{ {
/* /*
* "Deleting" xact really only locked it, so the tuple is live in any * "Deleting" xact really only locked it, so the tuple is live in any
* case. However, we must make sure that either XMAX_COMMITTED or * case. However, we should make sure that either XMAX_COMMITTED or
* XMAX_INVALID gets set once the xact is gone; otherwise it is unsafe * XMAX_INVALID gets set once the xact is gone, to reduce the costs
* to recycle CLOG status after vacuuming. * of examining the tuple for future xacts. Also, marking dead
* MultiXacts as invalid here provides defense against MultiXactId
* wraparound (see also comments in heap_freeze_tuple()).
*/ */
if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED)) if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
{ {
......
...@@ -6,7 +6,7 @@ ...@@ -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/clog.h,v 1.17 2006/03/24 04:32:13 tgl Exp $ * $PostgreSQL: pgsql/src/include/access/clog.h,v 1.18 2006/11/05 22:42:09 tgl Exp $
*/ */
#ifndef CLOG_H #ifndef CLOG_H
#define CLOG_H #define CLOG_H
...@@ -46,6 +46,7 @@ extern void TruncateCLOG(TransactionId oldestXact); ...@@ -46,6 +46,7 @@ extern void TruncateCLOG(TransactionId oldestXact);
/* XLOG stuff */ /* XLOG stuff */
#define CLOG_ZEROPAGE 0x00 #define CLOG_ZEROPAGE 0x00
#define CLOG_TRUNCATE 0x10
extern void clog_redo(XLogRecPtr lsn, XLogRecord *record); extern void clog_redo(XLogRecPtr lsn, XLogRecord *record);
extern void clog_desc(StringInfo buf, uint8 xl_info, char *rec); extern void clog_desc(StringInfo buf, uint8 xl_info, char *rec);
......
...@@ -7,7 +7,7 @@ ...@@ -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/access/heapam.h,v 1.116 2006/10/04 00:30:07 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.117 2006/11/05 22:42:10 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -170,6 +170,8 @@ extern HTSU_Result heap_lock_tuple(Relation relation, HeapTuple tuple, ...@@ -170,6 +170,8 @@ extern HTSU_Result heap_lock_tuple(Relation relation, HeapTuple tuple,
TransactionId *update_xmax, CommandId cid, TransactionId *update_xmax, CommandId cid,
LockTupleMode mode, bool nowait); LockTupleMode mode, bool nowait);
extern void heap_inplace_update(Relation relation, HeapTuple tuple); extern void heap_inplace_update(Relation relation, HeapTuple tuple);
extern bool heap_freeze_tuple(HeapTupleHeader tuple, TransactionId cutoff_xid,
Buffer buf);
extern Oid simple_heap_insert(Relation relation, HeapTuple tup); extern Oid simple_heap_insert(Relation relation, HeapTuple tup);
extern void simple_heap_delete(Relation relation, ItemPointer tid); extern void simple_heap_delete(Relation relation, ItemPointer tid);
...@@ -181,11 +183,17 @@ extern void heap_restrpos(HeapScanDesc scan); ...@@ -181,11 +183,17 @@ extern void heap_restrpos(HeapScanDesc scan);
extern void heap_redo(XLogRecPtr lsn, XLogRecord *rptr); extern void heap_redo(XLogRecPtr lsn, XLogRecord *rptr);
extern void heap_desc(StringInfo buf, uint8 xl_info, char *rec); extern void heap_desc(StringInfo buf, uint8 xl_info, char *rec);
extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer, extern void heap2_redo(XLogRecPtr lsn, XLogRecord *rptr);
OffsetNumber *unused, int uncnt); extern void heap2_desc(StringInfo buf, uint8 xl_info, char *rec);
extern XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf, extern XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf,
ItemPointerData from, ItemPointerData from,
Buffer newbuf, HeapTuple newtup); Buffer newbuf, HeapTuple newtup);
extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer,
OffsetNumber *unused, int uncnt);
extern XLogRecPtr log_heap_freeze(Relation reln, Buffer buffer,
TransactionId cutoff_xid,
OffsetNumber *offsets, int offcnt);
/* in common/heaptuple.c */ /* in common/heaptuple.c */
extern Size heap_compute_data_size(TupleDesc tupleDesc, extern Size heap_compute_data_size(TupleDesc tupleDesc,
......
...@@ -7,7 +7,7 @@ ...@@ -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/access/htup.h,v 1.86 2006/10/04 00:30:07 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/htup.h,v 1.87 2006/11/05 22:42:10 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -510,6 +510,13 @@ typedef HeapTupleData *HeapTuple; ...@@ -510,6 +510,13 @@ typedef HeapTupleData *HeapTuple;
* we can (and we do) restore entire page in redo * we can (and we do) restore entire page in redo
*/ */
#define XLOG_HEAP_INIT_PAGE 0x80 #define XLOG_HEAP_INIT_PAGE 0x80
/*
* We ran out of opcodes, so heapam.c now has a second RmgrId. These opcodes
* are associated with RM_HEAP2_ID, but are not logically different from
* the ones above associated with RM_HEAP_ID. We apply XLOG_HEAP_OPMASK,
* although currently XLOG_HEAP_INIT_PAGE is not used for any of these.
*/
#define XLOG_HEAP2_FREEZE 0x00
/* /*
* All what we need to find changed tuple * All what we need to find changed tuple
...@@ -613,4 +620,15 @@ typedef struct xl_heap_inplace ...@@ -613,4 +620,15 @@ typedef struct xl_heap_inplace
#define SizeOfHeapInplace (offsetof(xl_heap_inplace, target) + SizeOfHeapTid) #define SizeOfHeapInplace (offsetof(xl_heap_inplace, target) + SizeOfHeapTid)
/* This is what we need to know about tuple freezing during vacuum */
typedef struct xl_heap_freeze
{
RelFileNode node;
BlockNumber block;
TransactionId cutoff_xid;
/* TUPLE OFFSET NUMBERS FOLLOW AT THE END */
} xl_heap_freeze;
#define SizeOfHeapFreeze (offsetof(xl_heap_freeze, cutoff_xid) + sizeof(TransactionId))
#endif /* HTUP_H */ #endif /* HTUP_H */
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Resource managers definition * Resource managers definition
* *
* $PostgreSQL: pgsql/src/include/access/rmgr.h,v 1.16 2006/05/02 11:28:55 teodor Exp $ * $PostgreSQL: pgsql/src/include/access/rmgr.h,v 1.17 2006/11/05 22:42:10 tgl Exp $
*/ */
#ifndef RMGR_H #ifndef RMGR_H
#define RMGR_H #define RMGR_H
...@@ -12,6 +12,9 @@ typedef uint8 RmgrId; ...@@ -12,6 +12,9 @@ typedef uint8 RmgrId;
/* /*
* Built-in resource managers * Built-in resource managers
*
* Note: RM_MAX_ID could be as much as 255 without breaking the XLOG file
* format, but we keep it small to minimize the size of RmgrTable[].
*/ */
#define RM_XLOG_ID 0 #define RM_XLOG_ID 0
#define RM_XACT_ID 1 #define RM_XACT_ID 1
...@@ -20,6 +23,7 @@ typedef uint8 RmgrId; ...@@ -20,6 +23,7 @@ typedef uint8 RmgrId;
#define RM_DBASE_ID 4 #define RM_DBASE_ID 4
#define RM_TBLSPC_ID 5 #define RM_TBLSPC_ID 5
#define RM_MULTIXACT_ID 6 #define RM_MULTIXACT_ID 6
#define RM_HEAP2_ID 9
#define RM_HEAP_ID 10 #define RM_HEAP_ID 10
#define RM_BTREE_ID 11 #define RM_BTREE_ID 11
#define RM_HASH_ID 12 #define RM_HASH_ID 12
......
...@@ -7,7 +7,7 @@ ...@@ -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/access/transam.h,v 1.58 2006/07/10 16:20:51 alvherre Exp $ * $PostgreSQL: pgsql/src/include/access/transam.h,v 1.59 2006/11/05 22:42:10 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
* always be considered valid. * always be considered valid.
* *
* FirstNormalTransactionId is the first "normal" transaction id. * FirstNormalTransactionId is the first "normal" transaction id.
* Note: if you need to change it, you must change it in pg_class.h as well. * Note: if you need to change it, you must change pg_class.h as well.
* ---------------- * ----------------
*/ */
#define InvalidTransactionId ((TransactionId) 0) #define InvalidTransactionId ((TransactionId) 0)
...@@ -88,6 +88,9 @@ typedef struct VariableCacheData ...@@ -88,6 +88,9 @@ typedef struct VariableCacheData
Oid nextOid; /* next OID to assign */ Oid nextOid; /* next OID to assign */
uint32 oidCount; /* OIDs available before must do XLOG work */ uint32 oidCount; /* OIDs available before must do XLOG work */
TransactionId nextXid; /* next XID to assign */ TransactionId nextXid; /* next XID to assign */
TransactionId oldestXid; /* cluster-wide minimum datfrozenxid */
TransactionId xidVacLimit; /* start forcing autovacuums here */
TransactionId xidWarnLimit; /* start complaining here */ TransactionId xidWarnLimit; /* start complaining here */
TransactionId xidStopLimit; /* refuse to advance nextXid beyond here */ TransactionId xidStopLimit; /* refuse to advance nextXid beyond here */
TransactionId xidWrapLimit; /* where the world ends */ TransactionId xidWrapLimit; /* where the world ends */
...@@ -124,7 +127,7 @@ extern bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2); ...@@ -124,7 +127,7 @@ extern bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2);
/* in transam/varsup.c */ /* in transam/varsup.c */
extern TransactionId GetNewTransactionId(bool isSubXact); extern TransactionId GetNewTransactionId(bool isSubXact);
extern TransactionId ReadNewTransactionId(void); extern TransactionId ReadNewTransactionId(void);
extern void SetTransactionIdLimit(TransactionId oldest_datminxid, extern void SetTransactionIdLimit(TransactionId oldest_datfrozenxid,
Name oldest_datname); Name oldest_datname);
extern Oid GetNewObjectId(void); extern Oid GetNewObjectId(void);
......
...@@ -6,7 +6,7 @@ ...@@ -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.74 2006/08/21 16:16:31 tgl Exp $ * $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.75 2006/11/05 22:42:10 tgl Exp $
*/ */
#ifndef XLOG_H #ifndef XLOG_H
#define XLOG_H #define XLOG_H
...@@ -165,7 +165,6 @@ extern void InitXLOGAccess(void); ...@@ -165,7 +165,6 @@ extern void InitXLOGAccess(void);
extern void CreateCheckPoint(bool shutdown, bool force); extern void CreateCheckPoint(bool shutdown, bool force);
extern void XLogPutNextOid(Oid nextOid); extern void XLogPutNextOid(Oid nextOid);
extern XLogRecPtr GetRedoRecPtr(void); extern XLogRecPtr GetRedoRecPtr(void);
extern TransactionId GetRecentNextXid(void);
extern void GetNextXidAndEpoch(TransactionId *xid, uint32 *epoch); extern void GetNextXidAndEpoch(TransactionId *xid, uint32 *epoch);
#endif /* XLOG_H */ #endif /* XLOG_H */
...@@ -37,7 +37,7 @@ ...@@ -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.358 2006/09/18 22:40:38 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.359 2006/11/05 22:42:10 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200609181 #define CATALOG_VERSION_NO 200611051
#endif #endif
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,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_attribute.h,v 1.125 2006/10/04 00:30:07 momjian Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.126 2006/11/05 22:42:10 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -404,10 +404,9 @@ DATA(insert ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0)); ...@@ -404,10 +404,9 @@ DATA(insert ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
{ 1259, {"relhaspkey"}, 16, -1, 1, 22, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \ { 1259, {"relhaspkey"}, 16, -1, 1, 22, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relhasrules"}, 16, -1, 1, 23, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \ { 1259, {"relhasrules"}, 16, -1, 1, 23, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relhassubclass"},16, -1, 1, 24, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \ { 1259, {"relhassubclass"},16, -1, 1, 24, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
{ 1259, {"relminxid"}, 28, -1, 4, 25, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ { 1259, {"relfrozenxid"}, 28, -1, 4, 25, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"relvacuumxid"}, 28, -1, 4, 26, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ { 1259, {"relacl"}, 1034, -1, -1, 26, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
{ 1259, {"relacl"}, 1034, -1, -1, 27, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \ { 1259, {"reloptions"}, 1009, -1, -1, 27, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
{ 1259, {"reloptions"}, 1009, -1, -1, 28, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
DATA(insert ( 1259 relname 19 -1 NAMEDATALEN 1 0 -1 -1 f p i t f f t 0)); DATA(insert ( 1259 relname 19 -1 NAMEDATALEN 1 0 -1 -1 f p i t f f t 0));
DATA(insert ( 1259 relnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1259 relnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0));
...@@ -433,10 +432,9 @@ DATA(insert ( 1259 relhasoids 16 -1 1 21 0 -1 -1 t p c t f f t 0)); ...@@ -433,10 +432,9 @@ DATA(insert ( 1259 relhasoids 16 -1 1 21 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relhaspkey 16 -1 1 22 0 -1 -1 t p c t f f t 0)); DATA(insert ( 1259 relhaspkey 16 -1 1 22 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relhasrules 16 -1 1 23 0 -1 -1 t p c t f f t 0)); DATA(insert ( 1259 relhasrules 16 -1 1 23 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relhassubclass 16 -1 1 24 0 -1 -1 t p c t f f t 0)); DATA(insert ( 1259 relhassubclass 16 -1 1 24 0 -1 -1 t p c t f f t 0));
DATA(insert ( 1259 relminxid 28 -1 4 25 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1259 relfrozenxid 28 -1 4 25 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 relvacuumxid 28 -1 4 26 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1259 relacl 1034 -1 -1 26 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1259 relacl 1034 -1 -1 27 1 -1 -1 f x i f f f t 0)); DATA(insert ( 1259 reloptions 1009 -1 -1 27 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1259 reloptions 1009 -1 -1 28 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1259 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0)); DATA(insert ( 1259 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0));
DATA(insert ( 1259 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1259 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1259 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0));
......
...@@ -6,7 +6,7 @@ ...@@ -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/catalog/pg_autovacuum.h,v 1.4 2006/03/05 15:58:54 momjian Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_autovacuum.h,v 1.5 2006/11/05 22:42:10 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -28,14 +28,16 @@ ...@@ -28,14 +28,16 @@
#define AutovacuumRelationId 1248 #define AutovacuumRelationId 1248
CATALOG(pg_autovacuum,1248) BKI_WITHOUT_OIDS CATALOG(pg_autovacuum,1248) BKI_WITHOUT_OIDS
{ {
Oid vacrelid; /* OID of table */ Oid vacrelid; /* OID of table */
bool enabled; /* enabled for this table? */ bool enabled; /* enabled for this table? */
int4 vac_base_thresh; /* base threshold value */ int4 vac_base_thresh; /* base threshold value */
float4 vac_scale_factor; /* reltuples scaling factor */ float4 vac_scale_factor; /* reltuples scaling factor */
int4 anl_base_thresh; /* base threshold value */ int4 anl_base_thresh; /* base threshold value */
float4 anl_scale_factor; /* reltuples scaling factor */ float4 anl_scale_factor; /* reltuples scaling factor */
int4 vac_cost_delay; /* vacuum cost-based delay */ int4 vac_cost_delay; /* vacuum cost-based delay */
int4 vac_cost_limit; /* vacuum cost limit */ int4 vac_cost_limit; /* vacuum cost limit */
int4 freeze_min_age; /* vacuum min freeze age */
int4 freeze_max_age; /* max age before forcing vacuum */
} FormData_pg_autovacuum; } FormData_pg_autovacuum;
/* ---------------- /* ----------------
...@@ -49,7 +51,7 @@ typedef FormData_pg_autovacuum *Form_pg_autovacuum; ...@@ -49,7 +51,7 @@ typedef FormData_pg_autovacuum *Form_pg_autovacuum;
* compiler constants for pg_autovacuum * compiler constants for pg_autovacuum
* ---------------- * ----------------
*/ */
#define Natts_pg_autovacuum 8 #define Natts_pg_autovacuum 10
#define Anum_pg_autovacuum_vacrelid 1 #define Anum_pg_autovacuum_vacrelid 1
#define Anum_pg_autovacuum_enabled 2 #define Anum_pg_autovacuum_enabled 2
#define Anum_pg_autovacuum_vac_base_thresh 3 #define Anum_pg_autovacuum_vac_base_thresh 3
...@@ -58,6 +60,8 @@ typedef FormData_pg_autovacuum *Form_pg_autovacuum; ...@@ -58,6 +60,8 @@ typedef FormData_pg_autovacuum *Form_pg_autovacuum;
#define Anum_pg_autovacuum_anl_scale_factor 6 #define Anum_pg_autovacuum_anl_scale_factor 6
#define Anum_pg_autovacuum_vac_cost_delay 7 #define Anum_pg_autovacuum_vac_cost_delay 7
#define Anum_pg_autovacuum_vac_cost_limit 8 #define Anum_pg_autovacuum_vac_cost_limit 8
#define Anum_pg_autovacuum_freeze_min_age 9
#define Anum_pg_autovacuum_freeze_max_age 10
/* There are no preloaded tuples in pg_autovacuum.h */ /* There are no preloaded tuples in pg_autovacuum.h */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,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_class.h,v 1.96 2006/10/04 00:30:07 momjian Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_class.h,v 1.97 2006/11/05 22:42:10 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -65,8 +65,7 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP ...@@ -65,8 +65,7 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP
bool relhaspkey; /* has PRIMARY KEY index */ bool relhaspkey; /* has PRIMARY KEY index */
bool relhasrules; /* has associated rules */ bool relhasrules; /* has associated rules */
bool relhassubclass; /* has derived classes */ bool relhassubclass; /* has derived classes */
TransactionId relminxid; /* minimum Xid present in table */ TransactionId relfrozenxid; /* all Xids < this are frozen in this rel */
TransactionId relvacuumxid; /* Xid used as last vacuum OldestXmin */
/* /*
* VARIABLE LENGTH FIELDS start here. These fields may be NULL, too. * VARIABLE LENGTH FIELDS start here. These fields may be NULL, too.
...@@ -80,7 +79,7 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP ...@@ -80,7 +79,7 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP
/* Size of fixed part of pg_class tuples, not counting var-length fields */ /* Size of fixed part of pg_class tuples, not counting var-length fields */
#define CLASS_TUPLE_SIZE \ #define CLASS_TUPLE_SIZE \
(offsetof(FormData_pg_class,relvacuumxid) + sizeof(TransactionId)) (offsetof(FormData_pg_class,relfrozenxid) + sizeof(TransactionId))
/* ---------------- /* ----------------
* Form_pg_class corresponds to a pointer to a tuple with * Form_pg_class corresponds to a pointer to a tuple with
...@@ -94,7 +93,7 @@ typedef FormData_pg_class *Form_pg_class; ...@@ -94,7 +93,7 @@ typedef FormData_pg_class *Form_pg_class;
* ---------------- * ----------------
*/ */
#define Natts_pg_class 28 #define Natts_pg_class 27
#define Anum_pg_class_relname 1 #define Anum_pg_class_relname 1
#define Anum_pg_class_relnamespace 2 #define Anum_pg_class_relnamespace 2
#define Anum_pg_class_reltype 3 #define Anum_pg_class_reltype 3
...@@ -119,27 +118,27 @@ typedef FormData_pg_class *Form_pg_class; ...@@ -119,27 +118,27 @@ typedef FormData_pg_class *Form_pg_class;
#define Anum_pg_class_relhaspkey 22 #define Anum_pg_class_relhaspkey 22
#define Anum_pg_class_relhasrules 23 #define Anum_pg_class_relhasrules 23
#define Anum_pg_class_relhassubclass 24 #define Anum_pg_class_relhassubclass 24
#define Anum_pg_class_relminxid 25 #define Anum_pg_class_relfrozenxid 25
#define Anum_pg_class_relvacuumxid 26 #define Anum_pg_class_relacl 26
#define Anum_pg_class_relacl 27 #define Anum_pg_class_reloptions 27
#define Anum_pg_class_reloptions 28
/* ---------------- /* ----------------
* initial contents of pg_class * initial contents of pg_class
* *
* NOTE: only "bootstrapped" relations need to be declared here. Be sure that * NOTE: only "bootstrapped" relations need to be declared here. Be sure that
* the OIDs listed here match those given in their CATALOG macros. * the OIDs listed here match those given in their CATALOG macros, and that
* the relnatts values are correct.
* ---------------- * ----------------
*/ */
/* Note: the "3" here stands for FirstNormalTransactionId */ /* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId */
DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 23 0 0 0 0 0 t f f f 3 3 _null_ _null_ )); DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 23 0 0 0 0 0 t f f f 3 _null_ _null_ ));
DESCR(""); DESCR("");
DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 0 0 0 0 f f f f 3 3 _null_ _null_ )); DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 0 0 0 0 f f f f 3 _null_ _null_ ));
DESCR(""); DESCR("");
DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 0 0 f f r 18 0 0 0 0 0 t f f f 3 3 _null_ _null_ )); DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 0 0 f f r 18 0 0 0 0 0 t f f f 3 _null_ _null_ ));
DESCR(""); DESCR("");
DATA(insert OID = 1259 ( pg_class PGNSP 83 PGUID 0 1259 0 0 0 0 0 f f r 28 0 0 0 0 0 t f f f 3 3 _null_ _null_ )); DATA(insert OID = 1259 ( pg_class PGNSP 83 PGUID 0 1259 0 0 0 0 0 f f r 27 0 0 0 0 0 t f f f 3 _null_ _null_ ));
DESCR(""); DESCR("");
#define RELKIND_INDEX 'i' /* secondary index */ #define RELKIND_INDEX 'i' /* secondary index */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,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_database.h,v 1.41 2006/07/10 16:20:51 alvherre Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_database.h,v 1.42 2006/11/05 22:42:10 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -42,8 +42,7 @@ CATALOG(pg_database,1262) BKI_SHARED_RELATION ...@@ -42,8 +42,7 @@ CATALOG(pg_database,1262) BKI_SHARED_RELATION
bool datallowconn; /* new connections allowed? */ bool datallowconn; /* new connections allowed? */
int4 datconnlimit; /* max connections allowed (-1=no limit) */ int4 datconnlimit; /* max connections allowed (-1=no limit) */
Oid datlastsysoid; /* highest OID to consider a system OID */ Oid datlastsysoid; /* highest OID to consider a system OID */
TransactionId datvacuumxid; /* all XIDs before this are vacuumed */ TransactionId datfrozenxid; /* all Xids < this are frozen in this DB */
TransactionId datminxid; /* minimum XID present anywhere in the DB */
Oid dattablespace; /* default table space for this DB */ Oid dattablespace; /* default table space for this DB */
text datconfig[1]; /* database-specific GUC (VAR LENGTH) */ text datconfig[1]; /* database-specific GUC (VAR LENGTH) */
aclitem datacl[1]; /* access permissions (VAR LENGTH) */ aclitem datacl[1]; /* access permissions (VAR LENGTH) */
...@@ -60,7 +59,7 @@ typedef FormData_pg_database *Form_pg_database; ...@@ -60,7 +59,7 @@ typedef FormData_pg_database *Form_pg_database;
* compiler constants for pg_database * compiler constants for pg_database
* ---------------- * ----------------
*/ */
#define Natts_pg_database 12 #define Natts_pg_database 11
#define Anum_pg_database_datname 1 #define Anum_pg_database_datname 1
#define Anum_pg_database_datdba 2 #define Anum_pg_database_datdba 2
#define Anum_pg_database_encoding 3 #define Anum_pg_database_encoding 3
...@@ -68,13 +67,12 @@ typedef FormData_pg_database *Form_pg_database; ...@@ -68,13 +67,12 @@ typedef FormData_pg_database *Form_pg_database;
#define Anum_pg_database_datallowconn 5 #define Anum_pg_database_datallowconn 5
#define Anum_pg_database_datconnlimit 6 #define Anum_pg_database_datconnlimit 6
#define Anum_pg_database_datlastsysoid 7 #define Anum_pg_database_datlastsysoid 7
#define Anum_pg_database_datvacuumxid 8 #define Anum_pg_database_datfrozenxid 8
#define Anum_pg_database_datminxid 9 #define Anum_pg_database_dattablespace 9
#define Anum_pg_database_dattablespace 10 #define Anum_pg_database_datconfig 10
#define Anum_pg_database_datconfig 11 #define Anum_pg_database_datacl 11
#define Anum_pg_database_datacl 12
DATA(insert OID = 1 ( template1 PGUID ENCODING t t -1 0 0 0 1663 _null_ _null_ )); DATA(insert OID = 1 ( template1 PGUID ENCODING t t -1 0 0 1663 _null_ _null_ ));
SHDESCR("Default template database"); SHDESCR("Default template database");
#define TemplateDbOid 1 #define TemplateDbOid 1
......
...@@ -7,7 +7,7 @@ ...@@ -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/commands/vacuum.h,v 1.67 2006/07/13 18:01:02 momjian Exp $ * $PostgreSQL: pgsql/src/include/commands/vacuum.h,v 1.68 2006/11/05 22:42:10 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -104,8 +104,9 @@ typedef struct VacAttrStats ...@@ -104,8 +104,9 @@ typedef struct VacAttrStats
} VacAttrStats; } VacAttrStats;
/* Default statistics target (GUC parameter) */ /* GUC parameters */
extern DLLIMPORT int default_statistics_target; /* DLLIMPORT for PostGIS */ extern DLLIMPORT int default_statistics_target; /* DLLIMPORT for PostGIS */
extern int vacuum_freeze_min_age;
/* in commands/vacuum.c */ /* in commands/vacuum.c */
...@@ -117,14 +118,13 @@ extern void vac_update_relstats(Oid relid, ...@@ -117,14 +118,13 @@ extern void vac_update_relstats(Oid relid,
BlockNumber num_pages, BlockNumber num_pages,
double num_tuples, double num_tuples,
bool hasindex, bool hasindex,
TransactionId minxid, TransactionId frozenxid);
TransactionId vacuumxid);
extern void vacuum_set_xid_limits(VacuumStmt *vacstmt, bool sharedRel, extern void vacuum_set_xid_limits(VacuumStmt *vacstmt, bool sharedRel,
TransactionId *oldestXmin, TransactionId *oldestXmin,
TransactionId *freezeLimit); TransactionId *freezeLimit);
extern void vac_update_datfrozenxid(void);
extern bool vac_is_partial_index(Relation indrel); extern bool vac_is_partial_index(Relation indrel);
extern void vacuum_delay_point(void); extern void vacuum_delay_point(void);
extern TransactionId vactuple_get_minxid(HeapTuple tuple);
/* in commands/vacuumlazy.c */ /* in commands/vacuumlazy.c */
extern void lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt); extern void lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt);
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Interface to hba.c * Interface to hba.c
* *
* *
* $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.44 2006/10/04 00:30:08 momjian Exp $ * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.45 2006/11/05 22:42:10 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -40,7 +40,6 @@ extern void load_role(void); ...@@ -40,7 +40,6 @@ extern void load_role(void);
extern int hba_getauthmethod(hbaPort *port); extern int hba_getauthmethod(hbaPort *port);
extern int authident(hbaPort *port); extern int authident(hbaPort *port);
extern bool read_pg_database_line(FILE *fp, char *dbname, Oid *dboid, extern bool read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
Oid *dbtablespace, TransactionId *dbminxid, Oid *dbtablespace, TransactionId *dbfrozenxid);
TransactionId *dbvacuumxid);
#endif /* HBA_H */ #endif /* HBA_H */
...@@ -7,7 +7,7 @@ ...@@ -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/nodes/parsenodes.h,v 1.333 2006/10/13 21:43:19 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.334 2006/11/05 22:42:10 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1756,8 +1756,8 @@ typedef struct VacuumStmt ...@@ -1756,8 +1756,8 @@ typedef struct VacuumStmt
bool vacuum; /* do VACUUM step */ bool vacuum; /* do VACUUM step */
bool full; /* do FULL (non-concurrent) vacuum */ bool full; /* do FULL (non-concurrent) vacuum */
bool analyze; /* do ANALYZE step */ bool analyze; /* do ANALYZE step */
bool freeze; /* early-freeze option */
bool verbose; /* print progress info */ bool verbose; /* print progress info */
int freeze_min_age; /* min freeze age, or -1 to use default */
RangeVar *relation; /* single table to process, or NULL */ RangeVar *relation; /* single table to process, or NULL */
List *va_cols; /* list of column names, or NIL for all */ List *va_cols; /* list of column names, or NIL for all */
} VacuumStmt; } VacuumStmt;
......
...@@ -7,7 +7,7 @@ ...@@ -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/postmaster/autovacuum.h,v 1.4 2006/03/05 15:58:58 momjian Exp $ * $PostgreSQL: pgsql/src/include/postmaster/autovacuum.h,v 1.5 2006/11/05 22:42:10 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -21,6 +21,7 @@ extern int autovacuum_vac_thresh; ...@@ -21,6 +21,7 @@ extern int autovacuum_vac_thresh;
extern double autovacuum_vac_scale; extern double autovacuum_vac_scale;
extern int autovacuum_anl_thresh; extern int autovacuum_anl_thresh;
extern double autovacuum_anl_scale; extern double autovacuum_anl_scale;
extern int autovacuum_freeze_max_age;
extern int autovacuum_vac_cost_delay; extern int autovacuum_vac_cost_delay;
extern int autovacuum_vac_cost_limit; extern int autovacuum_vac_cost_limit;
......
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