Index: doc/src/sgml/catalogs.sgml
===================================================================
RCS file: /home/alvherre/cvs/pgsql/doc/src/sgml/catalogs.sgml,v
retrieving revision 2.110
diff -c -r2.110 catalogs.sgml
*** doc/src/sgml/catalogs.sgml 31 Jul 2005 17:19:16 -0000 2.110
--- doc/src/sgml/catalogs.sgml 7 Aug 2005 19:03:22 -0000
***************
*** 1197,1202 ****
--- 1197,1216 ----
Multiplier for reltuples to add to
anl_base_thresh>
+
+
+ vac_cost_delay
+ integer
+
+ Custom vacuum_cost_delay> parameter
+
+
+
+ vac_cost_limit
+ integer
+
+ Custom vacuum_cost_limit> parameter
+
***************
*** 1217,1223 ****
Any of the numerical fields can contain -1> (or indeed
any negative value) to indicate that the system-wide default should
! be used for this particular value.
--- 1231,1241 ----
Any of the numerical fields can contain -1> (or indeed
any negative value) to indicate that the system-wide default should
! be used for this particular value. Observe that the
! vac_cost_delay> variable inherits its default value from the
! autovacuum_vacuum_cost_delay> configuration parameter,
! or from vacuum_cost_delay> if the former is set to a negative
! value. The same applies to vac_cost_limit>.
Index: doc/src/sgml/runtime.sgml
===================================================================
RCS file: /home/alvherre/cvs/pgsql/doc/src/sgml/runtime.sgml,v
retrieving revision 1.341
diff -c -r1.341 runtime.sgml
*** doc/src/sgml/runtime.sgml 30 Jul 2005 17:15:35 -0000 1.341
--- doc/src/sgml/runtime.sgml 31 Jul 2005 23:22:11 -0000
***************
*** 3399,3404 ****
--- 3399,3436 ----
+
+ autovacuum_vacuum_cost_delay (integer)
+
+ autovacuum_vacuum_cost_delay> configuration parameter
+
+
+
+ Specifies the default value that will be applied to each
+ VACUUM> operation, for tables that do not have
+ a default value set in pg_autovacuum>. If a
+ negative value is specified (like the default value of -1),
+ the vacuum_cost_delay> value will be applied instead.
+
+
+
+
+
+ autovacuum_vacuum_cost_limit (integer)
+
+ autovacuum_vacuum_cost_limit> configuration parameter
+
+
+
+ Specifies the default value that will be applied to each
+ VACUUM> operation, for tables that do not have
+ a default value set in pg_autovacuum>. If a
+ negative value is specified (like the default value of -1),
+ the vacuum_cost_limit> value will be applied instead.
+
+
+
+
Index: src/backend/access/transam/xlog.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/access/transam/xlog.c,v
retrieving revision 1.214
diff -c -r1.214 xlog.c
*** src/backend/access/transam/xlog.c 30 Jul 2005 14:15:44 -0000 1.214
--- src/backend/access/transam/xlog.c 31 Jul 2005 21:36:45 -0000
***************
*** 33,38 ****
--- 33,39 ----
#include "catalog/catversion.h"
#include "catalog/pg_control.h"
#include "miscadmin.h"
+ #include "pgstat.h"
#include "postmaster/bgwriter.h"
#include "storage/bufpage.h"
#include "storage/fd.h"
***************
*** 48,54 ****
/*
! * Becauase O_DIRECT bypasses the kernel buffers, and because we never
* 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
* with fsync(), but because skipping the kernel buffer forces writes out
--- 49,55 ----
/*
! * Because O_DIRECT bypasses the kernel buffers, and because we never
* 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
* with fsync(), but because skipping the kernel buffer forces writes out
***************
*** 4544,4549 ****
--- 4545,4555 ----
} while (record != NULL && recoveryContinue);
/*
+ * Reset pgstat data, because it may be invalid after recovery.
+ */
+ pgstat_reset_all();
+
+ /*
* end of main redo apply loop
*/
Index: src/backend/libpq/hba.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/libpq/hba.c,v
retrieving revision 1.146
diff -c -r1.146 hba.c
*** src/backend/libpq/hba.c 29 Jul 2005 19:30:04 -0000 1.146
--- src/backend/libpq/hba.c 10 Aug 2005 02:48:20 -0000
***************
*** 1001,1013 ****
* dboid: gets database OID
* dbtablespace: gets database's default tablespace's OID
* dbfrozenxid: gets database's frozen XID
*
* This is not much related to the other functions in hba.c, but we put it
* here because it uses the next_token() infrastructure.
*/
bool
read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
! Oid *dbtablespace, TransactionId *dbfrozenxid)
{
char buf[MAX_TOKEN];
--- 1001,1015 ----
* dboid: gets database OID
* dbtablespace: gets database's default tablespace's OID
* 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
* here because it uses the next_token() infrastructure.
*/
bool
read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
! Oid *dbtablespace, TransactionId *dbfrozenxid,
! TransactionId *dbvacuumxid)
{
char buf[MAX_TOKEN];
***************
*** 1030,1035 ****
--- 1032,1041 ----
if (!isdigit((unsigned char) buf[0]))
elog(FATAL, "bad data in flat pg_database file");
*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 */
if (next_token(fp, buf, sizeof(buf)))
elog(FATAL, "bad data in flat pg_database file");
Index: src/backend/postmaster/autovacuum.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/postmaster/autovacuum.c,v
retrieving revision 1.2
diff -c -r1.2 autovacuum.c
*** src/backend/postmaster/autovacuum.c 29 Jul 2005 19:30:04 -0000 1.2
--- src/backend/postmaster/autovacuum.c 10 Aug 2005 02:46:52 -0000
***************
*** 27,32 ****
--- 27,33 ----
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_autovacuum.h"
+ #include "catalog/pg_database.h"
#include "commands/vacuum.h"
#include "libpq/hba.h"
#include "libpq/pqsignal.h"
***************
*** 57,62 ****
--- 58,66 ----
int autovacuum_anl_thresh;
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 */
static bool am_autovacuum = false;
***************
*** 64,91 ****
static time_t last_autovac_start_time = 0;
static time_t last_autovac_stop_time = 0;
/* struct to keep list of candidate databases for vacuum */
typedef struct autovac_dbase
{
Oid oid;
char *name;
TransactionId frozenxid;
PgStat_StatDBEntry *entry;
int32 age;
} autovac_dbase;
#ifdef EXEC_BACKEND
static pid_t autovac_forkexec(void);
#endif
NON_EXEC_STATIC void AutoVacMain(int argc, char *argv[]);
! static void do_autovacuum(bool whole_db, PgStat_StatDBEntry *dbentry);
static List *autovac_get_database_list(void);
static void test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
Form_pg_class classForm, Form_pg_autovacuum avForm,
List **vacuum_tables, List **analyze_tables);
! static void autovacuum_do_vac_analyze(List *relids, bool dovacuum);
!
/*
* Main entry point for autovacuum controller process.
--- 68,108 ----
static time_t last_autovac_start_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 */
typedef struct autovac_dbase
{
Oid oid;
char *name;
TransactionId frozenxid;
+ TransactionId vacuumxid;
PgStat_StatDBEntry *entry;
int32 age;
} autovac_dbase;
+ /* struct to keep track of tables to vacuum */
+ typedef struct autovac_table
+ {
+ Oid relid;
+ int vacuum_cost_delay;
+ int vacuum_cost_limit;
+ } autovac_table;
+
#ifdef EXEC_BACKEND
static pid_t autovac_forkexec(void);
#endif
NON_EXEC_STATIC void AutoVacMain(int argc, char *argv[]);
! static void process_whole_db(void);
! static void do_autovacuum(PgStat_StatDBEntry *dbentry);
static List *autovac_get_database_list(void);
static void test_rel_for_autovac(Oid relid, PgStat_StatTabEntry *tabentry,
Form_pg_class classForm, Form_pg_autovacuum avForm,
List **vacuum_tables, List **analyze_tables);
! static void autovacuum_do_vac_analyze(List *relids, bool doanalyze,
! bool dovacuum, bool freeze);
/*
* Main entry point for autovacuum controller process.
***************
*** 302,307 ****
--- 319,326 ----
{
autovac_dbase *tmp = lfirst(cell);
bool this_whole_db;
+ int32 freeze_age,
+ vacuum_age;
/*
* We look for the database that most urgently needs a database-wide
***************
*** 310,317 ****
* decide to start giving warnings. If any such db is found, we
* ignore all other dbs.
*/
! tmp->age = (int32) (nextXid - tmp->frozenxid);
! this_whole_db = (tmp->age > (int32) ((MaxTransactionId >> 3) * 3 - 100000));
if (whole_db || this_whole_db)
{
if (!this_whole_db)
--- 329,340 ----
* decide to start giving warnings. If any such db is found, we
* ignore all other dbs.
*/
! freeze_age = (int32) (nextXid - tmp->frozenxid);
! 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 (!this_whole_db)
***************
*** 363,372 ****
set_ps_display(db->name);
ereport(LOG,
(errmsg("autovacuum: processing database \"%s\"", db->name)));
/*
! * And do an appropriate amount of work on it
*/
! do_autovacuum(whole_db, db->entry);
}
/* One iteration done, go away */
--- 386,406 ----
set_ps_display(db->name);
ereport(LOG,
(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
*/
! if (whole_db)
! process_whole_db();
! else
! do_autovacuum(db->entry);
}
/* One iteration done, go away */
***************
*** 389,394 ****
--- 423,429 ----
Oid db_id;
Oid db_tablespace;
TransactionId db_frozenxid;
+ TransactionId db_vacuumxid;
filename = database_getflatfilename();
db_file = AllocateFile(filename, "r");
***************
*** 398,404 ****
errmsg("could not open file \"%s\": %m", filename)));
while (read_pg_database_line(db_file, thisname, &db_id,
! &db_tablespace, &db_frozenxid))
{
autovac_dbase *db;
--- 433,440 ----
errmsg("could not open file \"%s\": %m", filename)));
while (read_pg_database_line(db_file, thisname, &db_id,
! &db_tablespace, &db_frozenxid,
! &db_vacuumxid))
{
autovac_dbase *db;
***************
*** 407,412 ****
--- 443,449 ----
db->oid = db_id;
db->name = pstrdup(thisname);
db->frozenxid = db_frozenxid;
+ db->vacuumxid = db_vacuumxid;
/* these get set later: */
db->entry = NULL;
db->age = 0;
***************
*** 421,433 ****
}
/*
! * Process a database.
*
! * If whole_db is true, the database is processed as a whole, and the
! * dbentry parameter is ignored. If it's false, dbentry must be a valid
! * pointer to the database entry in the stats databases' hash table, and
! * 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
--- 458,520 ----
}
/*
! * 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];
! HeapScanDesc 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 heap scan, since there's no syscache for pg_database */
! ScanKeyInit(&entry[0],
! ObjectIdAttributeNumber,
! BTEqualStrategyNumber, F_OIDEQ,
! ObjectIdGetDatum(MyDatabaseId));
!
! scan = heap_beginscan(dbRel, SnapshotNow, 1, entry);
!
! tup = heap_getnext(scan, ForwardScanDirection);
!
! 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;
!
! heap_endscan(scan);
! heap_close(dbRel, AccessShareLock);
!
! elog(DEBUG2, "autovacuum: VACUUM%s whole database",
! (freeze) ? " FREEZE" : "");
!
! autovacuum_do_vac_analyze(NIL, false, true, freeze);
!
! /* Finally close out the last transaction. */
! CommitTransactionCommand();
! }
!
! /*
! * Process a database table per table
*
! * dbentry must be a valid pointer to the database entry in the stats
! * databases' hash table, and 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
***************
*** 437,443 ****
* order not to ignore shutdown commands for too long.
*/
static void
! do_autovacuum(bool whole_db, PgStat_StatDBEntry *dbentry)
{
Relation classRel,
avRel;
--- 524,530 ----
* order not to ignore shutdown commands for too long.
*/
static void
! do_autovacuum(PgStat_StatDBEntry *dbentry)
{
Relation classRel,
avRel;
***************
*** 445,460 ****
HeapScanDesc relScan;
List *vacuum_tables = NIL,
*analyze_tables = NIL;
! MemoryContext AutovacMemCxt;
!
! 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. */
StartTransactionCommand();
--- 532,538 ----
HeapScanDesc relScan;
List *vacuum_tables = NIL,
*analyze_tables = NIL;
! PgStat_StatDBEntry *shared;
/* Start a transaction so our commands have one to play into. */
StartTransactionCommand();
***************
*** 467,559 ****
*/
MemoryContextSwitchTo(AutovacMemCxt);
! if (whole_db)
! {
! elog(DEBUG2, "autovacuum: VACUUM ANALYZE whole database");
! autovacuum_do_vac_analyze(NIL, true);
! }
! else
! {
! /* the hash entry where pgstat stores shared relations */
! PgStat_StatDBEntry *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)
! {
! 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.
! */
- if (analyze_tables)
- autovacuum_do_vac_analyze(analyze_tables, false);
! CHECK_FOR_INTERRUPTS();
! /* get back to proper context */
! MemoryContextSwitchTo(AutovacMemCxt);
! if (vacuum_tables)
! autovacuum_do_vac_analyze(vacuum_tables, true);
}
/* Finally close out the last transaction. */
--- 545,641 ----
*/
MemoryContextSwitchTo(AutovacMemCxt);
! /* 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)
! {
! 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.
! */
!
! if (analyze_tables)
! autovacuum_do_vac_analyze(analyze_tables, true, false, false);
!
! CHECK_FOR_INTERRUPTS();
!
! if (vacuum_tables)
! {
! ListCell *cell;
! foreach(cell, vacuum_tables)
! {
! autovac_table *tab = lfirst(cell);
! /* Set the cost vacuum parameters for this table */
! VacuumCostDelay = tab->vacuum_cost_delay;
! VacuumCostLimit = tab->vacuum_cost_limit;
! autovacuum_do_vac_analyze(list_make1_oid(tab->relid), true,
! true, true);
! }
}
/* Finally close out the last transaction. */
***************
*** 606,611 ****
--- 688,696 ----
/* number of vacuum (resp. analyze) tuples at this time */
float4 vactuples,
anltuples;
+ /* cost-based vacuum delay parameters */
+ int vac_cost_limit;
+ int vac_cost_delay;
/* User disabled it in pg_autovacuum? */
if (avForm && !avForm->enabled)
***************
*** 645,650 ****
--- 730,743 ----
autovacuum_anl_scale : avForm->anl_scale_factor;
anl_base_thresh = (avForm->anl_base_thresh < 0) ?
autovacuum_anl_thresh : avForm->anl_base_thresh;
+
+ vac_cost_limit = (avForm->vac_cost_limit < 0) ?
+ (autovacuum_vac_cost_limit < 0) ? VacuumCostLimit :
+ autovacuum_vac_cost_limit : avForm->vac_cost_limit;
+
+ vac_cost_delay = (avForm->vac_cost_delay < 0) ?
+ (autovacuum_vac_cost_delay < 0) ? VacuumCostDelay :
+ autovacuum_vac_cost_delay : avForm->vac_cost_delay;
}
else
{
***************
*** 653,658 ****
--- 746,757 ----
anl_scale_factor = autovacuum_anl_scale;
anl_base_thresh = autovacuum_anl_thresh;
+
+ vac_cost_limit = (autovacuum_vac_cost_limit < 0) ?
+ VacuumCostLimit : autovacuum_vac_cost_limit;
+
+ vac_cost_delay = (autovacuum_vac_cost_delay < 0) ?
+ VacuumCostDelay : autovacuum_vac_cost_delay;
}
vacthresh = (float4) vac_base_thresh + vac_scale_factor * reltuples;
***************
*** 668,679 ****
RelationGetRelationName(rel),
vactuples, vacthresh, anltuples, anlthresh);
/* Determine if this table needs vacuum or analyze. */
if (vactuples > vacthresh)
{
elog(DEBUG2, "will VACUUM ANALYZE %s",
RelationGetRelationName(rel));
! *vacuum_tables = lappend_oid(*vacuum_tables, relid);
}
else if (anltuples > anlthresh)
{
--- 767,788 ----
RelationGetRelationName(rel),
vactuples, vacthresh, anltuples, anlthresh);
+ Assert(CurrentMemoryContext == AutovacMemCxt);
+
/* Determine if this table needs vacuum or analyze. */
if (vactuples > vacthresh)
{
+ autovac_table *tab = (autovac_table *)
+ palloc(sizeof(autovac_table));
+
elog(DEBUG2, "will VACUUM ANALYZE %s",
RelationGetRelationName(rel));
!
! tab->relid = relid;
! tab->vacuum_cost_limit = vac_cost_limit;
! tab->vacuum_cost_delay = vac_cost_delay;
!
! *vacuum_tables = lappend(*vacuum_tables, tab);
}
else if (anltuples > anlthresh)
{
***************
*** 691,704 ****
/*
* autovacuum_do_vac_analyze
! * Vacuum or analyze a list of tables; or all tables if relids = NIL
! *
! * We must be in AutovacMemCxt when this routine is called.
*/
static void
! autovacuum_do_vac_analyze(List *relids, bool dovacuum)
{
! VacuumStmt *vacstmt = makeNode(VacuumStmt);
/*
* Point QueryContext to the autovac memory context to fake out the
--- 800,821 ----
/*
* autovacuum_do_vac_analyze
! * Vacuum and/or analyze a list of tables; or all tables if relids = NIL
*/
static void
! autovacuum_do_vac_analyze(List *relids, bool doanalyze, bool dovacuum,
! bool freeze)
{
! 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
***************
*** 710,722 ****
/* Set up command parameters */
vacstmt->vacuum = dovacuum;
vacstmt->full = false;
! vacstmt->analyze = true;
! vacstmt->freeze = false;
vacstmt->verbose = false;
vacstmt->relation = NULL; /* all tables, or not used if relids != NIL */
vacstmt->va_cols = NIL;
vacuum(vacstmt, relids);
}
/*
--- 827,842 ----
/* Set up command parameters */
vacstmt->vacuum = dovacuum;
vacstmt->full = false;
! vacstmt->analyze = doanalyze;
! vacstmt->freeze = freeze;
vacstmt->verbose = false;
vacstmt->relation = NULL; /* all tables, or not used if relids != NIL */
vacstmt->va_cols = NIL;
vacuum(vacstmt, relids);
+
+ pfree(vacstmt);
+ MemoryContextSwitchTo(old_cxt);
}
/*
Index: src/backend/postmaster/pgstat.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/postmaster/pgstat.c,v
retrieving revision 1.102
diff -c -r1.102 pgstat.c
*** src/backend/postmaster/pgstat.c 29 Jul 2005 19:30:04 -0000 1.102
--- src/backend/postmaster/pgstat.c 31 Jul 2005 21:36:07 -0000
***************
*** 99,105 ****
* ----------
*/
bool pgstat_collect_startcollector = true;
! bool pgstat_collect_resetonpmstart = true;
bool pgstat_collect_querystring = false;
bool pgstat_collect_tuplelevel = false;
bool pgstat_collect_blocklevel = false;
--- 99,105 ----
* ----------
*/
bool pgstat_collect_startcollector = true;
! bool pgstat_collect_resetonpmstart = false;
bool pgstat_collect_querystring = false;
bool pgstat_collect_tuplelevel = false;
bool pgstat_collect_blocklevel = false;
***************
*** 236,242 ****
* statistics on postmaster start, simply remove the stats file.
*/
if (!pgstat_collect_startcollector || pgstat_collect_resetonpmstart)
! unlink(PGSTAT_STAT_FILENAME);
/*
* Nothing else required if collector will not get started
--- 236,242 ----
* statistics on postmaster start, simply remove the stats file.
*/
if (!pgstat_collect_startcollector || pgstat_collect_resetonpmstart)
! pgstat_reset_all();
/*
* Nothing else required if collector will not get started
***************
*** 455,460 ****
--- 455,472 ----
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
Index: src/backend/utils/init/flatfiles.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/utils/init/flatfiles.c,v
retrieving revision 1.13
diff -c -r1.13 flatfiles.c
*** src/backend/utils/init/flatfiles.c 28 Jul 2005 22:27:02 -0000 1.13
--- src/backend/utils/init/flatfiles.c 9 Aug 2005 16:39:46 -0000
***************
*** 208,219 ****
char *datname;
Oid datoid;
Oid dattablespace;
! TransactionId datfrozenxid;
datname = NameStr(dbform->datname);
datoid = HeapTupleGetOid(tuple);
dattablespace = dbform->dattablespace;
datfrozenxid = dbform->datfrozenxid;
/*
* Identify the oldest datfrozenxid, ignoring databases that are not
--- 208,221 ----
char *datname;
Oid datoid;
Oid dattablespace;
! TransactionId datfrozenxid,
! datvacuumxid;
datname = NameStr(dbform->datname);
datoid = HeapTupleGetOid(tuple);
dattablespace = dbform->dattablespace;
datfrozenxid = dbform->datfrozenxid;
+ datvacuumxid = dbform->datvacuumxid;
/*
* Identify the oldest datfrozenxid, ignoring databases that are not
***************
*** 248,254 ****
* for forensic purposes.
*/
fputs_quote(datname, fp);
! fprintf(fp, " %u %u %u\n", datoid, dattablespace, datfrozenxid);
}
heap_endscan(scan);
--- 250,257 ----
* for forensic purposes.
*/
fputs_quote(datname, fp);
! fprintf(fp, " %u %u %u %u\n", datoid, dattablespace, datfrozenxid,
! datvacuumxid);
}
heap_endscan(scan);
Index: src/backend/utils/init/postinit.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/utils/init/postinit.c,v
retrieving revision 1.155
diff -c -r1.155 postinit.c
*** src/backend/utils/init/postinit.c 31 Jul 2005 17:19:19 -0000 1.155
--- src/backend/utils/init/postinit.c 9 Aug 2005 16:43:27 -0000
***************
*** 78,84 ****
char *filename;
FILE *db_file;
char thisname[NAMEDATALEN];
! TransactionId frozenxid;
filename = database_getflatfilename();
db_file = AllocateFile(filename, "r");
--- 78,84 ----
char *filename;
FILE *db_file;
char thisname[NAMEDATALEN];
! TransactionId dummyxid;
filename = database_getflatfilename();
db_file = AllocateFile(filename, "r");
***************
*** 88,94 ****
errmsg("could not open file \"%s\": %m", filename)));
while (read_pg_database_line(db_file, thisname, db_id,
! db_tablespace, &frozenxid))
{
if (strcmp(thisname, name) == 0)
{
--- 88,95 ----
errmsg("could not open file \"%s\": %m", filename)));
while (read_pg_database_line(db_file, thisname, db_id,
! db_tablespace, &dummyxid,
! &dummyxid))
{
if (strcmp(thisname, name) == 0)
{
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/utils/misc/guc.c,v
retrieving revision 1.280
diff -c -r1.280 guc.c
*** src/backend/utils/misc/guc.c 30 Jul 2005 15:17:20 -0000 1.280
--- src/backend/utils/misc/guc.c 31 Jul 2005 21:15:36 -0000
***************
*** 672,678 ****
NULL
},
&pgstat_collect_resetonpmstart,
! true, NULL, NULL
},
{
{"stats_command_string", PGC_SUSET, STATS_COLLECTOR,
--- 672,678 ----
NULL
},
&pgstat_collect_resetonpmstart,
! false, NULL, NULL
},
{
{"stats_command_string", PGC_SUSET, STATS_COLLECTOR,
***************
*** 1161,1166 ****
--- 1161,1184 ----
},
{
+ {"autovacuum_vacuum_cost_delay", PGC_USERSET, 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_USERSET, 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,
gettext_noop("Sets the maximum number of simultaneously open files for each server process."),
NULL
Index: src/backend/utils/misc/postgresql.conf.sample
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/utils/misc/postgresql.conf.sample,v
retrieving revision 1.155
diff -c -r1.155 postgresql.conf.sample
*** src/backend/utils/misc/postgresql.conf.sample 30 Jul 2005 15:17:20 -0000 1.155
--- src/backend/utils/misc/postgresql.conf.sample 31 Jul 2005 21:16:43 -0000
***************
*** 287,293 ****
#stats_command_string = off
#stats_block_level = off
#stats_row_level = off
! #stats_reset_on_server_start = on
#---------------------------------------------------------------------------
--- 287,293 ----
#stats_command_string = off
#stats_block_level = off
#stats_row_level = off
! #stats_reset_on_server_start = off
#---------------------------------------------------------------------------
***************
*** 300,305 ****
--- 300,309 ----
#autovacuum_analyze_threshold = 500 # min # of tuple updates before analyze
#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_vacuum_cost_delay = -1 # default vacuum cost delay for autovac
+ # negative means use vacuum_cost_delay
+ #autovacuum_vacuum_cost_limit = -1 # default vacuum cost limit for autovac
+ # negative means use vacuum_cost_limit
#---------------------------------------------------------------------------
Index: src/include/pgstat.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/pgstat.h,v
retrieving revision 1.34
diff -c -r1.34 pgstat.h
*** src/include/pgstat.h 29 Jul 2005 19:30:09 -0000 1.34
--- src/include/pgstat.h 31 Jul 2005 21:32:59 -0000
***************
*** 367,372 ****
--- 367,373 ----
extern void pgstat_init(void);
extern int pgstat_start(void);
extern void pgstat_beterm(int pid);
+ extern void pgstat_reset_all(void);
#ifdef EXEC_BACKEND
extern void PgstatBufferMain(int argc, char *argv[]);
Index: src/include/catalog/pg_autovacuum.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/catalog/pg_autovacuum.h,v
retrieving revision 1.1
diff -c -r1.1 pg_autovacuum.h
*** src/include/catalog/pg_autovacuum.h 14 Jul 2005 05:13:42 -0000 1.1
--- src/include/catalog/pg_autovacuum.h 31 Jul 2005 23:26:27 -0000
***************
*** 34,39 ****
--- 34,41 ----
float4 vac_scale_factor; /* reltuples scaling factor */
int4 anl_base_thresh; /* base threshold value */
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;
/* ----------------
***************
*** 47,59 ****
* compiler constants for pg_autovacuum
* ----------------
*/
! #define Natts_pg_autovacuum 6
#define Anum_pg_autovacuum_vacrelid 1
#define Anum_pg_autovacuum_enabled 2
#define Anum_pg_autovacuum_vac_base_thresh 3
#define Anum_pg_autovacuum_vac_scale_factor 4
#define Anum_pg_autovacuum_anl_base_thresh 5
#define Anum_pg_autovacuum_anl_scale_factor 6
/* There are no preloaded tuples in pg_autovacuum.h */
--- 49,63 ----
* compiler constants for pg_autovacuum
* ----------------
*/
! #define Natts_pg_autovacuum 8
#define Anum_pg_autovacuum_vacrelid 1
#define Anum_pg_autovacuum_enabled 2
#define Anum_pg_autovacuum_vac_base_thresh 3
#define Anum_pg_autovacuum_vac_scale_factor 4
#define Anum_pg_autovacuum_anl_base_thresh 5
#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 */
Index: src/include/libpq/hba.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/libpq/hba.h,v
retrieving revision 1.39
diff -c -r1.39 hba.h
*** src/include/libpq/hba.h 29 Jul 2005 19:30:08 -0000 1.39
--- src/include/libpq/hba.h 9 Aug 2005 16:41:50 -0000
***************
*** 37,42 ****
extern int hba_getauthmethod(hbaPort *port);
extern int authident(hbaPort *port);
extern bool read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
! Oid *dbtablespace, TransactionId *dbfrozenxid);
#endif /* HBA_H */
--- 37,43 ----
extern int hba_getauthmethod(hbaPort *port);
extern int authident(hbaPort *port);
extern bool read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
! Oid *dbtablespace, TransactionId *dbfrozenxid,
! TransactionId *dbvacuumxid);
#endif /* HBA_H */
Index: src/include/postmaster/autovacuum.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/postmaster/autovacuum.h,v
retrieving revision 1.1
diff -c -r1.1 autovacuum.h
*** src/include/postmaster/autovacuum.h 14 Jul 2005 05:13:43 -0000 1.1
--- src/include/postmaster/autovacuum.h 31 Jul 2005 17:32:12 -0000
***************
*** 21,26 ****
--- 21,28 ----
extern double autovacuum_vac_scale;
extern int autovacuum_anl_thresh;
extern double autovacuum_anl_scale;
+ extern int autovacuum_vac_cost_delay;
+ extern int autovacuum_vac_cost_limit;
/* Status inquiry functions */
extern bool AutoVacuumingActive(void);