1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* vacuum.c
|
2001-07-14 00:55:59 +02:00
|
|
|
* The postgres vacuum cleaner.
|
|
|
|
*
|
2010-02-08 05:33:55 +01:00
|
|
|
* This file now includes only control and dispatch code for VACUUM and
|
|
|
|
* ANALYZE commands. Regular VACUUM is implemented in vacuumlazy.c,
|
|
|
|
* ANALYZE in analyze.c, and VACUUM FULL is a variant of CLUSTER, handled
|
|
|
|
* in cluster.c.
|
2001-07-14 00:55:59 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2011-01-01 19:18:15 +01:00
|
|
|
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/commands/vacuum.c
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
2000-12-02 20:38:34 +01:00
|
|
|
#include "postgres.h"
|
|
|
|
|
Fix VACUUM so that it always updates pg_class.reltuples/relpages.
When we added the ability for vacuum to skip heap pages by consulting the
visibility map, we made it just not update the reltuples/relpages
statistics if it skipped any pages. But this could leave us with extremely
out-of-date stats for a table that contains any unchanging areas,
especially for TOAST tables which never get processed by ANALYZE. In
particular this could result in autovacuum making poor decisions about when
to process the table, as in recent report from Florian Helmberger. And in
general it's a bad idea to not update the stats at all. Instead, use the
previous values of reltuples/relpages as an estimate of the tuple density
in unvisited pages. This approach results in a "moving average" estimate
of reltuples, which should converge to the correct value over multiple
VACUUM and ANALYZE cycles even when individual measurements aren't very
good.
This new method for updating reltuples is used by both VACUUM and ANALYZE,
with the result that we no longer need the grotty interconnections that
caused ANALYZE to not update the stats depending on what had happened
in the parent VACUUM command.
Also, fix the logic for skipping all-visible pages during VACUUM so that it
looks ahead rather than behind to decide what to do, as per a suggestion
from Greg Stark. This eliminates useless scanning of all-visible pages at
the start of the relation or just after a not-all-visible page. In
particular, the first few pages of the relation will not be invariably
included in the scanned pages, which seems to help in not overweighting
them in the reltuples estimate.
Back-patch to 8.4, where the visibility map was introduced.
2011-05-30 23:05:26 +02:00
|
|
|
#include <math.h>
|
|
|
|
|
2001-08-26 18:56:03 +02:00
|
|
|
#include "access/clog.h"
|
1998-04-27 06:08:07 +02:00
|
|
|
#include "access/genam.h"
|
|
|
|
#include "access/heapam.h"
|
2006-07-13 18:49:20 +02:00
|
|
|
#include "access/transam.h"
|
|
|
|
#include "access/xact.h"
|
2002-04-02 03:03:07 +02:00
|
|
|
#include "catalog/namespace.h"
|
2001-08-26 18:56:03 +02:00
|
|
|
#include "catalog/pg_database.h"
|
2008-02-20 15:31:35 +01:00
|
|
|
#include "catalog/pg_namespace.h"
|
2010-01-06 06:31:14 +01:00
|
|
|
#include "commands/cluster.h"
|
1998-04-27 06:08:07 +02:00
|
|
|
#include "commands/vacuum.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "miscadmin.h"
|
2008-03-26 22:10:39 +01:00
|
|
|
#include "pgstat.h"
|
2006-01-18 21:35:06 +01:00
|
|
|
#include "postmaster/autovacuum.h"
|
2008-05-12 02:00:54 +02:00
|
|
|
#include "storage/bufmgr.h"
|
|
|
|
#include "storage/lmgr.h"
|
2011-09-04 07:13:16 +02:00
|
|
|
#include "storage/proc.h"
|
2005-05-19 23:35:48 +02:00
|
|
|
#include "storage/procarray.h"
|
1999-11-29 05:43:15 +01:00
|
|
|
#include "utils/acl.h"
|
2000-05-28 19:56:29 +02:00
|
|
|
#include "utils/fmgroids.h"
|
2011-09-04 07:13:16 +02:00
|
|
|
#include "utils/guc.h"
|
2005-05-06 19:24:55 +02:00
|
|
|
#include "utils/memutils.h"
|
2008-03-26 19:48:59 +01:00
|
|
|
#include "utils/snapmgr.h"
|
1998-04-27 06:08:07 +02:00
|
|
|
#include "utils/syscache.h"
|
2008-03-26 22:10:39 +01:00
|
|
|
#include "utils/tqual.h"
|
2001-06-22 21:16:24 +02:00
|
|
|
|
2001-05-07 02:43:27 +02:00
|
|
|
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
/*
|
|
|
|
* GUC parameters
|
|
|
|
*/
|
|
|
|
int vacuum_freeze_min_age;
|
2009-01-16 14:27:24 +01:00
|
|
|
int vacuum_freeze_table_age;
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
|
2001-05-07 02:43:27 +02:00
|
|
|
|
2007-05-30 22:12:03 +02:00
|
|
|
/* A few variables that don't seem worth passing around as parameters */
|
2000-06-28 05:33:33 +02:00
|
|
|
static MemoryContext vac_context = NULL;
|
2007-05-30 22:12:03 +02:00
|
|
|
static BufferAccessStrategy vac_strategy;
|
|
|
|
|
2001-05-07 02:43:27 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* non-export function prototypes */
|
2010-11-18 09:04:02 +01:00
|
|
|
static List *get_rel_oids(Oid relid, const RangeVar *vacrel);
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
static void vac_truncate_clog(TransactionId frozenXID);
|
2011-02-08 04:04:29 +01:00
|
|
|
static bool vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast,
|
Fix VACUUM so that it always updates pg_class.reltuples/relpages.
When we added the ability for vacuum to skip heap pages by consulting the
visibility map, we made it just not update the reltuples/relpages
statistics if it skipped any pages. But this could leave us with extremely
out-of-date stats for a table that contains any unchanging areas,
especially for TOAST tables which never get processed by ANALYZE. In
particular this could result in autovacuum making poor decisions about when
to process the table, as in recent report from Florian Helmberger. And in
general it's a bad idea to not update the stats at all. Instead, use the
previous values of reltuples/relpages as an estimate of the tuple density
in unvisited pages. This approach results in a "moving average" estimate
of reltuples, which should converge to the correct value over multiple
VACUUM and ANALYZE cycles even when individual measurements aren't very
good.
This new method for updating reltuples is used by both VACUUM and ANALYZE,
with the result that we no longer need the grotty interconnections that
caused ANALYZE to not update the stats depending on what had happened
in the parent VACUUM command.
Also, fix the logic for skipping all-visible pages during VACUUM so that it
looks ahead rather than behind to decide what to do, as per a suggestion
from Greg Stark. This eliminates useless scanning of all-visible pages at
the start of the relation or just after a not-all-visible page. In
particular, the first few pages of the relation will not be invariably
included in the scanned pages, which seems to help in not overweighting
them in the reltuples estimate.
Back-patch to 8.4, where the visibility map was introduced.
2011-05-30 23:05:26 +02:00
|
|
|
bool for_wraparound);
|
2000-06-28 05:33:33 +02:00
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2001-05-07 02:43:27 +02:00
|
|
|
/*
|
|
|
|
* Primary entry point for VACUUM and ANALYZE commands.
|
2005-07-14 07:13:45 +02:00
|
|
|
*
|
2008-06-05 17:47:32 +02:00
|
|
|
* relid is normally InvalidOid; if it is not, then it provides the relation
|
|
|
|
* OID to be processed, and vacstmt->relation is ignored. (The non-invalid
|
|
|
|
* case is currently only used by autovacuum.)
|
2005-07-14 07:13:45 +02:00
|
|
|
*
|
2008-08-13 02:07:50 +02:00
|
|
|
* do_toast is passed as FALSE by autovacuum, because it processes TOAST
|
|
|
|
* tables separately.
|
|
|
|
*
|
2008-03-14 18:25:59 +01:00
|
|
|
* for_wraparound is used by autovacuum to let us know when it's forcing
|
2011-06-29 08:26:14 +02:00
|
|
|
* a vacuum for wraparound, which should not be auto-canceled.
|
2008-03-14 18:25:59 +01:00
|
|
|
*
|
2007-05-30 22:12:03 +02:00
|
|
|
* bstrategy is normally given as NULL, but in autovacuum it can be passed
|
|
|
|
* in to use the same buffer strategy object across multiple vacuum() calls.
|
|
|
|
*
|
2007-03-13 01:33:44 +01:00
|
|
|
* isTopLevel should be passed down from ProcessUtility.
|
|
|
|
*
|
2008-06-05 17:47:32 +02:00
|
|
|
* It is the caller's responsibility that vacstmt and bstrategy
|
2005-07-14 07:13:45 +02:00
|
|
|
* (if given) be allocated in a memory context that won't disappear
|
2007-03-13 01:33:44 +01:00
|
|
|
* at transaction commit.
|
2001-05-07 02:43:27 +02:00
|
|
|
*/
|
1996-07-09 08:22:35 +02:00
|
|
|
void
|
2008-08-13 02:07:50 +02:00
|
|
|
vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
|
2008-03-14 18:25:59 +01:00
|
|
|
BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2009-11-16 22:32:07 +01:00
|
|
|
const char *stmttype;
|
2011-04-11 21:28:45 +02:00
|
|
|
volatile bool in_outer_xact,
|
2004-05-23 01:14:38 +02:00
|
|
|
use_own_xacts;
|
2004-05-26 06:41:50 +02:00
|
|
|
List *relations;
|
2002-04-02 03:03:07 +02:00
|
|
|
|
2009-11-16 22:32:07 +01:00
|
|
|
/* sanity checks on options */
|
|
|
|
Assert(vacstmt->options & (VACOPT_VACUUM | VACOPT_ANALYZE));
|
|
|
|
Assert((vacstmt->options & VACOPT_VACUUM) ||
|
|
|
|
!(vacstmt->options & (VACOPT_FULL | VACOPT_FREEZE)));
|
|
|
|
Assert((vacstmt->options & VACOPT_ANALYZE) || vacstmt->va_cols == NIL);
|
|
|
|
|
|
|
|
stmttype = (vacstmt->options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE";
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* We cannot run VACUUM inside a user transaction block; if we were inside
|
|
|
|
* a transaction, then our commit- and start-transaction-command calls
|
2010-02-26 03:01:40 +01:00
|
|
|
* would not have the intended effect! There are numerous other subtle
|
2010-02-08 05:33:55 +01:00
|
|
|
* dependencies on this, too.
|
2004-05-23 01:14:38 +02:00
|
|
|
*
|
|
|
|
* ANALYZE (without VACUUM) can run either way.
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
2009-11-16 22:32:07 +01:00
|
|
|
if (vacstmt->options & VACOPT_VACUUM)
|
2004-05-23 01:14:38 +02:00
|
|
|
{
|
2007-03-13 01:33:44 +01:00
|
|
|
PreventTransactionChain(isTopLevel, stmttype);
|
2004-05-23 01:14:38 +02:00
|
|
|
in_outer_xact = false;
|
|
|
|
}
|
|
|
|
else
|
2007-03-13 01:33:44 +01:00
|
|
|
in_outer_xact = IsInTransactionChain(isTopLevel);
|
2002-06-13 21:52:02 +02:00
|
|
|
|
2004-10-07 16:19:58 +02:00
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* Send info about dead objects to the statistics collector, unless we are
|
|
|
|
* in autovacuum --- autovacuum.c does this for itself.
|
2004-10-07 16:19:58 +02:00
|
|
|
*/
|
2009-11-16 22:32:07 +01:00
|
|
|
if ((vacstmt->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
|
2008-05-15 02:17:41 +02:00
|
|
|
pgstat_vacuum_stat();
|
2001-06-22 21:16:24 +02:00
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
/*
|
|
|
|
* Create special memory context for cross-transaction storage.
|
|
|
|
*
|
2005-11-22 19:17:34 +01:00
|
|
|
* Since it is a child of PortalContext, it will go away eventually even
|
|
|
|
* if we suffer an error; there's no need for special abort cleanup logic.
|
2000-06-28 05:33:33 +02:00
|
|
|
*/
|
2003-05-02 22:54:36 +02:00
|
|
|
vac_context = AllocSetContextCreate(PortalContext,
|
2000-06-28 05:33:33 +02:00
|
|
|
"Vacuum",
|
|
|
|
ALLOCSET_DEFAULT_MINSIZE,
|
|
|
|
ALLOCSET_DEFAULT_INITSIZE,
|
|
|
|
ALLOCSET_DEFAULT_MAXSIZE);
|
2000-03-09 00:41:00 +01:00
|
|
|
|
2007-05-30 22:12:03 +02:00
|
|
|
/*
|
|
|
|
* If caller didn't give us a buffer strategy object, make one in the
|
|
|
|
* cross-transaction memory context.
|
|
|
|
*/
|
|
|
|
if (bstrategy == NULL)
|
|
|
|
{
|
|
|
|
MemoryContext old_context = MemoryContextSwitchTo(vac_context);
|
|
|
|
|
|
|
|
bstrategy = GetAccessStrategy(BAS_VACUUM);
|
|
|
|
MemoryContextSwitchTo(old_context);
|
|
|
|
}
|
|
|
|
vac_strategy = bstrategy;
|
|
|
|
|
2005-07-14 07:13:45 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Build list of relations to process, unless caller gave us one. (If we
|
|
|
|
* build one, we put it in vac_context for safekeeping.)
|
2005-07-14 07:13:45 +02:00
|
|
|
*/
|
2010-11-18 09:04:02 +01:00
|
|
|
relations = get_rel_oids(relid, vacstmt->relation);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2004-05-23 01:14:38 +02:00
|
|
|
/*
|
|
|
|
* Decide whether we need to start/commit our own transactions.
|
|
|
|
*
|
2005-11-22 19:17:34 +01:00
|
|
|
* For VACUUM (with or without ANALYZE): always do so, so that we can
|
|
|
|
* release locks as soon as possible. (We could possibly use the outer
|
2005-10-15 04:49:52 +02:00
|
|
|
* transaction for a one-table VACUUM, but handling TOAST tables would be
|
|
|
|
* problematic.)
|
2004-05-23 01:14:38 +02:00
|
|
|
*
|
|
|
|
* For ANALYZE (no VACUUM): if inside a transaction block, we cannot
|
2005-10-15 04:49:52 +02:00
|
|
|
* start/commit our own transactions. Also, there's no need to do so if
|
|
|
|
* only processing one relation. For multiple relations when not within a
|
2007-06-14 15:53:14 +02:00
|
|
|
* transaction block, and also in an autovacuum worker, use own
|
|
|
|
* transactions so we can release locks sooner.
|
2004-05-23 01:14:38 +02:00
|
|
|
*/
|
2009-11-16 22:32:07 +01:00
|
|
|
if (vacstmt->options & VACOPT_VACUUM)
|
2004-05-23 01:14:38 +02:00
|
|
|
use_own_xacts = true;
|
|
|
|
else
|
|
|
|
{
|
2009-11-16 22:32:07 +01:00
|
|
|
Assert(vacstmt->options & VACOPT_ANALYZE);
|
2007-06-14 15:53:14 +02:00
|
|
|
if (IsAutoVacuumWorkerProcess())
|
|
|
|
use_own_xacts = true;
|
|
|
|
else if (in_outer_xact)
|
2004-05-23 01:14:38 +02:00
|
|
|
use_own_xacts = false;
|
2004-05-26 06:41:50 +02:00
|
|
|
else if (list_length(relations) > 1)
|
2004-05-23 01:14:38 +02:00
|
|
|
use_own_xacts = true;
|
|
|
|
else
|
|
|
|
use_own_xacts = false;
|
|
|
|
}
|
|
|
|
|
2002-06-15 23:52:31 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* vacuum_rel expects to be entered with no transaction active; it will
|
|
|
|
* start and commit its own transaction. But we are called by an SQL
|
|
|
|
* command, and so we are executing inside a transaction already. We
|
|
|
|
* commit the transaction started in PostgresMain() here, and start
|
|
|
|
* another one before exiting to match the commit waiting for us back in
|
|
|
|
* PostgresMain().
|
2000-03-09 00:41:00 +01:00
|
|
|
*/
|
2004-05-23 01:14:38 +02:00
|
|
|
if (use_own_xacts)
|
2002-06-13 21:52:02 +02:00
|
|
|
{
|
2008-05-12 22:02:02 +02:00
|
|
|
/* ActiveSnapshot is not set by autovacuum */
|
|
|
|
if (ActiveSnapshotSet())
|
|
|
|
PopActiveSnapshot();
|
|
|
|
|
2002-06-13 21:52:02 +02:00
|
|
|
/* matches the StartTransaction in PostgresMain() */
|
2003-05-14 05:26:03 +02:00
|
|
|
CommitTransactionCommand();
|
2002-06-13 21:52:02 +02:00
|
|
|
}
|
2000-03-09 00:41:00 +01:00
|
|
|
|
2004-07-31 02:45:57 +02:00
|
|
|
/* Turn vacuum cost accounting on or off */
|
|
|
|
PG_TRY();
|
2001-05-07 02:43:27 +02:00
|
|
|
{
|
2004-07-31 02:45:57 +02:00
|
|
|
ListCell *cur;
|
2002-04-02 03:03:07 +02:00
|
|
|
|
2004-08-06 06:15:09 +02:00
|
|
|
VacuumCostActive = (VacuumCostDelay > 0);
|
2004-07-31 02:45:57 +02:00
|
|
|
VacuumCostBalance = 0;
|
|
|
|
|
2004-10-07 16:19:58 +02:00
|
|
|
/*
|
|
|
|
* Loop to process each selected relation.
|
|
|
|
*/
|
2004-07-31 02:45:57 +02:00
|
|
|
foreach(cur, relations)
|
2002-06-13 21:52:02 +02:00
|
|
|
{
|
2004-07-31 02:45:57 +02:00
|
|
|
Oid relid = lfirst_oid(cur);
|
|
|
|
|
2009-11-16 22:32:07 +01:00
|
|
|
if (vacstmt->options & VACOPT_VACUUM)
|
2011-02-08 04:04:29 +01:00
|
|
|
{
|
Fix VACUUM so that it always updates pg_class.reltuples/relpages.
When we added the ability for vacuum to skip heap pages by consulting the
visibility map, we made it just not update the reltuples/relpages
statistics if it skipped any pages. But this could leave us with extremely
out-of-date stats for a table that contains any unchanging areas,
especially for TOAST tables which never get processed by ANALYZE. In
particular this could result in autovacuum making poor decisions about when
to process the table, as in recent report from Florian Helmberger. And in
general it's a bad idea to not update the stats at all. Instead, use the
previous values of reltuples/relpages as an estimate of the tuple density
in unvisited pages. This approach results in a "moving average" estimate
of reltuples, which should converge to the correct value over multiple
VACUUM and ANALYZE cycles even when individual measurements aren't very
good.
This new method for updating reltuples is used by both VACUUM and ANALYZE,
with the result that we no longer need the grotty interconnections that
caused ANALYZE to not update the stats depending on what had happened
in the parent VACUUM command.
Also, fix the logic for skipping all-visible pages during VACUUM so that it
looks ahead rather than behind to decide what to do, as per a suggestion
from Greg Stark. This eliminates useless scanning of all-visible pages at
the start of the relation or just after a not-all-visible page. In
particular, the first few pages of the relation will not be invariably
included in the scanned pages, which seems to help in not overweighting
them in the reltuples estimate.
Back-patch to 8.4, where the visibility map was introduced.
2011-05-30 23:05:26 +02:00
|
|
|
if (!vacuum_rel(relid, vacstmt, do_toast, for_wraparound))
|
2011-02-08 04:04:29 +01:00
|
|
|
continue;
|
|
|
|
}
|
2006-07-10 18:20:52 +02:00
|
|
|
|
2009-11-16 22:32:07 +01:00
|
|
|
if (vacstmt->options & VACOPT_ANALYZE)
|
2002-06-13 21:52:02 +02:00
|
|
|
{
|
2004-07-31 02:45:57 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* If using separate xacts, start one for analyze. Otherwise,
|
2009-12-29 21:11:45 +01:00
|
|
|
* we can use the outer transaction.
|
2004-07-31 02:45:57 +02:00
|
|
|
*/
|
|
|
|
if (use_own_xacts)
|
|
|
|
{
|
|
|
|
StartTransactionCommand();
|
2004-09-13 22:10:13 +02:00
|
|
|
/* functions in indexes may want a snapshot set */
|
2008-05-12 22:02:02 +02:00
|
|
|
PushActiveSnapshot(GetTransactionSnapshot());
|
2004-07-31 02:45:57 +02:00
|
|
|
}
|
|
|
|
|
Fix VACUUM so that it always updates pg_class.reltuples/relpages.
When we added the ability for vacuum to skip heap pages by consulting the
visibility map, we made it just not update the reltuples/relpages
statistics if it skipped any pages. But this could leave us with extremely
out-of-date stats for a table that contains any unchanging areas,
especially for TOAST tables which never get processed by ANALYZE. In
particular this could result in autovacuum making poor decisions about when
to process the table, as in recent report from Florian Helmberger. And in
general it's a bad idea to not update the stats at all. Instead, use the
previous values of reltuples/relpages as an estimate of the tuple density
in unvisited pages. This approach results in a "moving average" estimate
of reltuples, which should converge to the correct value over multiple
VACUUM and ANALYZE cycles even when individual measurements aren't very
good.
This new method for updating reltuples is used by both VACUUM and ANALYZE,
with the result that we no longer need the grotty interconnections that
caused ANALYZE to not update the stats depending on what had happened
in the parent VACUUM command.
Also, fix the logic for skipping all-visible pages during VACUUM so that it
looks ahead rather than behind to decide what to do, as per a suggestion
from Greg Stark. This eliminates useless scanning of all-visible pages at
the start of the relation or just after a not-all-visible page. In
particular, the first few pages of the relation will not be invariably
included in the scanned pages, which seems to help in not overweighting
them in the reltuples estimate.
Back-patch to 8.4, where the visibility map was introduced.
2011-05-30 23:05:26 +02:00
|
|
|
analyze_rel(relid, vacstmt, vac_strategy);
|
2004-07-31 02:45:57 +02:00
|
|
|
|
|
|
|
if (use_own_xacts)
|
2008-05-12 22:02:02 +02:00
|
|
|
{
|
|
|
|
PopActiveSnapshot();
|
2004-07-31 02:45:57 +02:00
|
|
|
CommitTransactionCommand();
|
2008-05-12 22:02:02 +02:00
|
|
|
}
|
2002-06-13 21:52:02 +02:00
|
|
|
}
|
|
|
|
}
|
2001-05-07 02:43:27 +02:00
|
|
|
}
|
2004-07-31 02:45:57 +02:00
|
|
|
PG_CATCH();
|
|
|
|
{
|
|
|
|
/* Make sure cost accounting is turned off after error */
|
|
|
|
VacuumCostActive = false;
|
|
|
|
PG_RE_THROW();
|
|
|
|
}
|
|
|
|
PG_END_TRY();
|
|
|
|
|
|
|
|
/* Turn off vacuum cost accounting */
|
|
|
|
VacuumCostActive = false;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2004-10-07 16:19:58 +02:00
|
|
|
/*
|
|
|
|
* Finish up processing.
|
|
|
|
*/
|
2004-05-23 01:14:38 +02:00
|
|
|
if (use_own_xacts)
|
2001-08-26 18:56:03 +02:00
|
|
|
{
|
2002-06-15 23:52:31 +02:00
|
|
|
/* here, we are not in a transaction */
|
1999-05-01 21:09:46 +02:00
|
|
|
|
2002-08-31 00:18:07 +02:00
|
|
|
/*
|
2002-09-04 22:31:48 +02:00
|
|
|
* This matches the CommitTransaction waiting for us in
|
2003-05-14 05:26:03 +02:00
|
|
|
* PostgresMain().
|
2002-08-31 00:18:07 +02:00
|
|
|
*/
|
2003-05-14 05:26:03 +02:00
|
|
|
StartTransactionCommand();
|
2004-05-23 01:14:38 +02:00
|
|
|
}
|
2000-06-28 05:33:33 +02:00
|
|
|
|
2009-11-16 22:32:07 +01:00
|
|
|
if ((vacstmt->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
|
2004-05-23 01:14:38 +02:00
|
|
|
{
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
/*
|
|
|
|
* Update pg_database.datfrozenxid, and truncate pg_clog if possible.
|
|
|
|
* (autovacuum.c does this for itself.)
|
|
|
|
*/
|
|
|
|
vac_update_datfrozenxid();
|
2001-08-26 18:56:03 +02:00
|
|
|
}
|
|
|
|
|
2000-06-28 05:33:33 +02:00
|
|
|
/*
|
|
|
|
* Clean up working storage --- note we must do this after
|
2005-10-15 04:49:52 +02:00
|
|
|
* StartTransactionCommand, else we might be trying to delete the active
|
|
|
|
* context!
|
2000-06-28 05:33:33 +02:00
|
|
|
*/
|
|
|
|
MemoryContextDelete(vac_context);
|
|
|
|
vac_context = NULL;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2002-04-02 03:03:07 +02:00
|
|
|
* Build a list of Oids for each relation to be processed
|
2001-07-12 06:11:13 +02:00
|
|
|
*
|
|
|
|
* The list is built in vac_context so that it will survive across our
|
|
|
|
* per-relation transactions.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2002-04-02 03:03:07 +02:00
|
|
|
static List *
|
2010-11-18 09:04:02 +01:00
|
|
|
get_rel_oids(Oid relid, const RangeVar *vacrel)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2004-01-06 19:07:32 +01:00
|
|
|
List *oid_list = NIL;
|
2002-04-02 03:03:07 +02:00
|
|
|
MemoryContext oldcontext;
|
|
|
|
|
2008-06-05 17:47:32 +02:00
|
|
|
/* OID supplied by VACUUM's caller? */
|
|
|
|
if (OidIsValid(relid))
|
|
|
|
{
|
|
|
|
oldcontext = MemoryContextSwitchTo(vac_context);
|
|
|
|
oid_list = lappend_oid(oid_list, relid);
|
|
|
|
MemoryContextSwitchTo(oldcontext);
|
|
|
|
}
|
|
|
|
else if (vacrel)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2004-01-06 19:07:32 +01:00
|
|
|
/* Process a specific relation */
|
2002-09-04 22:31:48 +02:00
|
|
|
Oid relid;
|
2002-04-02 03:03:07 +02:00
|
|
|
|
2011-07-09 04:19:30 +02:00
|
|
|
/*
|
|
|
|
* Since we don't take a lock here, the relation might be gone,
|
|
|
|
* or the RangeVar might no longer refer to the OID we look up
|
|
|
|
* here. In the former case, VACUUM will do nothing; in the
|
|
|
|
* latter case, it will process the OID we looked up here, rather
|
|
|
|
* than the new one. Neither is ideal, but there's little practical
|
|
|
|
* alternative, since we're going to commit this transaction and
|
|
|
|
* begin a new one between now and then.
|
|
|
|
*/
|
|
|
|
relid = RangeVarGetRelid(vacrel, NoLock, false, false);
|
2002-04-02 03:03:07 +02:00
|
|
|
|
|
|
|
/* Make a relation list entry for this guy */
|
|
|
|
oldcontext = MemoryContextSwitchTo(vac_context);
|
2004-05-26 06:41:50 +02:00
|
|
|
oid_list = lappend_oid(oid_list, relid);
|
2002-04-02 03:03:07 +02:00
|
|
|
MemoryContextSwitchTo(oldcontext);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-04-02 03:03:07 +02:00
|
|
|
/* Process all plain relations listed in pg_class */
|
|
|
|
Relation pgclass;
|
|
|
|
HeapScanDesc scan;
|
|
|
|
HeapTuple tuple;
|
|
|
|
ScanKeyData key;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2003-11-12 22:15:59 +01:00
|
|
|
ScanKeyInit(&key,
|
|
|
|
Anum_pg_class_relkind,
|
|
|
|
BTEqualStrategyNumber, F_CHAREQ,
|
|
|
|
CharGetDatum(RELKIND_RELATION));
|
1996-10-03 22:11:41 +02:00
|
|
|
|
2005-04-14 22:03:27 +02:00
|
|
|
pgclass = heap_open(RelationRelationId, AccessShareLock);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2002-05-21 01:51:44 +02:00
|
|
|
scan = heap_beginscan(pgclass, SnapshotNow, 1, &key);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2002-05-21 01:51:44 +02:00
|
|
|
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2002-04-02 03:03:07 +02:00
|
|
|
/* Make a relation list entry for this guy */
|
|
|
|
oldcontext = MemoryContextSwitchTo(vac_context);
|
2004-05-26 06:41:50 +02:00
|
|
|
oid_list = lappend_oid(oid_list, HeapTupleGetOid(tuple));
|
2002-04-02 03:03:07 +02:00
|
|
|
MemoryContextSwitchTo(oldcontext);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2002-04-02 03:03:07 +02:00
|
|
|
heap_endscan(scan);
|
|
|
|
heap_close(pgclass, AccessShareLock);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
|
2004-01-06 19:07:32 +01:00
|
|
|
return oid_list;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2001-08-26 18:56:03 +02:00
|
|
|
/*
|
|
|
|
* vacuum_set_xid_limits() -- compute oldest-Xmin and freeze cutoff points
|
|
|
|
*/
|
|
|
|
void
|
2009-01-16 14:27:24 +01:00
|
|
|
vacuum_set_xid_limits(int freeze_min_age,
|
|
|
|
int freeze_table_age,
|
|
|
|
bool sharedRel,
|
2001-08-26 18:56:03 +02:00
|
|
|
TransactionId *oldestXmin,
|
2009-01-16 14:27:24 +01:00
|
|
|
TransactionId *freezeLimit,
|
|
|
|
TransactionId *freezeTableLimit)
|
2001-08-26 18:56:03 +02:00
|
|
|
{
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
int freezemin;
|
2001-08-26 18:56:03 +02:00
|
|
|
TransactionId limit;
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
TransactionId safeLimit;
|
2001-08-26 18:56:03 +02:00
|
|
|
|
2006-07-30 04:07:18 +02:00
|
|
|
/*
|
2006-10-04 02:30:14 +02:00
|
|
|
* We can always ignore processes running lazy vacuum. This is because we
|
2006-07-30 04:07:18 +02:00
|
|
|
* use these values only for deciding which tuples we must keep in the
|
2007-11-15 22:14:46 +01:00
|
|
|
* tables. Since lazy vacuum doesn't write its XID anywhere, it's safe to
|
2010-02-08 05:33:55 +01:00
|
|
|
* ignore it. In theory it could be problematic to ignore lazy vacuums in
|
2007-11-15 22:14:46 +01:00
|
|
|
* a full vacuum, but keep in mind that only one vacuum process can be
|
|
|
|
* working on a particular table at any time, and that each vacuum is
|
|
|
|
* always an independent transaction.
|
2006-07-30 04:07:18 +02:00
|
|
|
*/
|
|
|
|
*oldestXmin = GetOldestXmin(sharedRel, true);
|
2001-08-26 18:56:03 +02:00
|
|
|
|
|
|
|
Assert(TransactionIdIsNormal(*oldestXmin));
|
|
|
|
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
/*
|
2007-11-15 22:14:46 +01:00
|
|
|
* Determine the minimum freeze age to use: as specified by the caller, or
|
|
|
|
* vacuum_freeze_min_age, but in any case not more than half
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
* autovacuum_freeze_max_age, so that autovacuums to prevent XID
|
|
|
|
* wraparound won't occur too frequently.
|
|
|
|
*/
|
2007-05-17 17:28:29 +02:00
|
|
|
freezemin = freeze_min_age;
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
if (freezemin < 0)
|
|
|
|
freezemin = vacuum_freeze_min_age;
|
|
|
|
freezemin = Min(freezemin, autovacuum_freeze_max_age / 2);
|
|
|
|
Assert(freezemin >= 0);
|
2001-08-26 18:56:03 +02:00
|
|
|
|
2004-10-07 16:19:58 +02:00
|
|
|
/*
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
* Compute the cutoff XID, being careful not to generate a "permanent" XID
|
2004-10-07 16:19:58 +02:00
|
|
|
*/
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
limit = *oldestXmin - freezemin;
|
2001-08-26 18:56:03 +02:00
|
|
|
if (!TransactionIdIsNormal(limit))
|
|
|
|
limit = FirstNormalTransactionId;
|
|
|
|
|
2004-10-07 16:19:58 +02:00
|
|
|
/*
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
* If oldestXmin is very far back (in practice, more than
|
2007-11-15 22:14:46 +01:00
|
|
|
* autovacuum_freeze_max_age / 2 XIDs old), complain and force a minimum
|
|
|
|
* freeze age of zero.
|
2004-10-07 16:19:58 +02:00
|
|
|
*/
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
safeLimit = ReadNewTransactionId() - autovacuum_freeze_max_age;
|
|
|
|
if (!TransactionIdIsNormal(safeLimit))
|
|
|
|
safeLimit = FirstNormalTransactionId;
|
|
|
|
|
|
|
|
if (TransactionIdPrecedes(limit, safeLimit))
|
2001-08-26 18:56:03 +02:00
|
|
|
{
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(WARNING,
|
2003-09-25 08:58:07 +02:00
|
|
|
(errmsg("oldest xmin is far in the past"),
|
2003-07-20 23:56:35 +02:00
|
|
|
errhint("Close open transactions soon to avoid wraparound problems.")));
|
2001-08-26 18:56:03 +02:00
|
|
|
limit = *oldestXmin;
|
|
|
|
}
|
|
|
|
|
|
|
|
*freezeLimit = limit;
|
2009-01-16 14:27:24 +01:00
|
|
|
|
|
|
|
if (freezeTableLimit != NULL)
|
|
|
|
{
|
2009-06-11 16:49:15 +02:00
|
|
|
int freezetable;
|
2009-01-16 14:27:24 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Determine the table freeze age to use: as specified by the caller,
|
|
|
|
* or vacuum_freeze_table_age, but in any case not more than
|
|
|
|
* autovacuum_freeze_max_age * 0.95, so that if you have e.g nightly
|
|
|
|
* VACUUM schedule, the nightly VACUUM gets a chance to freeze tuples
|
|
|
|
* before anti-wraparound autovacuum is launched.
|
|
|
|
*/
|
|
|
|
freezetable = freeze_min_age;
|
|
|
|
if (freezetable < 0)
|
|
|
|
freezetable = vacuum_freeze_table_age;
|
|
|
|
freezetable = Min(freezetable, autovacuum_freeze_max_age * 0.95);
|
|
|
|
Assert(freezetable >= 0);
|
|
|
|
|
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* Compute the cutoff XID, being careful not to generate a "permanent"
|
|
|
|
* XID.
|
2009-01-16 14:27:24 +01:00
|
|
|
*/
|
|
|
|
limit = ReadNewTransactionId() - freezetable;
|
|
|
|
if (!TransactionIdIsNormal(limit))
|
|
|
|
limit = FirstNormalTransactionId;
|
|
|
|
|
|
|
|
*freezeTableLimit = limit;
|
|
|
|
}
|
2001-08-26 18:56:03 +02:00
|
|
|
}
|
|
|
|
|
2001-07-12 06:11:13 +02:00
|
|
|
|
Fix VACUUM so that it always updates pg_class.reltuples/relpages.
When we added the ability for vacuum to skip heap pages by consulting the
visibility map, we made it just not update the reltuples/relpages
statistics if it skipped any pages. But this could leave us with extremely
out-of-date stats for a table that contains any unchanging areas,
especially for TOAST tables which never get processed by ANALYZE. In
particular this could result in autovacuum making poor decisions about when
to process the table, as in recent report from Florian Helmberger. And in
general it's a bad idea to not update the stats at all. Instead, use the
previous values of reltuples/relpages as an estimate of the tuple density
in unvisited pages. This approach results in a "moving average" estimate
of reltuples, which should converge to the correct value over multiple
VACUUM and ANALYZE cycles even when individual measurements aren't very
good.
This new method for updating reltuples is used by both VACUUM and ANALYZE,
with the result that we no longer need the grotty interconnections that
caused ANALYZE to not update the stats depending on what had happened
in the parent VACUUM command.
Also, fix the logic for skipping all-visible pages during VACUUM so that it
looks ahead rather than behind to decide what to do, as per a suggestion
from Greg Stark. This eliminates useless scanning of all-visible pages at
the start of the relation or just after a not-all-visible page. In
particular, the first few pages of the relation will not be invariably
included in the scanned pages, which seems to help in not overweighting
them in the reltuples estimate.
Back-patch to 8.4, where the visibility map was introduced.
2011-05-30 23:05:26 +02:00
|
|
|
/*
|
|
|
|
* vac_estimate_reltuples() -- estimate the new value for pg_class.reltuples
|
|
|
|
*
|
|
|
|
* If we scanned the whole relation then we should just use the count of
|
|
|
|
* live tuples seen; but if we did not, we should not trust the count
|
|
|
|
* unreservedly, especially not in VACUUM, which may have scanned a quite
|
2011-06-09 20:32:50 +02:00
|
|
|
* nonrandom subset of the table. When we have only partial information,
|
Fix VACUUM so that it always updates pg_class.reltuples/relpages.
When we added the ability for vacuum to skip heap pages by consulting the
visibility map, we made it just not update the reltuples/relpages
statistics if it skipped any pages. But this could leave us with extremely
out-of-date stats for a table that contains any unchanging areas,
especially for TOAST tables which never get processed by ANALYZE. In
particular this could result in autovacuum making poor decisions about when
to process the table, as in recent report from Florian Helmberger. And in
general it's a bad idea to not update the stats at all. Instead, use the
previous values of reltuples/relpages as an estimate of the tuple density
in unvisited pages. This approach results in a "moving average" estimate
of reltuples, which should converge to the correct value over multiple
VACUUM and ANALYZE cycles even when individual measurements aren't very
good.
This new method for updating reltuples is used by both VACUUM and ANALYZE,
with the result that we no longer need the grotty interconnections that
caused ANALYZE to not update the stats depending on what had happened
in the parent VACUUM command.
Also, fix the logic for skipping all-visible pages during VACUUM so that it
looks ahead rather than behind to decide what to do, as per a suggestion
from Greg Stark. This eliminates useless scanning of all-visible pages at
the start of the relation or just after a not-all-visible page. In
particular, the first few pages of the relation will not be invariably
included in the scanned pages, which seems to help in not overweighting
them in the reltuples estimate.
Back-patch to 8.4, where the visibility map was introduced.
2011-05-30 23:05:26 +02:00
|
|
|
* we take the old value of pg_class.reltuples as a measurement of the
|
|
|
|
* tuple density in the unscanned pages.
|
|
|
|
*
|
|
|
|
* This routine is shared by VACUUM and ANALYZE.
|
|
|
|
*/
|
|
|
|
double
|
|
|
|
vac_estimate_reltuples(Relation relation, bool is_analyze,
|
|
|
|
BlockNumber total_pages,
|
|
|
|
BlockNumber scanned_pages,
|
|
|
|
double scanned_tuples)
|
|
|
|
{
|
2011-06-09 20:32:50 +02:00
|
|
|
BlockNumber old_rel_pages = relation->rd_rel->relpages;
|
Fix VACUUM so that it always updates pg_class.reltuples/relpages.
When we added the ability for vacuum to skip heap pages by consulting the
visibility map, we made it just not update the reltuples/relpages
statistics if it skipped any pages. But this could leave us with extremely
out-of-date stats for a table that contains any unchanging areas,
especially for TOAST tables which never get processed by ANALYZE. In
particular this could result in autovacuum making poor decisions about when
to process the table, as in recent report from Florian Helmberger. And in
general it's a bad idea to not update the stats at all. Instead, use the
previous values of reltuples/relpages as an estimate of the tuple density
in unvisited pages. This approach results in a "moving average" estimate
of reltuples, which should converge to the correct value over multiple
VACUUM and ANALYZE cycles even when individual measurements aren't very
good.
This new method for updating reltuples is used by both VACUUM and ANALYZE,
with the result that we no longer need the grotty interconnections that
caused ANALYZE to not update the stats depending on what had happened
in the parent VACUUM command.
Also, fix the logic for skipping all-visible pages during VACUUM so that it
looks ahead rather than behind to decide what to do, as per a suggestion
from Greg Stark. This eliminates useless scanning of all-visible pages at
the start of the relation or just after a not-all-visible page. In
particular, the first few pages of the relation will not be invariably
included in the scanned pages, which seems to help in not overweighting
them in the reltuples estimate.
Back-patch to 8.4, where the visibility map was introduced.
2011-05-30 23:05:26 +02:00
|
|
|
double old_rel_tuples = relation->rd_rel->reltuples;
|
|
|
|
double old_density;
|
|
|
|
double new_density;
|
|
|
|
double multiplier;
|
|
|
|
double updated_density;
|
|
|
|
|
|
|
|
/* If we did scan the whole table, just use the count as-is */
|
|
|
|
if (scanned_pages >= total_pages)
|
|
|
|
return scanned_tuples;
|
|
|
|
|
|
|
|
/*
|
2011-06-09 20:32:50 +02:00
|
|
|
* If scanned_pages is zero but total_pages isn't, keep the existing value
|
Fix a missed case in code for "moving average" estimate of reltuples.
It is possible for VACUUM to scan no pages at all, if the visibility map
shows that all pages are all-visible. In this situation VACUUM has no new
information to report about the relation's tuple density, so it wasn't
changing pg_class.reltuples ... but it updated pg_class.relpages anyway.
That's wrong in general, since there is no evidence to justify changing the
density ratio reltuples/relpages, but it's particularly bad if the previous
state was relpages=reltuples=0, which means "unknown tuple density".
We just replaced "unknown" with "zero". ANALYZE would eventually recover
from this, but it could take a lot of repetitions of ANALYZE to do so if
the relation size is much larger than the maximum number of pages ANALYZE
will scan, because of the moving-average behavior introduced by commit
b4b6923e03f4d29636a94f6f4cc2f5cf6298b8c8.
The only known situation where we could have relpages=reltuples=0 and yet
the visibility map asserts everything's visible is immediately following
a pg_upgrade. It might be advisable for pg_upgrade to try to preserve the
relpages/reltuples statistics; but in any case this code is wrong on its
own terms, so fix it. Per report from Sergey Koposov.
Back-patch to 8.4, where the visibility map was introduced, same as the
previous change.
2011-08-30 20:49:45 +02:00
|
|
|
* of reltuples. (Note: callers should avoid updating the pg_class
|
|
|
|
* statistics in this situation, since no new information has been
|
|
|
|
* provided.)
|
Fix VACUUM so that it always updates pg_class.reltuples/relpages.
When we added the ability for vacuum to skip heap pages by consulting the
visibility map, we made it just not update the reltuples/relpages
statistics if it skipped any pages. But this could leave us with extremely
out-of-date stats for a table that contains any unchanging areas,
especially for TOAST tables which never get processed by ANALYZE. In
particular this could result in autovacuum making poor decisions about when
to process the table, as in recent report from Florian Helmberger. And in
general it's a bad idea to not update the stats at all. Instead, use the
previous values of reltuples/relpages as an estimate of the tuple density
in unvisited pages. This approach results in a "moving average" estimate
of reltuples, which should converge to the correct value over multiple
VACUUM and ANALYZE cycles even when individual measurements aren't very
good.
This new method for updating reltuples is used by both VACUUM and ANALYZE,
with the result that we no longer need the grotty interconnections that
caused ANALYZE to not update the stats depending on what had happened
in the parent VACUUM command.
Also, fix the logic for skipping all-visible pages during VACUUM so that it
looks ahead rather than behind to decide what to do, as per a suggestion
from Greg Stark. This eliminates useless scanning of all-visible pages at
the start of the relation or just after a not-all-visible page. In
particular, the first few pages of the relation will not be invariably
included in the scanned pages, which seems to help in not overweighting
them in the reltuples estimate.
Back-patch to 8.4, where the visibility map was introduced.
2011-05-30 23:05:26 +02:00
|
|
|
*/
|
|
|
|
if (scanned_pages == 0)
|
|
|
|
return old_rel_tuples;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If old value of relpages is zero, old density is indeterminate; we
|
|
|
|
* can't do much except scale up scanned_tuples to match total_pages.
|
|
|
|
*/
|
|
|
|
if (old_rel_pages == 0)
|
|
|
|
return floor((scanned_tuples / scanned_pages) * total_pages + 0.5);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Okay, we've covered the corner cases. The normal calculation is to
|
2011-06-09 20:32:50 +02:00
|
|
|
* convert the old measurement to a density (tuples per page), then update
|
|
|
|
* the density using an exponential-moving-average approach, and finally
|
|
|
|
* compute reltuples as updated_density * total_pages.
|
Fix VACUUM so that it always updates pg_class.reltuples/relpages.
When we added the ability for vacuum to skip heap pages by consulting the
visibility map, we made it just not update the reltuples/relpages
statistics if it skipped any pages. But this could leave us with extremely
out-of-date stats for a table that contains any unchanging areas,
especially for TOAST tables which never get processed by ANALYZE. In
particular this could result in autovacuum making poor decisions about when
to process the table, as in recent report from Florian Helmberger. And in
general it's a bad idea to not update the stats at all. Instead, use the
previous values of reltuples/relpages as an estimate of the tuple density
in unvisited pages. This approach results in a "moving average" estimate
of reltuples, which should converge to the correct value over multiple
VACUUM and ANALYZE cycles even when individual measurements aren't very
good.
This new method for updating reltuples is used by both VACUUM and ANALYZE,
with the result that we no longer need the grotty interconnections that
caused ANALYZE to not update the stats depending on what had happened
in the parent VACUUM command.
Also, fix the logic for skipping all-visible pages during VACUUM so that it
looks ahead rather than behind to decide what to do, as per a suggestion
from Greg Stark. This eliminates useless scanning of all-visible pages at
the start of the relation or just after a not-all-visible page. In
particular, the first few pages of the relation will not be invariably
included in the scanned pages, which seems to help in not overweighting
them in the reltuples estimate.
Back-patch to 8.4, where the visibility map was introduced.
2011-05-30 23:05:26 +02:00
|
|
|
*
|
2011-06-09 20:32:50 +02:00
|
|
|
* For ANALYZE, the moving average multiplier is just the fraction of the
|
|
|
|
* table's pages we scanned. This is equivalent to assuming that the
|
|
|
|
* tuple density in the unscanned pages didn't change. Of course, it
|
|
|
|
* probably did, if the new density measurement is different. But over
|
|
|
|
* repeated cycles, the value of reltuples will converge towards the
|
|
|
|
* correct value, if repeated measurements show the same new density.
|
Fix VACUUM so that it always updates pg_class.reltuples/relpages.
When we added the ability for vacuum to skip heap pages by consulting the
visibility map, we made it just not update the reltuples/relpages
statistics if it skipped any pages. But this could leave us with extremely
out-of-date stats for a table that contains any unchanging areas,
especially for TOAST tables which never get processed by ANALYZE. In
particular this could result in autovacuum making poor decisions about when
to process the table, as in recent report from Florian Helmberger. And in
general it's a bad idea to not update the stats at all. Instead, use the
previous values of reltuples/relpages as an estimate of the tuple density
in unvisited pages. This approach results in a "moving average" estimate
of reltuples, which should converge to the correct value over multiple
VACUUM and ANALYZE cycles even when individual measurements aren't very
good.
This new method for updating reltuples is used by both VACUUM and ANALYZE,
with the result that we no longer need the grotty interconnections that
caused ANALYZE to not update the stats depending on what had happened
in the parent VACUUM command.
Also, fix the logic for skipping all-visible pages during VACUUM so that it
looks ahead rather than behind to decide what to do, as per a suggestion
from Greg Stark. This eliminates useless scanning of all-visible pages at
the start of the relation or just after a not-all-visible page. In
particular, the first few pages of the relation will not be invariably
included in the scanned pages, which seems to help in not overweighting
them in the reltuples estimate.
Back-patch to 8.4, where the visibility map was introduced.
2011-05-30 23:05:26 +02:00
|
|
|
*
|
|
|
|
* For VACUUM, the situation is a bit different: we have looked at a
|
|
|
|
* nonrandom sample of pages, but we know for certain that the pages we
|
|
|
|
* didn't look at are precisely the ones that haven't changed lately.
|
|
|
|
* Thus, there is a reasonable argument for doing exactly the same thing
|
2011-06-09 20:32:50 +02:00
|
|
|
* as for the ANALYZE case, that is use the old density measurement as the
|
|
|
|
* value for the unscanned pages.
|
Fix VACUUM so that it always updates pg_class.reltuples/relpages.
When we added the ability for vacuum to skip heap pages by consulting the
visibility map, we made it just not update the reltuples/relpages
statistics if it skipped any pages. But this could leave us with extremely
out-of-date stats for a table that contains any unchanging areas,
especially for TOAST tables which never get processed by ANALYZE. In
particular this could result in autovacuum making poor decisions about when
to process the table, as in recent report from Florian Helmberger. And in
general it's a bad idea to not update the stats at all. Instead, use the
previous values of reltuples/relpages as an estimate of the tuple density
in unvisited pages. This approach results in a "moving average" estimate
of reltuples, which should converge to the correct value over multiple
VACUUM and ANALYZE cycles even when individual measurements aren't very
good.
This new method for updating reltuples is used by both VACUUM and ANALYZE,
with the result that we no longer need the grotty interconnections that
caused ANALYZE to not update the stats depending on what had happened
in the parent VACUUM command.
Also, fix the logic for skipping all-visible pages during VACUUM so that it
looks ahead rather than behind to decide what to do, as per a suggestion
from Greg Stark. This eliminates useless scanning of all-visible pages at
the start of the relation or just after a not-all-visible page. In
particular, the first few pages of the relation will not be invariably
included in the scanned pages, which seems to help in not overweighting
them in the reltuples estimate.
Back-patch to 8.4, where the visibility map was introduced.
2011-05-30 23:05:26 +02:00
|
|
|
*
|
|
|
|
* This logic could probably use further refinement.
|
|
|
|
*/
|
|
|
|
old_density = old_rel_tuples / old_rel_pages;
|
|
|
|
new_density = scanned_tuples / scanned_pages;
|
|
|
|
multiplier = (double) scanned_pages / (double) total_pages;
|
|
|
|
updated_density = old_density + (new_density - old_density) * multiplier;
|
|
|
|
return floor(updated_density * total_pages + 0.5);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2001-07-12 06:11:13 +02:00
|
|
|
* vac_update_relstats() -- update statistics for one relation
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2001-07-12 06:11:13 +02:00
|
|
|
* Update the whole-relation statistics that are kept in its pg_class
|
|
|
|
* row. There are additional stats that will be updated if we are
|
|
|
|
* doing ANALYZE, but we always update these stats. This routine works
|
|
|
|
* for both index and heap relation entries in pg_class.
|
|
|
|
*
|
2006-05-11 01:18:39 +02:00
|
|
|
* We violate transaction semantics here by overwriting the rel's
|
|
|
|
* existing pg_class tuple with the new values. This is reasonably
|
|
|
|
* safe since the new values are correct whether or not this transaction
|
|
|
|
* commits. The reason for this is that if we updated these tuples in
|
2001-07-12 06:11:13 +02:00
|
|
|
* the usual way, vacuuming pg_class itself wouldn't work very well ---
|
|
|
|
* by the time we got done with a vacuum cycle, most of the tuples in
|
|
|
|
* pg_class would've been obsoleted. Of course, this only works for
|
|
|
|
* fixed-size never-null columns, but these are.
|
|
|
|
*
|
2008-11-10 01:49:37 +01:00
|
|
|
* Note another assumption: that two VACUUMs/ANALYZEs on a table can't
|
|
|
|
* run in parallel, nor can VACUUM/ANALYZE run in parallel with a
|
|
|
|
* schema alteration such as adding an index, rule, or trigger. Otherwise
|
|
|
|
* our updates of relhasindex etc might overwrite uncommitted updates.
|
|
|
|
*
|
2006-07-30 04:07:18 +02:00
|
|
|
* Another reason for doing it this way is that when we are in a lazy
|
2007-10-24 22:55:36 +02:00
|
|
|
* VACUUM and have PROC_IN_VACUUM set, we mustn't do any updates ---
|
|
|
|
* somebody vacuuming pg_class might think they could delete a tuple
|
|
|
|
* marked with xmin = our xid.
|
2006-07-30 04:07:18 +02:00
|
|
|
*
|
Fix VACUUM so that it always updates pg_class.reltuples/relpages.
When we added the ability for vacuum to skip heap pages by consulting the
visibility map, we made it just not update the reltuples/relpages
statistics if it skipped any pages. But this could leave us with extremely
out-of-date stats for a table that contains any unchanging areas,
especially for TOAST tables which never get processed by ANALYZE. In
particular this could result in autovacuum making poor decisions about when
to process the table, as in recent report from Florian Helmberger. And in
general it's a bad idea to not update the stats at all. Instead, use the
previous values of reltuples/relpages as an estimate of the tuple density
in unvisited pages. This approach results in a "moving average" estimate
of reltuples, which should converge to the correct value over multiple
VACUUM and ANALYZE cycles even when individual measurements aren't very
good.
This new method for updating reltuples is used by both VACUUM and ANALYZE,
with the result that we no longer need the grotty interconnections that
caused ANALYZE to not update the stats depending on what had happened
in the parent VACUUM command.
Also, fix the logic for skipping all-visible pages during VACUUM so that it
looks ahead rather than behind to decide what to do, as per a suggestion
from Greg Stark. This eliminates useless scanning of all-visible pages at
the start of the relation or just after a not-all-visible page. In
particular, the first few pages of the relation will not be invariably
included in the scanned pages, which seems to help in not overweighting
them in the reltuples estimate.
Back-patch to 8.4, where the visibility map was introduced.
2011-05-30 23:05:26 +02:00
|
|
|
* This routine is shared by VACUUM and ANALYZE.
|
2001-07-12 06:11:13 +02:00
|
|
|
*/
|
|
|
|
void
|
2008-11-10 01:49:37 +01:00
|
|
|
vac_update_relstats(Relation relation,
|
|
|
|
BlockNumber num_pages, double num_tuples,
|
2011-10-14 23:23:01 +02:00
|
|
|
BlockNumber num_all_visible_pages,
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
bool hasindex, TransactionId frozenxid)
|
2001-07-12 06:11:13 +02:00
|
|
|
{
|
2008-11-10 01:49:37 +01:00
|
|
|
Oid relid = RelationGetRelid(relation);
|
2001-07-12 06:11:13 +02:00
|
|
|
Relation rd;
|
|
|
|
HeapTuple ctup;
|
|
|
|
Form_pg_class pgcform;
|
2006-05-11 01:18:39 +02:00
|
|
|
bool dirty;
|
2001-07-12 06:11:13 +02:00
|
|
|
|
2005-04-14 22:03:27 +02:00
|
|
|
rd = heap_open(RelationRelationId, RowExclusiveLock);
|
2001-07-12 06:11:13 +02:00
|
|
|
|
2006-05-11 01:18:39 +02:00
|
|
|
/* Fetch a copy of the tuple to scribble on */
|
2010-02-14 19:42:19 +01:00
|
|
|
ctup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
|
2001-07-12 06:11:13 +02:00
|
|
|
if (!HeapTupleIsValid(ctup))
|
|
|
|
elog(ERROR, "pg_class entry for relid %u vanished during vacuuming",
|
|
|
|
relid);
|
2006-05-11 01:18:39 +02:00
|
|
|
pgcform = (Form_pg_class) GETSTRUCT(ctup);
|
2001-07-12 06:11:13 +02:00
|
|
|
|
2006-05-11 01:18:39 +02:00
|
|
|
/* Apply required updates, if any, to copied tuple */
|
2001-10-25 07:50:21 +02:00
|
|
|
|
2006-05-11 01:18:39 +02:00
|
|
|
dirty = false;
|
|
|
|
if (pgcform->relpages != (int32) num_pages)
|
|
|
|
{
|
|
|
|
pgcform->relpages = (int32) num_pages;
|
|
|
|
dirty = true;
|
|
|
|
}
|
|
|
|
if (pgcform->reltuples != (float4) num_tuples)
|
|
|
|
{
|
|
|
|
pgcform->reltuples = (float4) num_tuples;
|
|
|
|
dirty = true;
|
|
|
|
}
|
2011-10-14 23:23:01 +02:00
|
|
|
if (pgcform->relallvisible != (int32) num_all_visible_pages)
|
|
|
|
{
|
|
|
|
pgcform->relallvisible = (int32) num_all_visible_pages;
|
|
|
|
dirty = true;
|
|
|
|
}
|
2006-05-11 01:18:39 +02:00
|
|
|
if (pgcform->relhasindex != hasindex)
|
|
|
|
{
|
|
|
|
pgcform->relhasindex = hasindex;
|
|
|
|
dirty = true;
|
|
|
|
}
|
2006-10-04 02:30:14 +02:00
|
|
|
|
2001-08-10 20:57:42 +02:00
|
|
|
/*
|
2001-10-25 07:50:21 +02:00
|
|
|
* If we have discovered that there are no indexes, then there's no
|
2011-04-10 17:42:00 +02:00
|
|
|
* primary key either. This could be done more thoroughly...
|
2001-08-10 20:57:42 +02:00
|
|
|
*/
|
2011-01-25 23:51:59 +01:00
|
|
|
if (pgcform->relhaspkey && !hasindex)
|
2006-05-11 01:18:39 +02:00
|
|
|
{
|
2011-01-25 23:51:59 +01:00
|
|
|
pgcform->relhaspkey = false;
|
|
|
|
dirty = true;
|
2006-05-11 01:18:39 +02:00
|
|
|
}
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
|
2008-11-10 01:49:37 +01:00
|
|
|
/* We also clear relhasrules and relhastriggers if needed */
|
|
|
|
if (pgcform->relhasrules && relation->rd_rules == NULL)
|
|
|
|
{
|
|
|
|
pgcform->relhasrules = false;
|
|
|
|
dirty = true;
|
|
|
|
}
|
|
|
|
if (pgcform->relhastriggers && relation->trigdesc == NULL)
|
|
|
|
{
|
|
|
|
pgcform->relhastriggers = false;
|
|
|
|
dirty = true;
|
|
|
|
}
|
|
|
|
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
/*
|
|
|
|
* relfrozenxid should never go backward. Caller can pass
|
|
|
|
* InvalidTransactionId if it has no new data.
|
|
|
|
*/
|
|
|
|
if (TransactionIdIsNormal(frozenxid) &&
|
|
|
|
TransactionIdPrecedes(pgcform->relfrozenxid, frozenxid))
|
2006-07-10 18:20:52 +02:00
|
|
|
{
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
pgcform->relfrozenxid = frozenxid;
|
2006-07-10 18:20:52 +02:00
|
|
|
dirty = true;
|
|
|
|
}
|
2003-10-03 01:19:44 +02:00
|
|
|
|
2008-12-17 10:15:03 +01:00
|
|
|
/* If anything changed, write out the tuple. */
|
2006-05-11 01:18:39 +02:00
|
|
|
if (dirty)
|
|
|
|
heap_inplace_update(rd, ctup);
|
2001-07-12 06:11:13 +02:00
|
|
|
|
|
|
|
heap_close(rd, RowExclusiveLock);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-08-26 18:56:03 +02:00
|
|
|
/*
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
* vac_update_datfrozenxid() -- update pg_database.datfrozenxid for our DB
|
2001-08-26 18:56:03 +02:00
|
|
|
*
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
* Update pg_database's datfrozenxid entry for our database to be the
|
|
|
|
* minimum of the pg_class.relfrozenxid values. If we are able to
|
|
|
|
* advance pg_database.datfrozenxid, also try to truncate pg_clog.
|
2001-08-26 18:56:03 +02:00
|
|
|
*
|
2006-05-11 01:18:39 +02:00
|
|
|
* We violate transaction semantics here by overwriting the database's
|
2007-11-15 22:14:46 +01:00
|
|
|
* existing pg_database tuple with the new value. This is reasonably
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
* safe since the new value is correct whether or not this transaction
|
2006-05-11 01:18:39 +02:00
|
|
|
* commits. As with vac_update_relstats, this avoids leaving dead tuples
|
|
|
|
* behind after a VACUUM.
|
2001-08-26 18:56:03 +02:00
|
|
|
*/
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
void
|
|
|
|
vac_update_datfrozenxid(void)
|
2001-08-26 18:56:03 +02:00
|
|
|
{
|
|
|
|
HeapTuple tuple;
|
|
|
|
Form_pg_database dbform;
|
2006-07-10 18:20:52 +02:00
|
|
|
Relation relation;
|
2006-10-04 02:30:14 +02:00
|
|
|
SysScanDesc scan;
|
2006-07-10 18:20:52 +02:00
|
|
|
HeapTuple classTup;
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
TransactionId newFrozenXid;
|
2006-07-10 18:20:52 +02:00
|
|
|
bool dirty = false;
|
|
|
|
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
/*
|
2008-09-11 16:01:10 +02:00
|
|
|
* Initialize the "min" calculation with GetOldestXmin, which is a
|
|
|
|
* reasonable approximation to the minimum relfrozenxid for not-yet-
|
|
|
|
* committed pg_class entries for new tables; see AddNewRelationTuple().
|
|
|
|
* Se we cannot produce a wrong minimum by starting with this.
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
*/
|
2008-09-11 16:01:10 +02:00
|
|
|
newFrozenXid = GetOldestXmin(true, true);
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
|
2006-10-04 02:30:14 +02:00
|
|
|
/*
|
|
|
|
* We must seqscan pg_class to find the minimum Xid, because there is no
|
|
|
|
* index that can help us here.
|
2006-07-10 18:20:52 +02:00
|
|
|
*/
|
|
|
|
relation = heap_open(RelationRelationId, AccessShareLock);
|
|
|
|
|
|
|
|
scan = systable_beginscan(relation, InvalidOid, false,
|
|
|
|
SnapshotNow, 0, NULL);
|
|
|
|
|
|
|
|
while ((classTup = systable_getnext(scan)) != NULL)
|
|
|
|
{
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
Form_pg_class classForm = (Form_pg_class) GETSTRUCT(classTup);
|
2006-07-10 18:20:52 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Only consider heap and TOAST tables (anything else should have
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
* InvalidTransactionId in relfrozenxid anyway.)
|
2006-07-10 18:20:52 +02:00
|
|
|
*/
|
|
|
|
if (classForm->relkind != RELKIND_RELATION &&
|
|
|
|
classForm->relkind != RELKIND_TOASTVALUE)
|
|
|
|
continue;
|
|
|
|
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
Assert(TransactionIdIsNormal(classForm->relfrozenxid));
|
2006-07-10 18:20:52 +02:00
|
|
|
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
if (TransactionIdPrecedes(classForm->relfrozenxid, newFrozenXid))
|
|
|
|
newFrozenXid = classForm->relfrozenxid;
|
2006-07-10 18:20:52 +02:00
|
|
|
}
|
2001-08-26 18:56:03 +02:00
|
|
|
|
2006-07-10 18:20:52 +02:00
|
|
|
/* we're done with pg_class */
|
|
|
|
systable_endscan(scan);
|
|
|
|
heap_close(relation, AccessShareLock);
|
|
|
|
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
Assert(TransactionIdIsNormal(newFrozenXid));
|
2006-07-10 18:20:52 +02:00
|
|
|
|
|
|
|
/* Now fetch the pg_database tuple we need to update. */
|
2005-04-14 22:03:27 +02:00
|
|
|
relation = heap_open(DatabaseRelationId, RowExclusiveLock);
|
2001-08-26 18:56:03 +02:00
|
|
|
|
2006-05-11 01:18:39 +02:00
|
|
|
/* Fetch a copy of the tuple to scribble on */
|
2010-02-14 19:42:19 +01:00
|
|
|
tuple = SearchSysCacheCopy1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));
|
2001-08-26 18:56:03 +02:00
|
|
|
if (!HeapTupleIsValid(tuple))
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
elog(ERROR, "could not find tuple for database %u", MyDatabaseId);
|
2001-08-26 18:56:03 +02:00
|
|
|
dbform = (Form_pg_database) GETSTRUCT(tuple);
|
|
|
|
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
/*
|
|
|
|
* Don't allow datfrozenxid to go backward (probably can't happen anyway);
|
|
|
|
* and detect the common case where it doesn't go forward either.
|
|
|
|
*/
|
|
|
|
if (TransactionIdPrecedes(dbform->datfrozenxid, newFrozenXid))
|
2006-07-10 18:20:52 +02:00
|
|
|
{
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
dbform->datfrozenxid = newFrozenXid;
|
2006-07-10 18:20:52 +02:00
|
|
|
dirty = true;
|
|
|
|
}
|
2001-08-26 18:56:03 +02:00
|
|
|
|
2006-07-10 18:20:52 +02:00
|
|
|
if (dirty)
|
|
|
|
heap_inplace_update(relation, tuple);
|
2001-08-26 18:56:03 +02:00
|
|
|
|
2006-07-10 18:20:52 +02:00
|
|
|
heap_freetuple(tuple);
|
2001-08-26 18:56:03 +02:00
|
|
|
heap_close(relation, RowExclusiveLock);
|
2005-07-29 21:30:09 +02:00
|
|
|
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
/*
|
2010-02-26 03:01:40 +01:00
|
|
|
* If we were able to advance datfrozenxid, see if we can truncate
|
|
|
|
* pg_clog. Also do it if the shared XID-wrap-limit info is stale, since
|
|
|
|
* this action will update that too.
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
*/
|
2009-09-01 06:46:49 +02:00
|
|
|
if (dirty || ForceTransactionIdLimitUpdate())
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
vac_truncate_clog(newFrozenXid);
|
2001-08-26 18:56:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* vac_truncate_clog() -- attempt to truncate the commit log
|
|
|
|
*
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
* Scan pg_database to determine the system-wide oldest datfrozenxid,
|
2001-08-26 18:56:03 +02:00
|
|
|
* and use it to truncate the transaction commit log (pg_clog).
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
* Also update the XID wrap limit info maintained by varsup.c.
|
2001-08-26 18:56:03 +02:00
|
|
|
*
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
* The passed XID is simply the one I just wrote into my pg_database
|
|
|
|
* entry. It's used to initialize the "min" calculation.
|
2001-08-26 18:56:03 +02:00
|
|
|
*
|
2010-02-15 17:10:34 +01:00
|
|
|
* This routine is only invoked when we've managed to change our
|
2010-02-08 05:33:55 +01:00
|
|
|
* DB's datfrozenxid entry, or we found that the shared XID-wrap-limit
|
|
|
|
* info is stale.
|
2001-08-26 18:56:03 +02:00
|
|
|
*/
|
|
|
|
static void
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
vac_truncate_clog(TransactionId frozenXID)
|
2001-08-26 18:56:03 +02:00
|
|
|
{
|
2004-06-08 15:59:36 +02:00
|
|
|
TransactionId myXID = GetCurrentTransactionId();
|
2001-08-26 18:56:03 +02:00
|
|
|
Relation relation;
|
|
|
|
HeapScanDesc scan;
|
|
|
|
HeapTuple tuple;
|
2009-08-31 04:23:23 +02:00
|
|
|
Oid oldest_datoid;
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
bool frozenAlreadyWrapped = false;
|
2002-04-02 07:11:55 +02:00
|
|
|
|
2009-08-31 04:23:23 +02:00
|
|
|
/* init oldest_datoid to sync with my frozenXID */
|
|
|
|
oldest_datoid = MyDatabaseId;
|
2001-08-26 18:56:03 +02:00
|
|
|
|
2005-02-20 03:22:07 +01:00
|
|
|
/*
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
* Scan pg_database to compute the minimum datfrozenxid
|
|
|
|
*
|
|
|
|
* Note: we need not worry about a race condition with new entries being
|
|
|
|
* inserted by CREATE DATABASE. Any such entry will have a copy of some
|
|
|
|
* existing DB's datfrozenxid, and that source DB cannot be ours because
|
|
|
|
* of the interlock against copying a DB containing an active backend.
|
2007-11-15 22:14:46 +01:00
|
|
|
* Hence the new entry will not reduce the minimum. Also, if two VACUUMs
|
|
|
|
* concurrently modify the datfrozenxid's of different databases, the
|
|
|
|
* worst possible outcome is that pg_clog is not truncated as aggressively
|
|
|
|
* as it could be.
|
2005-02-20 03:22:07 +01:00
|
|
|
*/
|
2005-04-14 22:03:27 +02:00
|
|
|
relation = heap_open(DatabaseRelationId, AccessShareLock);
|
2001-08-26 18:56:03 +02:00
|
|
|
|
2002-05-21 01:51:44 +02:00
|
|
|
scan = heap_beginscan(relation, SnapshotNow, 0, NULL);
|
2001-08-26 18:56:03 +02:00
|
|
|
|
2002-05-21 01:51:44 +02:00
|
|
|
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
|
2001-08-26 18:56:03 +02:00
|
|
|
{
|
|
|
|
Form_pg_database dbform = (Form_pg_database) GETSTRUCT(tuple);
|
|
|
|
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
Assert(TransactionIdIsNormal(dbform->datfrozenxid));
|
2006-07-10 18:20:52 +02:00
|
|
|
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
if (TransactionIdPrecedes(myXID, dbform->datfrozenxid))
|
|
|
|
frozenAlreadyWrapped = true;
|
|
|
|
else if (TransactionIdPrecedes(dbform->datfrozenxid, frozenXID))
|
2002-04-02 07:11:55 +02:00
|
|
|
{
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
frozenXID = dbform->datfrozenxid;
|
2009-08-31 04:23:23 +02:00
|
|
|
oldest_datoid = HeapTupleGetOid(tuple);
|
2002-04-02 07:11:55 +02:00
|
|
|
}
|
2001-08-26 18:56:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
heap_endscan(scan);
|
|
|
|
|
|
|
|
heap_close(relation, AccessShareLock);
|
|
|
|
|
2002-04-02 07:11:55 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Do not truncate CLOG if we seem to have suffered wraparound already;
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
* the computed minimum XID might be bogus. This case should now be
|
|
|
|
* impossible due to the defenses in GetNewTransactionId, but we keep the
|
|
|
|
* test anyway.
|
2002-04-02 07:11:55 +02:00
|
|
|
*/
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
if (frozenAlreadyWrapped)
|
2002-04-02 07:11:55 +02:00
|
|
|
{
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(WARNING,
|
|
|
|
(errmsg("some databases have not been vacuumed in over 2 billion transactions"),
|
Wording cleanup for error messages. Also change can't -> cannot.
Standard English uses "may", "can", and "might" in different ways:
may - permission, "You may borrow my rake."
can - ability, "I can lift that log."
might - possibility, "It might rain today."
Unfortunately, in conversational English, their use is often mixed, as
in, "You may use this variable to do X", when in fact, "can" is a better
choice. Similarly, "It may crash" is better stated, "It might crash".
2007-02-01 20:10:30 +01:00
|
|
|
errdetail("You might have already suffered transaction-wraparound data loss.")));
|
2002-04-02 07:11:55 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
/* Truncate CLOG to the oldest frozenxid */
|
|
|
|
TruncateCLOG(frozenXID);
|
2006-07-10 18:20:52 +02:00
|
|
|
|
|
|
|
/*
|
Fix recently-understood problems with handling of XID freezing, particularly
in PITR scenarios. We now WAL-log the replacement of old XIDs with
FrozenTransactionId, so that such replacement is guaranteed to propagate to
PITR slave databases. Also, rather than relying on hint-bit updates to be
preserved, pg_clog is not truncated until all instances of an XID are known to
have been replaced by FrozenTransactionId. Add new GUC variables and
pg_autovacuum columns to allow management of the freezing policy, so that
users can trade off the size of pg_clog against the amount of freezing work
done. Revise the already-existing code that forces autovacuum of tables
approaching the wraparound point to make it more bulletproof; also, revise the
autovacuum logic so that anti-wraparound vacuuming is done per-table rather
than per-database. initdb forced because of changes in pg_class, pg_database,
and pg_autovacuum catalogs. Heikki Linnakangas, Simon Riggs, and Tom Lane.
2006-11-05 23:42:10 +01:00
|
|
|
* Update the wrap limit for GetNewTransactionId. Note: this function
|
|
|
|
* will also signal the postmaster for an(other) autovac cycle if needed.
|
2006-07-10 18:20:52 +02:00
|
|
|
*/
|
2009-08-31 04:23:23 +02:00
|
|
|
SetTransactionIdLimit(frozenXID, oldest_datoid);
|
2001-08-26 18:56:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-07-12 06:11:13 +02:00
|
|
|
/*
|
|
|
|
* vacuum_rel() -- vacuum one heap relation
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Doing one heap at a time incurs extra overhead, since we need to
|
|
|
|
* check that the heap exists again just before we vacuum it. The
|
|
|
|
* reason that we do this is so that vacuuming can be spread across
|
|
|
|
* many small transactions. Otherwise, two-phase locking would require
|
|
|
|
* us to lock the entire database during one pass of the vacuum cleaner.
|
2000-12-22 01:51:54 +01:00
|
|
|
*
|
|
|
|
* At entry and exit, we are not inside a transaction.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2011-02-08 04:04:29 +01:00
|
|
|
static bool
|
Fix VACUUM so that it always updates pg_class.reltuples/relpages.
When we added the ability for vacuum to skip heap pages by consulting the
visibility map, we made it just not update the reltuples/relpages
statistics if it skipped any pages. But this could leave us with extremely
out-of-date stats for a table that contains any unchanging areas,
especially for TOAST tables which never get processed by ANALYZE. In
particular this could result in autovacuum making poor decisions about when
to process the table, as in recent report from Florian Helmberger. And in
general it's a bad idea to not update the stats at all. Instead, use the
previous values of reltuples/relpages as an estimate of the tuple density
in unvisited pages. This approach results in a "moving average" estimate
of reltuples, which should converge to the correct value over multiple
VACUUM and ANALYZE cycles even when individual measurements aren't very
good.
This new method for updating reltuples is used by both VACUUM and ANALYZE,
with the result that we no longer need the grotty interconnections that
caused ANALYZE to not update the stats depending on what had happened
in the parent VACUUM command.
Also, fix the logic for skipping all-visible pages during VACUUM so that it
looks ahead rather than behind to decide what to do, as per a suggestion
from Greg Stark. This eliminates useless scanning of all-visible pages at
the start of the relation or just after a not-all-visible page. In
particular, the first few pages of the relation will not be invariably
included in the scanned pages, which seems to help in not overweighting
them in the reltuples estimate.
Back-patch to 8.4, where the visibility map was introduced.
2011-05-30 23:05:26 +02:00
|
|
|
vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2001-07-12 06:11:13 +02:00
|
|
|
LOCKMODE lmode;
|
1997-09-08 04:41:22 +02:00
|
|
|
Relation onerel;
|
2000-12-22 01:51:54 +01:00
|
|
|
LockRelId onerelid;
|
2000-07-05 18:17:43 +02:00
|
|
|
Oid toast_relid;
|
2008-01-03 22:23:15 +01:00
|
|
|
Oid save_userid;
|
Prevent indirect security attacks via changing session-local state within
an allegedly immutable index function. It was previously recognized that
we had to prevent such a function from executing SET/RESET ROLE/SESSION
AUTHORIZATION, or it could trivially obtain the privileges of the session
user. However, since there is in general no privilege checking for changes
of session-local state, it is also possible for such a function to change
settings in a way that might subvert later operations in the same session.
Examples include changing search_path to cause an unexpected function to
be called, or replacing an existing prepared statement with another one
that will execute a function of the attacker's choosing.
The present patch secures VACUUM, ANALYZE, and CREATE INDEX/REINDEX against
these threats, which are the same places previously deemed to need protection
against the SET ROLE issue. GUC changes are still allowed, since there are
many useful cases for that, but we prevent security problems by forcing a
rollback of any GUC change after completing the operation. Other cases are
handled by throwing an error if any change is attempted; these include temp
table creation, closing a cursor, and creating or deleting a prepared
statement. (In 7.4, the infrastructure to roll back GUC changes doesn't
exist, so we settle for rejecting changes of "search_path" in these contexts.)
Original report and patch by Gurjeet Singh, additional analysis by
Tom Lane.
Security: CVE-2009-4136
2009-12-09 22:57:51 +01:00
|
|
|
int save_sec_context;
|
|
|
|
int save_nestlevel;
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2000-12-22 01:51:54 +01:00
|
|
|
/* Begin a transaction for vacuuming this relation */
|
2003-05-14 05:26:03 +02:00
|
|
|
StartTransactionCommand();
|
2006-07-30 04:07:18 +02:00
|
|
|
|
2008-09-11 16:01:10 +02:00
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* Functions in indexes may want a snapshot set. Also, setting a snapshot
|
|
|
|
* ensures that RecentGlobalXmin is kept truly recent.
|
2008-09-11 16:01:10 +02:00
|
|
|
*/
|
|
|
|
PushActiveSnapshot(GetTransactionSnapshot());
|
|
|
|
|
2009-11-16 22:32:07 +01:00
|
|
|
if (!(vacstmt->options & VACOPT_FULL))
|
2006-07-30 04:07:18 +02:00
|
|
|
{
|
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* In lazy vacuum, we can set the PROC_IN_VACUUM flag, which lets
|
|
|
|
* other concurrent VACUUMs know that they can ignore this one while
|
2007-11-15 22:14:46 +01:00
|
|
|
* determining their OldestXmin. (The reason we don't set it during a
|
2010-02-08 05:33:55 +01:00
|
|
|
* full VACUUM is exactly that we may have to run user-defined
|
2007-11-15 22:14:46 +01:00
|
|
|
* functions for functional indexes, and we want to make sure that if
|
|
|
|
* they use the snapshot set above, any tuples it requires can't get
|
|
|
|
* removed from other tables. An index function that depends on the
|
|
|
|
* contents of other tables is arguably broken, but we won't break it
|
|
|
|
* here by violating transaction semantics.)
|
2006-07-30 04:07:18 +02:00
|
|
|
*
|
2009-06-11 16:49:15 +02:00
|
|
|
* We also set the VACUUM_FOR_WRAPAROUND flag, which is passed down by
|
2011-06-29 08:26:14 +02:00
|
|
|
* autovacuum; it's used to avoid canceling a vacuum that was invoked
|
2009-06-11 16:49:15 +02:00
|
|
|
* in an emergency.
|
2008-03-14 18:25:59 +01:00
|
|
|
*
|
2008-08-13 02:07:50 +02:00
|
|
|
* Note: these flags remain set until CommitTransaction or
|
|
|
|
* AbortTransaction. We don't want to clear them until we reset
|
2006-07-30 04:07:18 +02:00
|
|
|
* MyProc->xid/xmin, else OldestXmin might appear to go backwards,
|
|
|
|
* which is probably Not Good.
|
|
|
|
*/
|
2007-10-24 22:55:36 +02:00
|
|
|
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
|
2011-11-25 14:02:10 +01:00
|
|
|
MyPgXact->vacuumFlags |= PROC_IN_VACUUM;
|
2008-03-14 18:25:59 +01:00
|
|
|
if (for_wraparound)
|
2011-11-25 14:02:10 +01:00
|
|
|
MyPgXact->vacuumFlags |= PROC_VACUUM_FOR_WRAPAROUND;
|
2007-10-24 22:55:36 +02:00
|
|
|
LWLockRelease(ProcArrayLock);
|
2006-07-30 04:07:18 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-11-28 03:10:01 +01:00
|
|
|
/*
|
2000-01-20 21:01:25 +01:00
|
|
|
* Check for user-requested abort. Note we want this to be inside a
|
2002-03-06 07:10:59 +01:00
|
|
|
* transaction, so xact.c doesn't issue useless WARNING.
|
1999-11-28 03:10:01 +01:00
|
|
|
*/
|
2001-01-14 06:08:17 +01:00
|
|
|
CHECK_FOR_INTERRUPTS();
|
1999-11-28 03:10:01 +01:00
|
|
|
|
1999-09-18 21:08:25 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Determine the type of lock we want --- hard exclusive lock for a FULL
|
2005-11-22 19:17:34 +01:00
|
|
|
* vacuum, but just ShareUpdateExclusiveLock for concurrent vacuum. Either
|
|
|
|
* way, we can be sure that no other backend is vacuuming the same table.
|
2001-07-12 06:11:13 +02:00
|
|
|
*/
|
2009-11-16 22:32:07 +01:00
|
|
|
lmode = (vacstmt->options & VACOPT_FULL) ? AccessExclusiveLock : ShareUpdateExclusiveLock;
|
2001-07-12 06:11:13 +02:00
|
|
|
|
|
|
|
/*
|
2006-08-18 18:09:13 +02:00
|
|
|
* Open the relation and get the appropriate lock on it.
|
|
|
|
*
|
2006-10-04 02:30:14 +02:00
|
|
|
* There's a race condition here: the rel may have gone away since the
|
|
|
|
* last time we saw it. If so, we don't need to vacuum it.
|
2011-02-08 04:04:29 +01:00
|
|
|
*
|
2011-04-10 17:42:00 +02:00
|
|
|
* If we've been asked not to wait for the relation lock, acquire it first
|
|
|
|
* in non-blocking mode, before calling try_relation_open().
|
2006-08-18 18:09:13 +02:00
|
|
|
*/
|
2011-02-08 04:04:29 +01:00
|
|
|
if (!(vacstmt->options & VACOPT_NOWAIT))
|
|
|
|
onerel = try_relation_open(relid, lmode);
|
|
|
|
else if (ConditionalLockRelationOid(relid, lmode))
|
|
|
|
onerel = try_relation_open(relid, NoLock);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
onerel = NULL;
|
|
|
|
if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
|
|
|
|
ereport(LOG,
|
|
|
|
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
|
2011-04-10 17:42:00 +02:00
|
|
|
errmsg("skipping vacuum of \"%s\" --- lock not available",
|
|
|
|
vacstmt->relation->relname)));
|
2011-02-08 04:04:29 +01:00
|
|
|
}
|
2006-08-18 18:09:13 +02:00
|
|
|
|
|
|
|
if (!onerel)
|
|
|
|
{
|
2008-09-11 16:01:10 +02:00
|
|
|
PopActiveSnapshot();
|
2006-08-18 18:09:13 +02:00
|
|
|
CommitTransactionCommand();
|
2011-02-08 04:04:29 +01:00
|
|
|
return false;
|
2006-08-18 18:09:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check permissions.
|
1999-11-29 05:43:15 +01:00
|
|
|
*
|
2005-11-22 19:17:34 +01:00
|
|
|
* We allow the user to vacuum a table if he is superuser, the table
|
|
|
|
* owner, or the database owner (but in the latter case, only if it's not
|
|
|
|
* a shared relation). pg_class_ownercheck includes the superuser case.
|
2001-06-13 23:44:41 +02:00
|
|
|
*
|
2005-11-22 19:17:34 +01:00
|
|
|
* Note we choose to treat permissions failure as a WARNING and keep
|
|
|
|
* trying to vacuum the rest of the DB --- is this appropriate?
|
1999-09-18 21:08:25 +02:00
|
|
|
*/
|
2002-03-22 00:27:25 +01:00
|
|
|
if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) ||
|
2003-06-27 16:45:32 +02:00
|
|
|
(pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared)))
|
1999-11-29 05:43:15 +01:00
|
|
|
{
|
2008-02-20 15:31:35 +01:00
|
|
|
if (onerel->rd_rel->relisshared)
|
|
|
|
ereport(WARNING,
|
2009-06-11 16:49:15 +02:00
|
|
|
(errmsg("skipping \"%s\" --- only superuser can vacuum it",
|
|
|
|
RelationGetRelationName(onerel))));
|
2008-02-20 15:31:35 +01:00
|
|
|
else if (onerel->rd_rel->relnamespace == PG_CATALOG_NAMESPACE)
|
|
|
|
ereport(WARNING,
|
|
|
|
(errmsg("skipping \"%s\" --- only superuser or database owner can vacuum it",
|
|
|
|
RelationGetRelationName(onerel))));
|
|
|
|
else
|
|
|
|
ereport(WARNING,
|
|
|
|
(errmsg("skipping \"%s\" --- only table or database owner can vacuum it",
|
|
|
|
RelationGetRelationName(onerel))));
|
2002-04-02 03:03:07 +02:00
|
|
|
relation_close(onerel, lmode);
|
2008-09-11 16:01:10 +02:00
|
|
|
PopActiveSnapshot();
|
2003-05-14 05:26:03 +02:00
|
|
|
CommitTransactionCommand();
|
2011-02-08 04:04:29 +01:00
|
|
|
return false;
|
2002-04-02 03:03:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* Check that it's a vacuumable table; we used to do this in
|
|
|
|
* get_rel_oids() but seems safer to check after we've locked the
|
|
|
|
* relation.
|
2002-04-02 03:03:07 +02:00
|
|
|
*/
|
2008-08-13 02:07:50 +02:00
|
|
|
if (onerel->rd_rel->relkind != RELKIND_RELATION &&
|
|
|
|
onerel->rd_rel->relkind != RELKIND_TOASTVALUE)
|
2002-04-02 03:03:07 +02:00
|
|
|
{
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(WARNING,
|
2011-01-02 13:26:10 +01:00
|
|
|
(errmsg("skipping \"%s\" --- cannot vacuum non-tables or special system tables",
|
2003-07-20 23:56:35 +02:00
|
|
|
RelationGetRelationName(onerel))));
|
2002-04-02 03:03:07 +02:00
|
|
|
relation_close(onerel, lmode);
|
2008-09-11 16:01:10 +02:00
|
|
|
PopActiveSnapshot();
|
2003-05-14 05:26:03 +02:00
|
|
|
CommitTransactionCommand();
|
2011-02-08 04:04:29 +01:00
|
|
|
return false;
|
1999-11-29 05:43:15 +01:00
|
|
|
}
|
|
|
|
|
2002-09-23 22:43:41 +02:00
|
|
|
/*
|
|
|
|
* Silently ignore tables that are temp tables of other backends ---
|
|
|
|
* trying to vacuum these will lead to great unhappiness, since their
|
|
|
|
* contents are probably not up-to-date on disk. (We don't throw a
|
|
|
|
* warning here; it would just lead to chatter during a database-wide
|
|
|
|
* VACUUM.)
|
|
|
|
*/
|
2009-04-01 00:12:48 +02:00
|
|
|
if (RELATION_IS_OTHER_TEMP(onerel))
|
2002-09-23 22:43:41 +02:00
|
|
|
{
|
|
|
|
relation_close(onerel, lmode);
|
2008-09-11 16:01:10 +02:00
|
|
|
PopActiveSnapshot();
|
2003-05-14 05:26:03 +02:00
|
|
|
CommitTransactionCommand();
|
2011-02-08 04:04:29 +01:00
|
|
|
return false;
|
2002-09-23 22:43:41 +02:00
|
|
|
}
|
|
|
|
|
2000-09-19 21:30:03 +02:00
|
|
|
/*
|
2001-07-12 06:11:13 +02:00
|
|
|
* Get a session-level lock too. This will protect our access to the
|
|
|
|
* relation across multiple transactions, so that we can vacuum the
|
2005-10-15 04:49:52 +02:00
|
|
|
* relation's TOAST table (if any) secure in the knowledge that no one is
|
|
|
|
* deleting the parent relation.
|
2000-12-22 01:51:54 +01:00
|
|
|
*
|
|
|
|
* NOTE: this cannot block, even if someone else is waiting for access,
|
|
|
|
* because the lock manager knows that both lock requests are from the
|
|
|
|
* same process.
|
|
|
|
*/
|
|
|
|
onerelid = onerel->rd_lockInfo.lockRelId;
|
2006-07-31 22:09:10 +02:00
|
|
|
LockRelationIdForSession(&onerelid, lmode);
|
2000-12-22 01:51:54 +01:00
|
|
|
|
2004-10-07 16:19:58 +02:00
|
|
|
/*
|
2008-08-13 02:07:50 +02:00
|
|
|
* Remember the relation's TOAST relation for later, if the caller asked
|
2010-02-08 17:50:21 +01:00
|
|
|
* us to process it. In VACUUM FULL, though, the toast table is
|
|
|
|
* automatically rebuilt by cluster_rel so we shouldn't recurse to it.
|
2004-10-07 16:19:58 +02:00
|
|
|
*/
|
2010-02-08 17:50:21 +01:00
|
|
|
if (do_toast && !(vacstmt->options & VACOPT_FULL))
|
2008-08-13 02:07:50 +02:00
|
|
|
toast_relid = onerel->rd_rel->reltoastrelid;
|
|
|
|
else
|
|
|
|
toast_relid = InvalidOid;
|
2000-09-19 21:30:03 +02:00
|
|
|
|
2008-01-03 22:23:15 +01:00
|
|
|
/*
|
2009-06-11 16:49:15 +02:00
|
|
|
* Switch to the table owner's userid, so that any index functions are run
|
Prevent indirect security attacks via changing session-local state within
an allegedly immutable index function. It was previously recognized that
we had to prevent such a function from executing SET/RESET ROLE/SESSION
AUTHORIZATION, or it could trivially obtain the privileges of the session
user. However, since there is in general no privilege checking for changes
of session-local state, it is also possible for such a function to change
settings in a way that might subvert later operations in the same session.
Examples include changing search_path to cause an unexpected function to
be called, or replacing an existing prepared statement with another one
that will execute a function of the attacker's choosing.
The present patch secures VACUUM, ANALYZE, and CREATE INDEX/REINDEX against
these threats, which are the same places previously deemed to need protection
against the SET ROLE issue. GUC changes are still allowed, since there are
many useful cases for that, but we prevent security problems by forcing a
rollback of any GUC change after completing the operation. Other cases are
handled by throwing an error if any change is attempted; these include temp
table creation, closing a cursor, and creating or deleting a prepared
statement. (In 7.4, the infrastructure to roll back GUC changes doesn't
exist, so we settle for rejecting changes of "search_path" in these contexts.)
Original report and patch by Gurjeet Singh, additional analysis by
Tom Lane.
Security: CVE-2009-4136
2009-12-09 22:57:51 +01:00
|
|
|
* as that user. Also lock down security-restricted operations and
|
2010-02-26 03:01:40 +01:00
|
|
|
* arrange to make GUC variable changes local to this command. (This is
|
|
|
|
* unnecessary, but harmless, for lazy VACUUM.)
|
2008-01-03 22:23:15 +01:00
|
|
|
*/
|
Prevent indirect security attacks via changing session-local state within
an allegedly immutable index function. It was previously recognized that
we had to prevent such a function from executing SET/RESET ROLE/SESSION
AUTHORIZATION, or it could trivially obtain the privileges of the session
user. However, since there is in general no privilege checking for changes
of session-local state, it is also possible for such a function to change
settings in a way that might subvert later operations in the same session.
Examples include changing search_path to cause an unexpected function to
be called, or replacing an existing prepared statement with another one
that will execute a function of the attacker's choosing.
The present patch secures VACUUM, ANALYZE, and CREATE INDEX/REINDEX against
these threats, which are the same places previously deemed to need protection
against the SET ROLE issue. GUC changes are still allowed, since there are
many useful cases for that, but we prevent security problems by forcing a
rollback of any GUC change after completing the operation. Other cases are
handled by throwing an error if any change is attempted; these include temp
table creation, closing a cursor, and creating or deleting a prepared
statement. (In 7.4, the infrastructure to roll back GUC changes doesn't
exist, so we settle for rejecting changes of "search_path" in these contexts.)
Original report and patch by Gurjeet Singh, additional analysis by
Tom Lane.
Security: CVE-2009-4136
2009-12-09 22:57:51 +01:00
|
|
|
GetUserIdAndSecContext(&save_userid, &save_sec_context);
|
|
|
|
SetUserIdAndSecContext(onerel->rd_rel->relowner,
|
|
|
|
save_sec_context | SECURITY_RESTRICTED_OPERATION);
|
|
|
|
save_nestlevel = NewGUCNestLevel();
|
2008-01-03 22:23:15 +01:00
|
|
|
|
2004-10-07 16:19:58 +02:00
|
|
|
/*
|
2010-02-08 05:33:55 +01:00
|
|
|
* Do the actual work --- either FULL or "lazy" vacuum
|
2004-10-07 16:19:58 +02:00
|
|
|
*/
|
2010-02-08 05:33:55 +01:00
|
|
|
if (vacstmt->options & VACOPT_FULL)
|
2010-01-06 06:31:14 +01:00
|
|
|
{
|
2010-02-08 05:33:55 +01:00
|
|
|
/* close relation before vacuuming, but hold lock until commit */
|
2010-01-06 06:31:14 +01:00
|
|
|
relation_close(onerel, NoLock);
|
|
|
|
onerel = NULL;
|
|
|
|
|
2010-02-08 05:33:55 +01:00
|
|
|
/* VACUUM FULL is now a variant of CLUSTER; see cluster.c */
|
2010-01-06 06:31:14 +01:00
|
|
|
cluster_rel(relid, InvalidOid, false,
|
2010-02-07 21:48:13 +01:00
|
|
|
(vacstmt->options & VACOPT_VERBOSE) != 0,
|
|
|
|
vacstmt->freeze_min_age, vacstmt->freeze_table_age);
|
2010-01-06 06:31:14 +01:00
|
|
|
}
|
2010-02-08 05:33:55 +01:00
|
|
|
else
|
Fix VACUUM so that it always updates pg_class.reltuples/relpages.
When we added the ability for vacuum to skip heap pages by consulting the
visibility map, we made it just not update the reltuples/relpages
statistics if it skipped any pages. But this could leave us with extremely
out-of-date stats for a table that contains any unchanging areas,
especially for TOAST tables which never get processed by ANALYZE. In
particular this could result in autovacuum making poor decisions about when
to process the table, as in recent report from Florian Helmberger. And in
general it's a bad idea to not update the stats at all. Instead, use the
previous values of reltuples/relpages as an estimate of the tuple density
in unvisited pages. This approach results in a "moving average" estimate
of reltuples, which should converge to the correct value over multiple
VACUUM and ANALYZE cycles even when individual measurements aren't very
good.
This new method for updating reltuples is used by both VACUUM and ANALYZE,
with the result that we no longer need the grotty interconnections that
caused ANALYZE to not update the stats depending on what had happened
in the parent VACUUM command.
Also, fix the logic for skipping all-visible pages during VACUUM so that it
looks ahead rather than behind to decide what to do, as per a suggestion
from Greg Stark. This eliminates useless scanning of all-visible pages at
the start of the relation or just after a not-all-visible page. In
particular, the first few pages of the relation will not be invariably
included in the scanned pages, which seems to help in not overweighting
them in the reltuples estimate.
Back-patch to 8.4, where the visibility map was introduced.
2011-05-30 23:05:26 +02:00
|
|
|
lazy_vacuum_rel(onerel, vacstmt, vac_strategy);
|
2006-08-18 18:09:13 +02:00
|
|
|
|
Prevent indirect security attacks via changing session-local state within
an allegedly immutable index function. It was previously recognized that
we had to prevent such a function from executing SET/RESET ROLE/SESSION
AUTHORIZATION, or it could trivially obtain the privileges of the session
user. However, since there is in general no privilege checking for changes
of session-local state, it is also possible for such a function to change
settings in a way that might subvert later operations in the same session.
Examples include changing search_path to cause an unexpected function to
be called, or replacing an existing prepared statement with another one
that will execute a function of the attacker's choosing.
The present patch secures VACUUM, ANALYZE, and CREATE INDEX/REINDEX against
these threats, which are the same places previously deemed to need protection
against the SET ROLE issue. GUC changes are still allowed, since there are
many useful cases for that, but we prevent security problems by forcing a
rollback of any GUC change after completing the operation. Other cases are
handled by throwing an error if any change is attempted; these include temp
table creation, closing a cursor, and creating or deleting a prepared
statement. (In 7.4, the infrastructure to roll back GUC changes doesn't
exist, so we settle for rejecting changes of "search_path" in these contexts.)
Original report and patch by Gurjeet Singh, additional analysis by
Tom Lane.
Security: CVE-2009-4136
2009-12-09 22:57:51 +01:00
|
|
|
/* Roll back any GUC changes executed by index functions */
|
|
|
|
AtEOXact_GUC(false, save_nestlevel);
|
|
|
|
|
|
|
|
/* Restore userid and security context */
|
|
|
|
SetUserIdAndSecContext(save_userid, save_sec_context);
|
2008-01-03 22:23:15 +01:00
|
|
|
|
2001-07-12 06:11:13 +02:00
|
|
|
/* all done with this class, but hold lock until commit */
|
2010-01-06 06:31:14 +01:00
|
|
|
if (onerel)
|
|
|
|
relation_close(onerel, NoLock);
|
2001-07-12 06:11:13 +02:00
|
|
|
|
2004-10-07 16:19:58 +02:00
|
|
|
/*
|
|
|
|
* Complete the transaction and free all temporary memory used.
|
|
|
|
*/
|
2008-09-11 16:01:10 +02:00
|
|
|
PopActiveSnapshot();
|
2003-05-14 05:26:03 +02:00
|
|
|
CommitTransactionCommand();
|
2001-07-12 06:11:13 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the relation has a secondary toast rel, vacuum that too while we
|
|
|
|
* still hold the session lock on the master table. Note however that
|
2005-10-15 04:49:52 +02:00
|
|
|
* "analyze" will not get done on the toast table. This is good, because
|
|
|
|
* the toaster always uses hardcoded index access and statistics are
|
|
|
|
* totally unimportant for toast relations.
|
2001-07-12 06:11:13 +02:00
|
|
|
*/
|
|
|
|
if (toast_relid != InvalidOid)
|
Fix VACUUM so that it always updates pg_class.reltuples/relpages.
When we added the ability for vacuum to skip heap pages by consulting the
visibility map, we made it just not update the reltuples/relpages
statistics if it skipped any pages. But this could leave us with extremely
out-of-date stats for a table that contains any unchanging areas,
especially for TOAST tables which never get processed by ANALYZE. In
particular this could result in autovacuum making poor decisions about when
to process the table, as in recent report from Florian Helmberger. And in
general it's a bad idea to not update the stats at all. Instead, use the
previous values of reltuples/relpages as an estimate of the tuple density
in unvisited pages. This approach results in a "moving average" estimate
of reltuples, which should converge to the correct value over multiple
VACUUM and ANALYZE cycles even when individual measurements aren't very
good.
This new method for updating reltuples is used by both VACUUM and ANALYZE,
with the result that we no longer need the grotty interconnections that
caused ANALYZE to not update the stats depending on what had happened
in the parent VACUUM command.
Also, fix the logic for skipping all-visible pages during VACUUM so that it
looks ahead rather than behind to decide what to do, as per a suggestion
from Greg Stark. This eliminates useless scanning of all-visible pages at
the start of the relation or just after a not-all-visible page. In
particular, the first few pages of the relation will not be invariably
included in the scanned pages, which seems to help in not overweighting
them in the reltuples estimate.
Back-patch to 8.4, where the visibility map was introduced.
2011-05-30 23:05:26 +02:00
|
|
|
vacuum_rel(toast_relid, vacstmt, false, for_wraparound);
|
2001-07-12 06:11:13 +02:00
|
|
|
|
2004-10-07 16:19:58 +02:00
|
|
|
/*
|
|
|
|
* Now release the session-level lock on the master table.
|
|
|
|
*/
|
2006-07-31 22:09:10 +02:00
|
|
|
UnlockRelationIdForSession(&onerelid, lmode);
|
2011-02-08 04:04:29 +01:00
|
|
|
|
|
|
|
/* Report that we really did it. */
|
|
|
|
return true;
|
2001-07-12 06:11:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2010-02-08 05:33:55 +01:00
|
|
|
* Open all the indexes of the given relation, obtaining the specified kind
|
|
|
|
* of lock on each. Return an array of Relation pointers for the indexes
|
|
|
|
* into *Irel, and the number of indexes into *nindexes.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2010-02-08 05:33:55 +01:00
|
|
|
void
|
|
|
|
vac_open_indexes(Relation relation, LOCKMODE lockmode,
|
|
|
|
int *nindexes, Relation **Irel)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2010-02-08 05:33:55 +01:00
|
|
|
List *indexoidlist;
|
|
|
|
ListCell *indexoidscan;
|
|
|
|
int i;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2010-02-08 05:33:55 +01:00
|
|
|
Assert(lockmode != NoLock);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2010-02-08 05:33:55 +01:00
|
|
|
indexoidlist = RelationGetIndexList(relation);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2010-02-08 05:33:55 +01:00
|
|
|
*nindexes = list_length(indexoidlist);
|
2004-06-08 15:59:36 +02:00
|
|
|
|
2010-02-08 05:33:55 +01:00
|
|
|
if (*nindexes > 0)
|
|
|
|
*Irel = (Relation *) palloc(*nindexes * sizeof(Relation));
|
2001-06-29 22:14:27 +02:00
|
|
|
else
|
2010-02-08 05:33:55 +01:00
|
|
|
*Irel = NULL;
|
1996-10-18 10:13:36 +02:00
|
|
|
|
2010-02-08 05:33:55 +01:00
|
|
|
i = 0;
|
|
|
|
foreach(indexoidscan, indexoidlist)
|
1999-03-28 22:32:42 +02:00
|
|
|
{
|
2010-02-08 05:33:55 +01:00
|
|
|
Oid indexoid = lfirst_oid(indexoidscan);
|
|
|
|
|
|
|
|
(*Irel)[i++] = index_open(indexoid, lockmode);
|
1999-03-28 22:32:42 +02:00
|
|
|
}
|
|
|
|
|
2010-02-08 05:33:55 +01:00
|
|
|
list_free(indexoidlist);
|
2000-05-29 03:46:00 +02:00
|
|
|
}
|
1996-11-27 08:27:20 +01:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2010-02-08 05:33:55 +01:00
|
|
|
* Release the resources acquired by vac_open_indexes. Optionally release
|
|
|
|
* the locks (say NoLock to keep 'em).
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2010-02-08 05:33:55 +01:00
|
|
|
void
|
|
|
|
vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2010-02-08 05:33:55 +01:00
|
|
|
if (Irel == NULL)
|
|
|
|
return;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2010-02-08 05:33:55 +01:00
|
|
|
while (nindexes--)
|
1996-11-27 08:27:20 +01:00
|
|
|
{
|
2010-02-08 05:33:55 +01:00
|
|
|
Relation ind = Irel[nindexes];
|
2004-10-01 01:21:26 +02:00
|
|
|
|
2006-07-31 22:09:10 +02:00
|
|
|
index_close(ind, lockmode);
|
2004-10-01 01:21:26 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
pfree(Irel);
|
2000-05-29 03:46:00 +02:00
|
|
|
}
|
1996-11-27 08:27:20 +01:00
|
|
|
|
2004-02-10 04:42:45 +01:00
|
|
|
/*
|
|
|
|
* vacuum_delay_point --- check for interrupts and cost-based delay.
|
|
|
|
*
|
|
|
|
* This should be called in each major loop of VACUUM processing,
|
|
|
|
* typically once per page processed.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
vacuum_delay_point(void)
|
|
|
|
{
|
|
|
|
/* Always check for interrupts */
|
|
|
|
CHECK_FOR_INTERRUPTS();
|
|
|
|
|
|
|
|
/* Nap if appropriate */
|
|
|
|
if (VacuumCostActive && !InterruptPending &&
|
|
|
|
VacuumCostBalance >= VacuumCostLimit)
|
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
int msec;
|
2004-02-10 04:42:45 +01:00
|
|
|
|
2004-08-06 06:15:09 +02:00
|
|
|
msec = VacuumCostDelay * VacuumCostBalance / VacuumCostLimit;
|
|
|
|
if (msec > VacuumCostDelay * 4)
|
|
|
|
msec = VacuumCostDelay * 4;
|
2004-02-10 04:42:45 +01:00
|
|
|
|
|
|
|
pg_usleep(msec * 1000L);
|
|
|
|
|
|
|
|
VacuumCostBalance = 0;
|
|
|
|
|
2007-04-16 20:30:04 +02:00
|
|
|
/* update balance values for workers */
|
|
|
|
AutoVacuumUpdateDelay();
|
|
|
|
|
2004-02-10 04:42:45 +01:00
|
|
|
/* Might have gotten an interrupt while sleeping */
|
|
|
|
CHECK_FOR_INTERRUPTS();
|
|
|
|
}
|
|
|
|
}
|