mirror of
https://github.com/postgres/postgres.git
synced 2025-07-27 12:41:57 +03:00
Fix autovacuum to avoid leaving non-permanent Xids in non-connectable
databases. Apply to the 8.1 branch only, as the new 8.2 (and HEAD) coding does not have this problem.
This commit is contained in:
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.5.2.6 2006/05/19 15:15:38 alvherre Exp $
|
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.5.2.7 2007/01/14 20:18:30 alvherre Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -482,30 +482,19 @@ autovac_get_database_list(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process a whole database. If it's a template database or is disallowing
|
* Return a palloc'ed copy of the pg_database entry for the given database.
|
||||||
* connection by means of datallowconn=false, then issue a VACUUM FREEZE.
|
* Note that no lock is retained on the entry whatsoever, so it may be stale by
|
||||||
* Else use a plain VACUUM.
|
* the time the caller inspects it. This is sufficient for our purposes
|
||||||
|
* however.
|
||||||
*/
|
*/
|
||||||
static void
|
static Form_pg_database
|
||||||
process_whole_db(void)
|
get_pg_database_entry(Oid dbid)
|
||||||
{
|
{
|
||||||
Relation dbRel;
|
Form_pg_database dbForm;
|
||||||
ScanKeyData entry[1];
|
ScanKeyData entry[1];
|
||||||
|
Relation dbRel;
|
||||||
SysScanDesc scan;
|
SysScanDesc scan;
|
||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
Form_pg_database dbForm;
|
|
||||||
bool freeze;
|
|
||||||
|
|
||||||
/* Start a transaction so our commands have one to play into. */
|
|
||||||
StartTransactionCommand();
|
|
||||||
|
|
||||||
/* functions in indexes may want a snapshot set */
|
|
||||||
ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Clean up any dead statistics collector entries for this DB.
|
|
||||||
*/
|
|
||||||
pgstat_vacuum_tabstat();
|
|
||||||
|
|
||||||
dbRel = heap_open(DatabaseRelationId, AccessShareLock);
|
dbRel = heap_open(DatabaseRelationId, AccessShareLock);
|
||||||
|
|
||||||
@ -523,17 +512,44 @@ process_whole_db(void)
|
|||||||
if (!HeapTupleIsValid(tup))
|
if (!HeapTupleIsValid(tup))
|
||||||
elog(ERROR, "could not find tuple for database %u", MyDatabaseId);
|
elog(ERROR, "could not find tuple for database %u", MyDatabaseId);
|
||||||
|
|
||||||
dbForm = (Form_pg_database) GETSTRUCT(tup);
|
dbForm = (Form_pg_database) palloc(sizeof(FormData_pg_database));
|
||||||
|
memcpy(dbForm, GETSTRUCT(tup), sizeof(FormData_pg_database));
|
||||||
if (!dbForm->datallowconn || dbForm->datistemplate)
|
|
||||||
freeze = true;
|
|
||||||
else
|
|
||||||
freeze = false;
|
|
||||||
|
|
||||||
systable_endscan(scan);
|
systable_endscan(scan);
|
||||||
|
|
||||||
heap_close(dbRel, AccessShareLock);
|
heap_close(dbRel, AccessShareLock);
|
||||||
|
|
||||||
|
return dbForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
Form_pg_database dbForm;
|
||||||
|
bool freeze;
|
||||||
|
|
||||||
|
/* Start a transaction so our commands have one to play into. */
|
||||||
|
StartTransactionCommand();
|
||||||
|
|
||||||
|
/* functions in indexes may want a snapshot set */
|
||||||
|
ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clean up any dead statistics collector entries for this DB.
|
||||||
|
*/
|
||||||
|
pgstat_vacuum_tabstat();
|
||||||
|
|
||||||
|
dbForm = get_pg_database_entry(MyDatabaseId);
|
||||||
|
|
||||||
|
freeze = (!dbForm->datallowconn || dbForm->datistemplate);
|
||||||
|
|
||||||
|
pfree(dbForm);
|
||||||
|
|
||||||
elog(DEBUG2, "autovacuum: VACUUM%s whole database",
|
elog(DEBUG2, "autovacuum: VACUUM%s whole database",
|
||||||
(freeze) ? " FREEZE" : "");
|
(freeze) ? " FREEZE" : "");
|
||||||
|
|
||||||
@ -564,6 +580,8 @@ do_autovacuum(PgStat_StatDBEntry *dbentry)
|
|||||||
List *toast_table_ids = NIL;
|
List *toast_table_ids = NIL;
|
||||||
ListCell *cell;
|
ListCell *cell;
|
||||||
PgStat_StatDBEntry *shared;
|
PgStat_StatDBEntry *shared;
|
||||||
|
Form_pg_database dbForm;
|
||||||
|
bool istemplate;
|
||||||
|
|
||||||
/* Start a transaction so our commands have one to play into. */
|
/* Start a transaction so our commands have one to play into. */
|
||||||
StartTransactionCommand();
|
StartTransactionCommand();
|
||||||
@ -578,6 +596,14 @@ do_autovacuum(PgStat_StatDBEntry *dbentry)
|
|||||||
*/
|
*/
|
||||||
pgstat_vacuum_tabstat();
|
pgstat_vacuum_tabstat();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In a template database, we need to avoid putting our Xid in any table,
|
||||||
|
* so disallow analyzes and force use of VACUUM FREEZE.
|
||||||
|
*/
|
||||||
|
dbForm = get_pg_database_entry(MyDatabaseId);
|
||||||
|
istemplate = (!dbForm->datallowconn || dbForm->datistemplate);
|
||||||
|
pfree(dbForm);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* StartTransactionCommand and CommitTransactionCommand will automatically
|
* StartTransactionCommand and CommitTransactionCommand will automatically
|
||||||
* switch to other contexts. We need this one to keep the list of
|
* switch to other contexts. We need this one to keep the list of
|
||||||
@ -694,10 +720,11 @@ do_autovacuum(PgStat_StatDBEntry *dbentry)
|
|||||||
VacuumCostDelay = tab->vacuum_cost_delay;
|
VacuumCostDelay = tab->vacuum_cost_delay;
|
||||||
VacuumCostLimit = tab->vacuum_cost_limit;
|
VacuumCostLimit = tab->vacuum_cost_limit;
|
||||||
|
|
||||||
|
/* in a template database, we never analyze and force freezing */
|
||||||
autovacuum_do_vac_analyze(list_make1_oid(tab->relid),
|
autovacuum_do_vac_analyze(list_make1_oid(tab->relid),
|
||||||
tab->dovacuum,
|
tab->dovacuum,
|
||||||
tab->doanalyze,
|
!istemplate && tab->doanalyze,
|
||||||
false);
|
istemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally close out the last transaction. */
|
/* Finally close out the last transaction. */
|
||||||
|
Reference in New Issue
Block a user