Autovacuum loose end mop-up. Provide autovacuum-specific vacuum cost

delay and limit, both as global GUCs and as table-specific entries in
pg_autovacuum.  stats_reset_on_server_start is now OFF by default,
but a reset is forced if we did WAL replay.  XID-wrap vacuums do not
ANALYZE, but do FREEZE if it's a template database.  Alvaro Herrera
This commit is contained in:
Tom Lane 2005-08-11 21:11:50 +00:00
parent f6c30d54fa
commit d90c531188
18 changed files with 456 additions and 209 deletions

View File

@ -1,6 +1,6 @@
<!-- <!--
Documentation of the system catalogs, directed toward PostgreSQL developers Documentation of the system catalogs, directed toward PostgreSQL developers
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.110 2005/07/31 17:19:16 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.111 2005/08/11 21:11:41 tgl Exp $
--> -->
<chapter id="catalogs"> <chapter id="catalogs">
@ -1197,6 +1197,20 @@
<entry>Multiplier for reltuples to add to <entry>Multiplier for reltuples to add to
<structfield>anl_base_thresh</></entry> <structfield>anl_base_thresh</></entry>
</row> </row>
<row>
<entry><structfield>vac_cost_delay</structfield></entry>
<entry><type>integer</type></entry>
<entry></entry>
<entry>Custom <varname>vacuum_cost_delay</> parameter</entry>
</row>
<row>
<entry><structfield>vac_cost_limit</structfield></entry>
<entry><type>integer</type></entry>
<entry></entry>
<entry>Custom <varname>vacuum_cost_limit</> parameter</entry>
</row>
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
@ -1217,7 +1231,11 @@
<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
be used for this particular value. be used for this particular value. Observe that the
<structfield>vac_cost_delay</> variable inherits its default value from the
<varname>autovacuum_vacuum_cost_delay</> configuration parameter,
or from <varname>vacuum_cost_delay</> if the former is set to a negative
value. The same applies to <structfield>vac_cost_limit</>.
</para> </para>
</sect1> </sect1>

View File

@ -1,5 +1,5 @@
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.343 2005/08/09 05:01:10 momjian Exp $ $PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.344 2005/08/11 21:11:42 tgl Exp $
--> -->
<chapter Id="runtime"> <chapter Id="runtime">
@ -3296,7 +3296,7 @@ SELECT * FROM parent WHERE key = 2400;
<para> <para>
If on, collected statistics are zeroed out whenever the server If on, collected statistics are zeroed out whenever the server
is restarted. If off, statistics are accumulated across server is restarted. If off, statistics are accumulated across server
restarts. The default is <literal>on</>. This option can only restarts. The default is <literal>off</>. This option can only
be set at server start. be set at server start.
</para> </para>
</listitem> </listitem>
@ -3424,6 +3424,40 @@ SELECT * FROM parent WHERE key = 2400;
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry id="guc-autovacuum-vacuum-cost-delay" xreflabel="autovacuum_vacuum_cost_delay">
<term><varname>autovacuum_vacuum_cost_delay</varname> (<type>integer</type>)</term>
<indexterm>
<primary><varname>autovacuum_vacuum_cost_delay</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
Specifies the cost delay value that will be used in automatic
<command>VACUUM</> operations. If -1 is specified (which is the
default), the regular
<xref linkend="guc-vacuum-cost-delay"> value will be used.
This setting can be overridden for individual tables by entries in
<structname>pg_autovacuum</>.
</para>
</listitem>
</varlistentry>
<varlistentry id="guc-autovacuum-vacuum-cost-limit" xreflabel="autovacuum_vacuum_cost_limit">
<term><varname>autovacuum_vacuum_cost_limit</varname> (<type>integer</type>)</term>
<indexterm>
<primary><varname>autovacuum_vacuum_cost_limit</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
Specifies the cost limit value that will be used in automatic
<command>VACUUM</> operations. If -1 is specified (which is the
default), the regular
<xref linkend="guc-vacuum-cost-limit"> value will be used.
This setting can be overridden for individual tables by entries in
<structname>pg_autovacuum</>.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</sect2> </sect2>

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, 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.214 2005/07/30 14:15:44 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.215 2005/08/11 21:11:43 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -33,6 +33,7 @@
#include "catalog/catversion.h" #include "catalog/catversion.h"
#include "catalog/pg_control.h" #include "catalog/pg_control.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "pgstat.h"
#include "postmaster/bgwriter.h" #include "postmaster/bgwriter.h"
#include "storage/bufpage.h" #include "storage/bufpage.h"
#include "storage/fd.h" #include "storage/fd.h"
@ -48,7 +49,7 @@
/* /*
* Becauase O_DIRECT bypasses the kernel buffers, and because we never * Because O_DIRECT bypasses the kernel buffers, and because we never
* read those buffers except during crash recovery, it is a win to use * read those buffers except during crash recovery, it is a win to use
* it in all cases where we sync on each write(). We could allow O_DIRECT * it in all cases where we sync on each write(). We could allow O_DIRECT
* with fsync(), but because skipping the kernel buffer forces writes out * with fsync(), but because skipping the kernel buffer forces writes out
@ -4685,6 +4686,11 @@ StartupXLOG(void)
RmgrTable[rmid].rm_cleanup(); RmgrTable[rmid].rm_cleanup();
} }
/*
* Reset pgstat data, because it may be invalid after recovery.
*/
pgstat_reset_all();
/* /*
* Perform a new checkpoint to update our recovery activity to * Perform a new checkpoint to update our recovery activity to
* disk. * disk.

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.146 2005/07/29 19:30:04 tgl Exp $ * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.147 2005/08/11 21:11:44 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1001,13 +1001,15 @@ load_hba(void)
* dboid: gets database OID * dboid: gets database OID
* dbtablespace: gets database's default tablespace's OID * dbtablespace: gets database's default tablespace's OID
* dbfrozenxid: gets database's frozen 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 *dbfrozenxid) Oid *dbtablespace, TransactionId *dbfrozenxid,
TransactionId *dbvacuumxid)
{ {
char buf[MAX_TOKEN]; char buf[MAX_TOKEN];
@ -1030,6 +1032,10 @@ read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
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");
*dbfrozenxid = 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");

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.2 2005/07/29 19:30:04 tgl Exp $ * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.3 2005/08/11 21:11:44 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -27,6 +27,7 @@
#include "catalog/indexing.h" #include "catalog/indexing.h"
#include "catalog/namespace.h" #include "catalog/namespace.h"
#include "catalog/pg_autovacuum.h" #include "catalog/pg_autovacuum.h"
#include "catalog/pg_database.h"
#include "commands/vacuum.h" #include "commands/vacuum.h"
#include "libpq/hba.h" #include "libpq/hba.h"
#include "libpq/pqsignal.h" #include "libpq/pqsignal.h"
@ -57,6 +58,9 @@ double autovacuum_vac_scale;
int autovacuum_anl_thresh; int autovacuum_anl_thresh;
double autovacuum_anl_scale; double autovacuum_anl_scale;
int autovacuum_vac_cost_delay;
int autovacuum_vac_cost_limit;
/* Flag to tell if we are in the autovacuum daemon process */ /* Flag to tell if we are in the autovacuum daemon process */
static bool am_autovacuum = false; static bool am_autovacuum = false;
@ -64,27 +68,43 @@ static bool am_autovacuum = false;
static time_t last_autovac_start_time = 0; static time_t last_autovac_start_time = 0;
static time_t last_autovac_stop_time = 0; static time_t last_autovac_stop_time = 0;
/* Memory context for long-lived data */
static MemoryContext AutovacMemCxt;
/* struct to keep list of candidate databases for vacuum */ /* struct to keep list of candidate databases for vacuum */
typedef struct autovac_dbase typedef struct autovac_dbase
{ {
Oid oid; Oid oid;
char *name; char *name;
TransactionId frozenxid; TransactionId frozenxid;
TransactionId vacuumxid;
PgStat_StatDBEntry *entry; PgStat_StatDBEntry *entry;
int32 age; int32 age;
} autovac_dbase; } autovac_dbase;
/* struct to keep track of tables to vacuum and/or analyze */
typedef struct autovac_table
{
Oid relid;
bool dovacuum;
bool doanalyze;
int vacuum_cost_delay;
int vacuum_cost_limit;
} autovac_table;
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
static pid_t autovac_forkexec(void); static pid_t autovac_forkexec(void);
#endif #endif
NON_EXEC_STATIC void AutoVacMain(int argc, char *argv[]); NON_EXEC_STATIC void AutoVacMain(int argc, char *argv[]);
static void do_autovacuum(bool whole_db, PgStat_StatDBEntry *dbentry); static void process_whole_db(void);
static void do_autovacuum(PgStat_StatDBEntry *dbentry);
static List *autovac_get_database_list(void); static List *autovac_get_database_list(void);
static void test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry, static void test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
Form_pg_class classForm, Form_pg_autovacuum avForm, Form_pg_class classForm, Form_pg_autovacuum avForm,
List **vacuum_tables, List **analyze_tables); List **vacuum_tables);
static void autovacuum_do_vac_analyze(List *relids, bool dovacuum); static void autovacuum_do_vac_analyze(List *relids, bool dovacuum,
bool doanalyze, bool freeze);
/* /*
@ -210,6 +230,12 @@ AutoVacMain(int argc, char *argv[])
/* Lose the postmaster's on-exit routines */ /* Lose the postmaster's on-exit routines */
on_exit_reset(); on_exit_reset();
/* Identify myself via ps */
init_ps_display("autovacuum process", "", "");
set_ps_display("");
SetProcessingMode(InitProcessing);
/* /*
* Set up signal handlers. We operate on databases much like a * Set up signal handlers. We operate on databases much like a
* regular backend, so we use the same signal handling. See * regular backend, so we use the same signal handling. See
@ -233,12 +259,9 @@ AutoVacMain(int argc, char *argv[])
pqsignal(SIGUSR1, CatchupInterruptHandler); pqsignal(SIGUSR1, CatchupInterruptHandler);
/* We don't listen for async notifies */ /* We don't listen for async notifies */
pqsignal(SIGUSR2, SIG_IGN); pqsignal(SIGUSR2, SIG_IGN);
pqsignal(SIGFPE, FloatExceptionHandler);
pqsignal(SIGCHLD, SIG_DFL); pqsignal(SIGCHLD, SIG_DFL);
/* Identify myself via ps */
init_ps_display("autovacuum process", "", "");
set_ps_display("");
/* Early initialization */ /* Early initialization */
BaseInit(); BaseInit();
@ -302,6 +325,8 @@ AutoVacMain(int argc, char *argv[])
{ {
autovac_dbase *tmp = lfirst(cell); autovac_dbase *tmp = lfirst(cell);
bool this_whole_db; bool this_whole_db;
int32 freeze_age,
vacuum_age;
/* /*
* We look for the database that most urgently needs a database-wide * We look for the database that most urgently needs a database-wide
@ -309,9 +334,16 @@ AutoVacMain(int argc, char *argv[])
* transactions sooner than vacuum.c's vac_truncate_clog() would * transactions sooner than vacuum.c's vac_truncate_clog() would
* decide to start giving warnings. If any such db is found, we * decide to start giving warnings. If any such db is found, we
* ignore all other dbs. * ignore all other dbs.
*
* Unlike vacuum.c, we also look at vacuumxid. This is so that
* pg_clog can be kept trimmed to a reasonable size.
*/ */
tmp->age = (int32) (nextXid - tmp->frozenxid); freeze_age = (int32) (nextXid - tmp->frozenxid);
this_whole_db = (tmp->age > (int32) ((MaxTransactionId >> 3) * 3 - 100000)); vacuum_age = (int32) (nextXid - tmp->vacuumxid);
tmp->age = Max(freeze_age, vacuum_age);
this_whole_db = (tmp->age >
(int32) ((MaxTransactionId >> 3) * 3 - 100000));
if (whole_db || this_whole_db) if (whole_db || this_whole_db)
{ {
if (!this_whole_db) if (!this_whole_db)
@ -363,10 +395,21 @@ AutoVacMain(int argc, char *argv[])
set_ps_display(db->name); set_ps_display(db->name);
ereport(LOG, ereport(LOG,
(errmsg("autovacuum: processing database \"%s\"", db->name))); (errmsg("autovacuum: processing database \"%s\"", db->name)));
/* Create the memory context where cross-transaction state is stored */
AutovacMemCxt = AllocSetContextCreate(TopMemoryContext,
"Autovacuum context",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
/* /*
* And do an appropriate amount of work on it * And do an appropriate amount of work
*/ */
do_autovacuum(whole_db, db->entry); if (whole_db)
process_whole_db();
else
do_autovacuum(db->entry);
} }
/* One iteration done, go away */ /* One iteration done, go away */
@ -389,6 +432,7 @@ autovac_get_database_list(void)
Oid db_id; Oid db_id;
Oid db_tablespace; Oid db_tablespace;
TransactionId db_frozenxid; TransactionId db_frozenxid;
TransactionId db_vacuumxid;
filename = database_getflatfilename(); filename = database_getflatfilename();
db_file = AllocateFile(filename, "r"); db_file = AllocateFile(filename, "r");
@ -398,7 +442,8 @@ autovac_get_database_list(void)
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, &db_frozenxid)) &db_tablespace, &db_frozenxid,
&db_vacuumxid))
{ {
autovac_dbase *db; autovac_dbase *db;
@ -407,6 +452,7 @@ autovac_get_database_list(void)
db->oid = db_id; db->oid = db_id;
db->name = pstrdup(thisname); db->name = pstrdup(thisname);
db->frozenxid = db_frozenxid; db->frozenxid = db_frozenxid;
db->vacuumxid = db_vacuumxid;
/* these get set later: */ /* these get set later: */
db->entry = NULL; db->entry = NULL;
db->age = 0; db->age = 0;
@ -421,40 +467,79 @@ autovac_get_database_list(void)
} }
/* /*
* Process a database. * Process a whole database. If it's a template database or is disallowing
* connection by means of datallowconn=false, then issue a VACUUM FREEZE.
* Else use a plain VACUUM.
*/
static void
process_whole_db(void)
{
Relation dbRel;
ScanKeyData entry[1];
SysScanDesc scan;
HeapTuple tup;
Form_pg_database dbForm;
bool freeze;
/* Start a transaction so our commands have one to play into. */
StartTransactionCommand();
dbRel = heap_open(DatabaseRelationId, AccessShareLock);
/* Must use a table scan, since there's no syscache for pg_database */
ScanKeyInit(&entry[0],
ObjectIdAttributeNumber,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(MyDatabaseId));
scan = systable_beginscan(dbRel, DatabaseOidIndexId, true,
SnapshotNow, 1, entry);
tup = systable_getnext(scan);
if (!HeapTupleIsValid(tup))
elog(ERROR, "could not find tuple for database %u", MyDatabaseId);
dbForm = (Form_pg_database) GETSTRUCT(tup);
if (!dbForm->datallowconn || dbForm->datistemplate)
freeze = true;
else
freeze = false;
systable_endscan(scan);
heap_close(dbRel, AccessShareLock);
elog(DEBUG2, "autovacuum: VACUUM%s whole database",
(freeze) ? " FREEZE" : "");
autovacuum_do_vac_analyze(NIL, true, false, freeze);
/* Finally close out the last transaction. */
CommitTransactionCommand();
}
/*
* Process a database table-by-table
* *
* If whole_db is true, the database is processed as a whole, and the * dbentry must be a valid pointer to the database entry in the stats
* dbentry parameter is ignored. If it's false, dbentry must be a valid * databases' hash table, and it will be used to determine whether vacuum or
* pointer to the database entry in the stats databases' hash table, and * analyze is needed on a per-table basis.
* it will be used to determine whether vacuum or analyze is needed on a
* per-table basis.
*
* Note that test_rel_for_autovac generates two separate lists, one for
* vacuum and other for analyze. This is to facilitate processing all
* analyzes first, and then all vacuums.
* *
* Note that CHECK_FOR_INTERRUPTS is supposed to be used in certain spots in * Note that CHECK_FOR_INTERRUPTS is supposed to be used in certain spots in
* order not to ignore shutdown commands for too long. * order not to ignore shutdown commands for too long.
*/ */
static void static void
do_autovacuum(bool whole_db, PgStat_StatDBEntry *dbentry) do_autovacuum(PgStat_StatDBEntry *dbentry)
{ {
Relation classRel, Relation classRel,
avRel; avRel;
HeapTuple tuple; HeapTuple tuple;
HeapScanDesc relScan; HeapScanDesc relScan;
List *vacuum_tables = NIL, List *vacuum_tables = NIL;
*analyze_tables = NIL; ListCell *cell;
MemoryContext AutovacMemCxt; PgStat_StatDBEntry *shared;
Assert(whole_db || PointerIsValid(dbentry));
/* Memory context where cross-transaction state is stored */
AutovacMemCxt = AllocSetContextCreate(TopMemoryContext,
"Autovacuum context",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
/* Start a transaction so our commands have one to play into. */ /* Start a transaction so our commands have one to play into. */
StartTransactionCommand(); StartTransactionCommand();
@ -467,93 +552,87 @@ do_autovacuum(bool whole_db, PgStat_StatDBEntry *dbentry)
*/ */
MemoryContextSwitchTo(AutovacMemCxt); MemoryContextSwitchTo(AutovacMemCxt);
if (whole_db) /* The database hash where pgstat keeps shared relations */
shared = pgstat_fetch_stat_dbentry(InvalidOid);
classRel = heap_open(RelationRelationId, AccessShareLock);
avRel = heap_open(AutovacuumRelationId, AccessShareLock);
relScan = heap_beginscan(classRel, SnapshotNow, 0, NULL);
/* Scan pg_class looking for tables to vacuum */
while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
{ {
elog(DEBUG2, "autovacuum: VACUUM ANALYZE whole database"); Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
autovacuum_do_vac_analyze(NIL, true); Form_pg_autovacuum avForm = NULL;
} PgStat_StatTabEntry *tabentry;
else SysScanDesc avScan;
{ HeapTuple avTup;
/* the hash entry where pgstat stores shared relations */ ScanKeyData entry[1];
PgStat_StatDBEntry *shared = pgstat_fetch_stat_dbentry(InvalidOid); Oid relid;
classRel = heap_open(RelationRelationId, AccessShareLock); /* Skip non-table entries. */
avRel = heap_open(AutovacuumRelationId, AccessShareLock); /* XXX possibly allow RELKIND_TOASTVALUE entries here too? */
if (classForm->relkind != RELKIND_RELATION)
relScan = heap_beginscan(classRel, SnapshotNow, 0, NULL); continue;
/* Scan pg_class looking for tables to vacuum */
while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
{
Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
Form_pg_autovacuum avForm = NULL;
PgStat_StatTabEntry *tabentry;
SysScanDesc avScan;
HeapTuple avTup;
ScanKeyData entry[1];
Oid relid;
/* Skip non-table entries. */
/* XXX possibly allow RELKIND_TOASTVALUE entries here too? */
if (classForm->relkind != RELKIND_RELATION)
continue;
/*
* Skip temp tables (i.e. those in temp namespaces). We cannot
* safely process other backends' temp tables.
*/
if (isTempNamespace(classForm->relnamespace))
continue;
relid = HeapTupleGetOid(tuple);
/* See if we have a pg_autovacuum entry for this relation. */
ScanKeyInit(&entry[0],
Anum_pg_autovacuum_vacrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
avScan = systable_beginscan(avRel, AutovacuumRelidIndexId, true,
SnapshotNow, 1, entry);
avTup = systable_getnext(avScan);
if (HeapTupleIsValid(avTup))
avForm = (Form_pg_autovacuum) GETSTRUCT(avTup);
if (classForm->relisshared && PointerIsValid(shared))
tabentry = hash_search(shared->tables, &relid,
HASH_FIND, NULL);
else
tabentry = hash_search(dbentry->tables, &relid,
HASH_FIND, NULL);
test_rel_for_autovac(relid, tabentry, classForm, avForm,
&vacuum_tables, &analyze_tables);
systable_endscan(avScan);
}
heap_endscan(relScan);
heap_close(avRel, AccessShareLock);
heap_close(classRel, AccessShareLock);
CHECK_FOR_INTERRUPTS();
/* /*
* Perform operations on collected tables. * Skip temp tables (i.e. those in temp namespaces). We cannot
* safely process other backends' temp tables.
*/ */
if (isTempNamespace(classForm->relnamespace))
continue;
if (analyze_tables) relid = HeapTupleGetOid(tuple);
autovacuum_do_vac_analyze(analyze_tables, false);
/* See if we have a pg_autovacuum entry for this relation. */
ScanKeyInit(&entry[0],
Anum_pg_autovacuum_vacrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(relid));
avScan = systable_beginscan(avRel, AutovacuumRelidIndexId, true,
SnapshotNow, 1, entry);
avTup = systable_getnext(avScan);
if (HeapTupleIsValid(avTup))
avForm = (Form_pg_autovacuum) GETSTRUCT(avTup);
if (classForm->relisshared && PointerIsValid(shared))
tabentry = hash_search(shared->tables, &relid,
HASH_FIND, NULL);
else
tabentry = hash_search(dbentry->tables, &relid,
HASH_FIND, NULL);
test_rel_for_autovac(relid, tabentry, classForm, avForm,
&vacuum_tables);
systable_endscan(avScan);
}
heap_endscan(relScan);
heap_close(avRel, AccessShareLock);
heap_close(classRel, AccessShareLock);
/*
* Perform operations on collected tables.
*/
foreach(cell, vacuum_tables)
{
autovac_table *tab = lfirst(cell);
CHECK_FOR_INTERRUPTS(); CHECK_FOR_INTERRUPTS();
/* get back to proper context */ /* Set the vacuum cost parameters for this table */
MemoryContextSwitchTo(AutovacMemCxt); VacuumCostDelay = tab->vacuum_cost_delay;
VacuumCostLimit = tab->vacuum_cost_limit;
if (vacuum_tables) autovacuum_do_vac_analyze(list_make1_oid(tab->relid),
autovacuum_do_vac_analyze(vacuum_tables, true); tab->dovacuum,
tab->doanalyze,
false);
} }
/* Finally close out the last transaction. */ /* Finally close out the last transaction. */
@ -564,7 +643,7 @@ do_autovacuum(bool whole_db, PgStat_StatDBEntry *dbentry)
* test_rel_for_autovac * test_rel_for_autovac
* *
* Check whether a table needs to be vacuumed or analyzed. Add it to the * Check whether a table needs to be vacuumed or analyzed. Add it to the
* respective list if so. * output list if so.
* *
* A table needs to be vacuumed if the number of dead tuples exceeds a * A table needs to be vacuumed if the number of dead tuples exceeds a
* threshold. This threshold is calculated as * threshold. This threshold is calculated as
@ -591,7 +670,7 @@ static void
test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry, test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
Form_pg_class classForm, Form_pg_class classForm,
Form_pg_autovacuum avForm, Form_pg_autovacuum avForm,
List **vacuum_tables, List **analyze_tables) List **vacuum_tables)
{ {
Relation rel; Relation rel;
float4 reltuples; /* pg_class.reltuples */ float4 reltuples; /* pg_class.reltuples */
@ -606,6 +685,11 @@ test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
/* number of vacuum (resp. analyze) tuples at this time */ /* number of vacuum (resp. analyze) tuples at this time */
float4 vactuples, float4 vactuples,
anltuples; anltuples;
/* cost-based vacuum delay parameters */
int vac_cost_limit;
int vac_cost_delay;
bool dovacuum;
bool doanalyze;
/* User disabled it in pg_autovacuum? */ /* User disabled it in pg_autovacuum? */
if (avForm && !avForm->enabled) if (avForm && !avForm->enabled)
@ -636,15 +720,25 @@ test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
*/ */
if (avForm != NULL) if (avForm != NULL)
{ {
vac_scale_factor = (avForm->vac_scale_factor < 0) ? vac_scale_factor = (avForm->vac_scale_factor >= 0) ?
autovacuum_vac_scale : avForm->vac_scale_factor; avForm->vac_scale_factor : autovacuum_vac_scale;
vac_base_thresh = (avForm->vac_base_thresh < 0) ? vac_base_thresh = (avForm->vac_base_thresh >= 0) ?
autovacuum_vac_thresh : avForm->vac_base_thresh; avForm->vac_base_thresh : autovacuum_vac_thresh;
anl_scale_factor = (avForm->anl_scale_factor < 0) ? anl_scale_factor = (avForm->anl_scale_factor >= 0) ?
autovacuum_anl_scale : avForm->anl_scale_factor; avForm->anl_scale_factor : autovacuum_anl_scale;
anl_base_thresh = (avForm->anl_base_thresh < 0) ? anl_base_thresh = (avForm->anl_base_thresh >= 0) ?
autovacuum_anl_thresh : avForm->anl_base_thresh; avForm->anl_base_thresh : autovacuum_anl_thresh;
vac_cost_limit = (avForm->vac_cost_limit >= 0) ?
avForm->vac_cost_limit :
((autovacuum_vac_cost_limit >= 0) ?
autovacuum_vac_cost_limit : VacuumCostLimit);
vac_cost_delay = (avForm->vac_cost_delay >= 0) ?
avForm->vac_cost_delay :
((autovacuum_vac_cost_delay >= 0) ?
autovacuum_vac_cost_delay : VacuumCostDelay);
} }
else else
{ {
@ -653,6 +747,12 @@ test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
anl_scale_factor = autovacuum_anl_scale; anl_scale_factor = autovacuum_anl_scale;
anl_base_thresh = autovacuum_anl_thresh; anl_base_thresh = autovacuum_anl_thresh;
vac_cost_limit = (autovacuum_vac_cost_limit >= 0) ?
autovacuum_vac_cost_limit : VacuumCostLimit;
vac_cost_delay = (autovacuum_vac_cost_delay >= 0) ?
autovacuum_vac_cost_delay : VacuumCostDelay;
} }
vacthresh = (float4) vac_base_thresh + vac_scale_factor * reltuples; vacthresh = (float4) vac_base_thresh + vac_scale_factor * reltuples;
@ -668,22 +768,33 @@ test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
RelationGetRelationName(rel), RelationGetRelationName(rel),
vactuples, vacthresh, anltuples, anlthresh); vactuples, vacthresh, anltuples, anlthresh);
Assert(CurrentMemoryContext == AutovacMemCxt);
/* Determine if this table needs vacuum or analyze. */ /* Determine if this table needs vacuum or analyze. */
if (vactuples > vacthresh) dovacuum = (vactuples > vacthresh);
doanalyze = (anltuples > anlthresh);
/* ANALYZE refuses to work with pg_statistics */
if (relid == StatisticRelationId)
doanalyze = false;
if (dovacuum || doanalyze)
{ {
elog(DEBUG2, "will VACUUM ANALYZE %s", autovac_table *tab;
elog(DEBUG2, "will%s%s %s",
(dovacuum ? " VACUUM" : ""),
(doanalyze ? " ANALYZE" : ""),
RelationGetRelationName(rel)); RelationGetRelationName(rel));
*vacuum_tables = lappend_oid(*vacuum_tables, relid);
} tab = (autovac_table *) palloc(sizeof(autovac_table));
else if (anltuples > anlthresh) tab->relid = relid;
{ tab->dovacuum = dovacuum;
/* ANALYZE refuses to work with pg_statistics */ tab->doanalyze = doanalyze;
if (relid != StatisticRelationId) tab->vacuum_cost_limit = vac_cost_limit;
{ tab->vacuum_cost_delay = vac_cost_delay;
elog(DEBUG2, "will ANALYZE %s",
RelationGetRelationName(rel)); *vacuum_tables = lappend(*vacuum_tables, tab);
*analyze_tables = lappend_oid(*analyze_tables, relid);
}
} }
RelationClose(rel); RelationClose(rel);
@ -691,14 +802,22 @@ test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
/* /*
* autovacuum_do_vac_analyze * autovacuum_do_vac_analyze
* Vacuum or analyze a list of tables; or all tables if relids = NIL * Vacuum and/or analyze a list of tables; or all tables if relids = NIL
*
* We must be in AutovacMemCxt when this routine is called.
*/ */
static void static void
autovacuum_do_vac_analyze(List *relids, bool dovacuum) autovacuum_do_vac_analyze(List *relids, bool dovacuum, bool doanalyze,
bool freeze)
{ {
VacuumStmt *vacstmt = makeNode(VacuumStmt); VacuumStmt *vacstmt;
MemoryContext old_cxt;
/*
* The node must survive transaction boundaries, so make sure we create it
* in a long-lived context
*/
old_cxt = MemoryContextSwitchTo(AutovacMemCxt);
vacstmt = makeNode(VacuumStmt);
/* /*
* Point QueryContext to the autovac memory context to fake out the * Point QueryContext to the autovac memory context to fake out the
@ -710,13 +829,16 @@ autovacuum_do_vac_analyze(List *relids, bool dovacuum)
/* Set up command parameters */ /* Set up command parameters */
vacstmt->vacuum = dovacuum; vacstmt->vacuum = dovacuum;
vacstmt->full = false; vacstmt->full = false;
vacstmt->analyze = true; vacstmt->analyze = doanalyze;
vacstmt->freeze = false; vacstmt->freeze = freeze;
vacstmt->verbose = false; vacstmt->verbose = false;
vacstmt->relation = NULL; /* all tables, or not used if relids != NIL */ vacstmt->relation = NULL; /* all tables, or not used if relids != NIL */
vacstmt->va_cols = NIL; vacstmt->va_cols = NIL;
vacuum(vacstmt, relids); vacuum(vacstmt, relids);
pfree(vacstmt);
MemoryContextSwitchTo(old_cxt);
} }
/* /*

View File

@ -13,7 +13,7 @@
* *
* Copyright (c) 2001-2005, PostgreSQL Global Development Group * Copyright (c) 2001-2005, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.104 2005/08/09 21:14:55 tgl Exp $ * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.105 2005/08/11 21:11:44 tgl Exp $
* ---------- * ----------
*/ */
#include "postgres.h" #include "postgres.h"
@ -100,7 +100,7 @@
* ---------- * ----------
*/ */
bool pgstat_collect_startcollector = true; bool pgstat_collect_startcollector = true;
bool pgstat_collect_resetonpmstart = true; bool pgstat_collect_resetonpmstart = false;
bool pgstat_collect_querystring = false; bool pgstat_collect_querystring = false;
bool pgstat_collect_tuplelevel = false; bool pgstat_collect_tuplelevel = false;
bool pgstat_collect_blocklevel = false; bool pgstat_collect_blocklevel = false;
@ -237,7 +237,7 @@ pgstat_init(void)
* statistics on postmaster start, simply remove the stats file. * statistics on postmaster start, simply remove the stats file.
*/ */
if (!pgstat_collect_startcollector || pgstat_collect_resetonpmstart) if (!pgstat_collect_startcollector || pgstat_collect_resetonpmstart)
unlink(PGSTAT_STAT_FILENAME); pgstat_reset_all();
/* /*
* Nothing else required if collector will not get started * Nothing else required if collector will not get started
@ -456,6 +456,18 @@ startup_failed:
pgstat_collect_blocklevel = false; pgstat_collect_blocklevel = false;
} }
/*
* pgstat_reset_all() -
*
* Remove the stats file. This is used on server start if the
* stats_reset_on_server_start feature is enabled, or if WAL
* recovery is needed after a crash.
*/
void
pgstat_reset_all(void)
{
unlink(PGSTAT_STAT_FILENAME);
}
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
@ -677,11 +689,19 @@ pgstat_bestart(void)
if (pgStatSock < 0) if (pgStatSock < 0)
return; return;
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_BESTART); /*
msg.m_databaseid = MyDatabaseId; * We may not have a MyProcPort (eg, if this is the autovacuum process).
msg.m_userid = GetSessionUserId(); * For the moment, punt and don't send BESTART --- would be better to
memcpy(&msg.m_clientaddr, &MyProcPort->raddr, sizeof(msg.m_clientaddr)); * work out a clean way of handling "unknown clientaddr".
pgstat_send(&msg, sizeof(msg)); */
if (MyProcPort)
{
pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_BESTART);
msg.m_databaseid = MyDatabaseId;
msg.m_userid = GetSessionUserId();
memcpy(&msg.m_clientaddr, &MyProcPort->raddr, sizeof(msg.m_clientaddr));
pgstat_send(&msg, sizeof(msg));
}
/* /*
* Set up a process-exit hook to ensure we flush the last batch of * Set up a process-exit hook to ensure we flush the last batch of

View File

@ -37,7 +37,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.461 2005/07/29 19:30:04 tgl Exp $ * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.462 2005/08/11 21:11:44 tgl Exp $
* *
* NOTES * NOTES
* *
@ -342,6 +342,7 @@ typedef struct
int syslogPipe[2]; int syslogPipe[2];
#endif #endif
char my_exec_path[MAXPGPATH]; char my_exec_path[MAXPGPATH];
char pkglib_path[MAXPGPATH];
char ExtraOptions[MAXPGPATH]; char ExtraOptions[MAXPGPATH];
char lc_collate[LOCALE_NAME_BUFLEN]; char lc_collate[LOCALE_NAME_BUFLEN];
char lc_ctype[LOCALE_NAME_BUFLEN]; char lc_ctype[LOCALE_NAME_BUFLEN];
@ -3702,6 +3703,8 @@ save_backend_variables(BackendParameters *param, Port *port,
StrNCpy(param->my_exec_path, my_exec_path, MAXPGPATH); StrNCpy(param->my_exec_path, my_exec_path, MAXPGPATH);
StrNCpy(param->pkglib_path, pkglib_path, MAXPGPATH);
StrNCpy(param->ExtraOptions, ExtraOptions, MAXPGPATH); StrNCpy(param->ExtraOptions, ExtraOptions, MAXPGPATH);
StrNCpy(param->lc_collate, setlocale(LC_COLLATE, NULL), LOCALE_NAME_BUFLEN); StrNCpy(param->lc_collate, setlocale(LC_COLLATE, NULL), LOCALE_NAME_BUFLEN);
@ -3903,6 +3906,8 @@ restore_backend_variables(BackendParameters *param, Port *port)
StrNCpy(my_exec_path, param->my_exec_path, MAXPGPATH); StrNCpy(my_exec_path, param->my_exec_path, MAXPGPATH);
StrNCpy(pkglib_path, param->pkglib_path, MAXPGPATH);
StrNCpy(ExtraOptions, param->ExtraOptions, MAXPGPATH); StrNCpy(ExtraOptions, param->ExtraOptions, MAXPGPATH);
setlocale(LC_COLLATE, param->lc_collate); setlocale(LC_COLLATE, param->lc_collate);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.456 2005/08/08 03:12:12 tgl Exp $ * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.457 2005/08/11 21:11:45 tgl Exp $
* *
* NOTES * NOTES
* this is the "main" module of the postgres backend and * this is the "main" module of the postgres backend and
@ -162,7 +162,6 @@ static List *pg_rewrite_queries(List *querytree_list);
static void start_xact_command(void); static void start_xact_command(void);
static void finish_xact_command(void); static void finish_xact_command(void);
static void SigHupHandler(SIGNAL_ARGS); static void SigHupHandler(SIGNAL_ARGS);
static void FloatExceptionHandler(SIGNAL_ARGS);
static void log_disconnections(int code, Datum arg); static void log_disconnections(int code, Datum arg);
@ -2151,7 +2150,7 @@ StatementCancelHandler(SIGNAL_ARGS)
} }
/* signal handler for floating point exception */ /* signal handler for floating point exception */
static void void
FloatExceptionHandler(SIGNAL_ARGS) FloatExceptionHandler(SIGNAL_ARGS)
{ {
ereport(ERROR, ereport(ERROR,

View File

@ -23,7 +23,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, 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.13 2005/07/28 22:27:02 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.14 2005/08/11 21:11:46 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -208,12 +208,14 @@ write_database_file(Relation drel)
char *datname; char *datname;
Oid datoid; Oid datoid;
Oid dattablespace; Oid dattablespace;
TransactionId datfrozenxid; TransactionId datfrozenxid,
datvacuumxid;
datname = NameStr(dbform->datname); datname = NameStr(dbform->datname);
datoid = HeapTupleGetOid(tuple); datoid = HeapTupleGetOid(tuple);
dattablespace = dbform->dattablespace; dattablespace = dbform->dattablespace;
datfrozenxid = dbform->datfrozenxid; datfrozenxid = dbform->datfrozenxid;
datvacuumxid = dbform->datvacuumxid;
/* /*
* Identify the oldest datfrozenxid, ignoring databases that are not * Identify the oldest datfrozenxid, ignoring databases that are not
@ -242,13 +244,14 @@ write_database_file(Relation drel)
} }
/* /*
* The file format is: "dbname" oid tablespace frozenxid * The file format is: "dbname" oid tablespace frozenxid vacuumxid
* *
* The xid is not needed for backend startup, but may be of use * The xids are not needed for backend startup, but are of use to
* 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\n", datoid, dattablespace, datfrozenxid); fprintf(fp, " %u %u %u %u\n",
datoid, dattablespace, datfrozenxid, datvacuumxid);
} }
heap_endscan(scan); heap_endscan(scan);
@ -654,8 +657,10 @@ write_auth_file(Relation rel_authid, Relation rel_authmem)
* base backup which may be far out of sync with the current state. * base backup which may be far out of sync with the current state.
* *
* In theory we could skip rebuilding the flat files if no WAL replay * In theory we could skip rebuilding the flat files if no WAL replay
* occurred, but it seems safest to just do it always. We have to * occurred, but it seems best to just do it always. We have to
* scan pg_database to compute the XID wrap limit anyway. * scan pg_database to compute the XID wrap limit anyway. Also, this
* policy means we need not force initdb to change the format of the
* flat files.
* *
* In a standalone backend we pass database_only = true to skip processing * In a standalone backend we pass database_only = true to skip processing
* the auth file. We won't need it, and building it could fail if there's * the auth file. We won't need it, and building it could fail if there's

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.156 2005/08/08 03:12:14 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.157 2005/08/11 21:11:46 tgl Exp $
* *
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
@ -20,8 +20,10 @@
#include <math.h> #include <math.h>
#include <unistd.h> #include <unistd.h>
#include "access/genam.h"
#include "access/heapam.h" #include "access/heapam.h"
#include "catalog/catalog.h" #include "catalog/catalog.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h" #include "catalog/namespace.h"
#include "catalog/pg_authid.h" #include "catalog/pg_authid.h"
#include "catalog/pg_database.h" #include "catalog/pg_database.h"
@ -79,7 +81,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 frozenxid; TransactionId dummyxid;
filename = database_getflatfilename(); filename = database_getflatfilename();
db_file = AllocateFile(filename, "r"); db_file = AllocateFile(filename, "r");
@ -89,7 +91,8 @@ 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, &frozenxid)) db_tablespace, &dummyxid,
&dummyxid))
{ {
if (strcmp(thisname, name) == 0) if (strcmp(thisname, name) == 0)
{ {
@ -131,7 +134,7 @@ static void
ReverifyMyDatabase(const char *name) ReverifyMyDatabase(const char *name)
{ {
Relation pgdbrel; Relation pgdbrel;
HeapScanDesc pgdbscan; SysScanDesc pgdbscan;
ScanKeyData key; ScanKeyData key;
HeapTuple tup; HeapTuple tup;
Form_pg_database dbform; Form_pg_database dbform;
@ -147,9 +150,10 @@ ReverifyMyDatabase(const char *name)
BTEqualStrategyNumber, F_NAMEEQ, BTEqualStrategyNumber, F_NAMEEQ,
NameGetDatum(name)); NameGetDatum(name));
pgdbscan = heap_beginscan(pgdbrel, SnapshotNow, 1, &key); pgdbscan = systable_beginscan(pgdbrel, DatabaseNameIndexId, true,
SnapshotNow, 1, &key);
tup = heap_getnext(pgdbscan, ForwardScanDirection); tup = systable_getnext(pgdbscan);
if (!HeapTupleIsValid(tup) || if (!HeapTupleIsValid(tup) ||
HeapTupleGetOid(tup) != MyDatabaseId) HeapTupleGetOid(tup) != MyDatabaseId)
{ {
@ -238,7 +242,7 @@ ReverifyMyDatabase(const char *name)
} }
} }
heap_endscan(pgdbscan); systable_endscan(pgdbscan);
heap_close(pgdbrel, RowShareLock); heap_close(pgdbrel, RowShareLock);
} }
@ -428,6 +432,18 @@ InitPostgres(const char *dbname, const char *username)
/* Initialize portal manager */ /* Initialize portal manager */
EnablePortalManager(); EnablePortalManager();
/*
* Set up process-exit callback to do pre-shutdown cleanup. This
* has to be after we've initialized all the low-level modules
* like the buffer manager, because during shutdown this has to
* run before the low-level modules start to close down. On the
* other hand, we want it in place before we begin our first
* transaction --- if we fail during the initialization transaction,
* as is entirely possible, we need the AbortTransaction call to
* clean up.
*/
on_shmem_exit(ShutdownPostgres, 0);
/* start a new transaction here before access to db */ /* start a new transaction here before access to db */
if (!bootstrap) if (!bootstrap)
StartTransactionCommand(); StartTransactionCommand();
@ -465,7 +481,8 @@ InitPostgres(const char *dbname, const char *username)
/* /*
* Unless we are bootstrapping, double-check that InitMyDatabaseInfo() * Unless we are bootstrapping, double-check that InitMyDatabaseInfo()
* got a correct result. We can't do this until all the * got a correct result. We can't do this until all the
* database-access infrastructure is up. * database-access infrastructure is up. (Also, it wants to know if
* the user is a superuser, so the above stuff has to happen first.)
*/ */
if (!bootstrap) if (!bootstrap)
ReverifyMyDatabase(dbname); ReverifyMyDatabase(dbname);
@ -509,24 +526,10 @@ InitPostgres(const char *dbname, const char *username)
/* initialize client encoding */ /* initialize client encoding */
InitializeClientEncoding(); InitializeClientEncoding();
/* /* initialize statistics collection for this backend */
* Initialize statistics collection for this backend. We do this
* here because the shutdown hook it sets up needs to be invoked
* at the corresponding phase of backend shutdown: after
* ShutdownPostgres and before we drop access to shared memory.
*/
if (IsUnderPostmaster) if (IsUnderPostmaster)
pgstat_bestart(); pgstat_bestart();
/*
* Set up process-exit callback to do pre-shutdown cleanup. This
* should be last because we want shmem_exit to call this routine
* before the exit callbacks that are registered by buffer manager,
* lock manager, etc. We need to run this code before we close down
* database access!
*/
on_shmem_exit(ShutdownPostgres, 0);
/* close the transaction we started above */ /* close the transaction we started above */
if (!bootstrap) if (!bootstrap)
CommitTransactionCommand(); CommitTransactionCommand();
@ -538,9 +541,7 @@ InitPostgres(const char *dbname, const char *username)
/* /*
* Backend-shutdown callback. Do cleanup that we want to be sure happens * Backend-shutdown callback. Do cleanup that we want to be sure happens
* before all the supporting modules begin to nail their doors shut via * before all the supporting modules begin to nail their doors shut via
* their own callbacks. Note that because this has to be registered very * their own callbacks.
* late in startup, it will not get called if we suffer a failure *during*
* startup.
* *
* User-level cleanup, such as temp-relation removal and UNLISTEN, happens * User-level cleanup, such as temp-relation removal and UNLISTEN, happens
* via separate callbacks that execute before this one. We don't combine the * via separate callbacks that execute before this one. We don't combine the

View File

@ -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.280 2005/07/30 15:17:20 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.281 2005/08/11 21:11:47 tgl Exp $
* *
*-------------------------------------------------------------------- *--------------------------------------------------------------------
*/ */
@ -672,7 +672,7 @@ static struct config_bool ConfigureNamesBool[] =
NULL NULL
}, },
&pgstat_collect_resetonpmstart, &pgstat_collect_resetonpmstart,
true, NULL, NULL false, NULL, NULL
}, },
{ {
{"stats_command_string", PGC_SUSET, STATS_COLLECTOR, {"stats_command_string", PGC_SUSET, STATS_COLLECTOR,
@ -1160,6 +1160,24 @@ static struct config_int ConfigureNamesInt[] =
0, 0, 1000, NULL, NULL 0, 0, 1000, NULL, NULL
}, },
{
{"autovacuum_vacuum_cost_delay", PGC_SIGHUP, AUTOVACUUM,
gettext_noop("Vacuum cost delay in milliseconds, for autovacuum."),
NULL
},
&autovacuum_vac_cost_delay,
-1, -1, 1000, NULL, NULL
},
{
{"autovacuum_vacuum_cost_limit", PGC_SIGHUP, AUTOVACUUM,
gettext_noop("Vacuum cost amount available before napping, for autovacuum."),
NULL
},
&autovacuum_vac_cost_limit,
-1, -1, 10000, NULL, NULL
},
{ {
{"max_files_per_process", PGC_POSTMASTER, RESOURCES_KERNEL, {"max_files_per_process", PGC_POSTMASTER, RESOURCES_KERNEL,
gettext_noop("Sets the maximum number of simultaneously open files for each server process."), gettext_noop("Sets the maximum number of simultaneously open files for each server process."),

View File

@ -288,7 +288,7 @@
#stats_command_string = off #stats_command_string = off
#stats_block_level = off #stats_block_level = off
#stats_row_level = off #stats_row_level = off
#stats_reset_on_server_start = on #stats_reset_on_server_start = off
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
@ -301,6 +301,10 @@
#autovacuum_analyze_threshold = 500 # min # of tuple updates before analyze #autovacuum_analyze_threshold = 500 # min # of tuple updates before analyze
#autovacuum_vacuum_scale_factor = 0.4 # fraction of rel size before vacuum #autovacuum_vacuum_scale_factor = 0.4 # fraction of rel size before vacuum
#autovacuum_analyze_scale_factor = 0.2 # fraction of rel size before analyze #autovacuum_analyze_scale_factor = 0.2 # fraction of rel size before analyze
#autovacuum_vacuum_cost_delay = -1 # default vacuum cost delay for autovac
# -1 means use vacuum_cost_delay
#autovacuum_vacuum_cost_limit = -1 # default vacuum cost limit for autovac
# -1 means use vacuum_cost_limit
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, 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.295 2005/08/01 20:31:14 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.296 2005/08/11 21:11:47 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200508011 #define CATALOG_VERSION_NO 200508111
#endif #endif

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, 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.1 2005/07/14 05:13:42 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_autovacuum.h,v 1.2 2005/08/11 21:11:47 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -34,6 +34,8 @@ CATALOG(pg_autovacuum,1248) BKI_WITHOUT_OIDS
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_limit; /* vacuum cost limit */
} FormData_pg_autovacuum; } FormData_pg_autovacuum;
/* ---------------- /* ----------------
@ -47,13 +49,15 @@ typedef FormData_pg_autovacuum *Form_pg_autovacuum;
* compiler constants for pg_autovacuum * compiler constants for pg_autovacuum
* ---------------- * ----------------
*/ */
#define Natts_pg_autovacuum 6 #define Natts_pg_autovacuum 8
#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
#define Anum_pg_autovacuum_vac_scale_factor 4 #define Anum_pg_autovacuum_vac_scale_factor 4
#define Anum_pg_autovacuum_anl_base_thresh 5 #define Anum_pg_autovacuum_anl_base_thresh 5
#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_limit 8
/* There are no preloaded tuples in pg_autovacuum.h */ /* There are no preloaded tuples in pg_autovacuum.h */

View File

@ -4,7 +4,7 @@
* Interface to hba.c * Interface to hba.c
* *
* *
* $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.39 2005/07/29 19:30:08 tgl Exp $ * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.40 2005/08/11 21:11:48 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -37,6 +37,7 @@ 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 *dbfrozenxid); Oid *dbtablespace, TransactionId *dbfrozenxid,
TransactionId *dbvacuumxid);
#endif /* HBA_H */ #endif /* HBA_H */

View File

@ -5,7 +5,7 @@
* *
* Copyright (c) 2001-2005, PostgreSQL Global Development Group * Copyright (c) 2001-2005, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/include/pgstat.h,v 1.34 2005/07/29 19:30:09 tgl Exp $ * $PostgreSQL: pgsql/src/include/pgstat.h,v 1.35 2005/08/11 21:11:49 tgl Exp $
* ---------- * ----------
*/ */
#ifndef PGSTAT_H #ifndef PGSTAT_H
@ -367,6 +367,7 @@ extern bool pgstat_collect_blocklevel;
extern void pgstat_init(void); extern void pgstat_init(void);
extern int pgstat_start(void); extern int pgstat_start(void);
extern void pgstat_beterm(int pid); extern void pgstat_beterm(int pid);
extern void pgstat_reset_all(void);
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
extern void PgstatBufferMain(int argc, char *argv[]); extern void PgstatBufferMain(int argc, char *argv[]);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, 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.1 2005/07/14 05:13:43 tgl Exp $ * $PostgreSQL: pgsql/src/include/postmaster/autovacuum.h,v 1.2 2005/08/11 21:11:50 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -21,6 +21,8 @@ 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_vac_cost_delay;
extern int autovacuum_vac_cost_limit;
/* Status inquiry functions */ /* Status inquiry functions */
extern bool AutoVacuumingActive(void); extern bool AutoVacuumingActive(void);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, 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/tcop/tcopprot.h,v 1.76 2005/07/14 05:13:44 tgl Exp $ * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.77 2005/08/11 21:11:50 tgl Exp $
* *
* OLD COMMENTS * OLD COMMENTS
* This file was created so that other c files could get the two * This file was created so that other c files could get the two
@ -59,6 +59,7 @@ extern void die(SIGNAL_ARGS);
extern void quickdie(SIGNAL_ARGS); extern void quickdie(SIGNAL_ARGS);
extern void authdie(SIGNAL_ARGS); extern void authdie(SIGNAL_ARGS);
extern void StatementCancelHandler(SIGNAL_ARGS); extern void StatementCancelHandler(SIGNAL_ARGS);
extern void FloatExceptionHandler(SIGNAL_ARGS);
extern void prepare_for_client_read(void); extern void prepare_for_client_read(void);
extern void client_read_ended(void); extern void client_read_ended(void);
extern int PostgresMain(int argc, char *argv[], const char *username); extern int PostgresMain(int argc, char *argv[], const char *username);