1 /*-------------------------------------------------------------------------
4 * The postgres vacuum cleaner.
6 * This file now includes only control and dispatch code for VACUUM and
7 * ANALYZE commands. Regular VACUUM is implemented in vacuumlazy.c,
8 * ANALYZE in analyze.c, and VACUUM FULL is a variant of CLUSTER, handled
12 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
13 * Portions Copyright (c) 1994, Regents of the University of California
17 * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.409 2010/02/15 16:10:34 alvherre Exp $
19 *-------------------------------------------------------------------------
23 #include "access/clog.h"
24 #include "access/genam.h"
25 #include "access/heapam.h"
26 #include "access/transam.h"
27 #include "access/xact.h"
28 #include "catalog/namespace.h"
29 #include "catalog/pg_database.h"
30 #include "catalog/pg_namespace.h"
31 #include "commands/cluster.h"
32 #include "commands/vacuum.h"
33 #include "miscadmin.h"
35 #include "postmaster/autovacuum.h"
36 #include "storage/bufmgr.h"
37 #include "storage/lmgr.h"
38 #include "storage/proc.h"
39 #include "storage/procarray.h"
40 #include "utils/acl.h"
41 #include "utils/fmgroids.h"
42 #include "utils/guc.h"
43 #include "utils/memutils.h"
44 #include "utils/snapmgr.h"
45 #include "utils/syscache.h"
46 #include "utils/tqual.h"
52 int vacuum_freeze_min_age;
53 int vacuum_freeze_table_age;
56 /* A few variables that don't seem worth passing around as parameters */
57 static MemoryContext vac_context = NULL;
58 static BufferAccessStrategy vac_strategy;
61 /* non-export function prototypes */
62 static List *get_rel_oids(Oid relid, const RangeVar *vacrel,
63 const char *stmttype);
64 static void vac_truncate_clog(TransactionId frozenXID);
65 static void vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast,
66 bool for_wraparound, bool *scanned_all);
70 * Primary entry point for VACUUM and ANALYZE commands.
72 * relid is normally InvalidOid; if it is not, then it provides the relation
73 * OID to be processed, and vacstmt->relation is ignored. (The non-invalid
74 * case is currently only used by autovacuum.)
76 * do_toast is passed as FALSE by autovacuum, because it processes TOAST
79 * for_wraparound is used by autovacuum to let us know when it's forcing
80 * a vacuum for wraparound, which should not be auto-cancelled.
82 * bstrategy is normally given as NULL, but in autovacuum it can be passed
83 * in to use the same buffer strategy object across multiple vacuum() calls.
85 * isTopLevel should be passed down from ProcessUtility.
87 * It is the caller's responsibility that vacstmt and bstrategy
88 * (if given) be allocated in a memory context that won't disappear
89 * at transaction commit.
92 vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
93 BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel)
96 volatile bool all_rels,
101 /* sanity checks on options */
102 Assert(vacstmt->options & (VACOPT_VACUUM | VACOPT_ANALYZE));
103 Assert((vacstmt->options & VACOPT_VACUUM) ||
104 !(vacstmt->options & (VACOPT_FULL | VACOPT_FREEZE)));
105 Assert((vacstmt->options & VACOPT_ANALYZE) || vacstmt->va_cols == NIL);
107 stmttype = (vacstmt->options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE";
110 * We cannot run VACUUM inside a user transaction block; if we were inside
111 * a transaction, then our commit- and start-transaction-command calls
112 * would not have the intended effect! There are numerous other subtle
113 * dependencies on this, too.
115 * ANALYZE (without VACUUM) can run either way.
117 if (vacstmt->options & VACOPT_VACUUM)
119 PreventTransactionChain(isTopLevel, stmttype);
120 in_outer_xact = false;
123 in_outer_xact = IsInTransactionChain(isTopLevel);
126 * Send info about dead objects to the statistics collector, unless we are
127 * in autovacuum --- autovacuum.c does this for itself.
129 if ((vacstmt->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
130 pgstat_vacuum_stat();
133 * Create special memory context for cross-transaction storage.
135 * Since it is a child of PortalContext, it will go away eventually even
136 * if we suffer an error; there's no need for special abort cleanup logic.
138 vac_context = AllocSetContextCreate(PortalContext,
140 ALLOCSET_DEFAULT_MINSIZE,
141 ALLOCSET_DEFAULT_INITSIZE,
142 ALLOCSET_DEFAULT_MAXSIZE);
145 * If caller didn't give us a buffer strategy object, make one in the
146 * cross-transaction memory context.
148 if (bstrategy == NULL)
150 MemoryContext old_context = MemoryContextSwitchTo(vac_context);
152 bstrategy = GetAccessStrategy(BAS_VACUUM);
153 MemoryContextSwitchTo(old_context);
155 vac_strategy = bstrategy;
157 /* Remember whether we are processing everything in the DB */
158 all_rels = (!OidIsValid(relid) && vacstmt->relation == NULL);
161 * Build list of relations to process, unless caller gave us one. (If we
162 * build one, we put it in vac_context for safekeeping.)
164 relations = get_rel_oids(relid, vacstmt->relation, stmttype);
167 * Decide whether we need to start/commit our own transactions.
169 * For VACUUM (with or without ANALYZE): always do so, so that we can
170 * release locks as soon as possible. (We could possibly use the outer
171 * transaction for a one-table VACUUM, but handling TOAST tables would be
174 * For ANALYZE (no VACUUM): if inside a transaction block, we cannot
175 * start/commit our own transactions. Also, there's no need to do so if
176 * only processing one relation. For multiple relations when not within a
177 * transaction block, and also in an autovacuum worker, use own
178 * transactions so we can release locks sooner.
180 if (vacstmt->options & VACOPT_VACUUM)
181 use_own_xacts = true;
184 Assert(vacstmt->options & VACOPT_ANALYZE);
185 if (IsAutoVacuumWorkerProcess())
186 use_own_xacts = true;
187 else if (in_outer_xact)
188 use_own_xacts = false;
189 else if (list_length(relations) > 1)
190 use_own_xacts = true;
192 use_own_xacts = false;
196 * vacuum_rel expects to be entered with no transaction active; it will
197 * start and commit its own transaction. But we are called by an SQL
198 * command, and so we are executing inside a transaction already. We
199 * commit the transaction started in PostgresMain() here, and start
200 * another one before exiting to match the commit waiting for us back in
205 /* ActiveSnapshot is not set by autovacuum */
206 if (ActiveSnapshotSet())
209 /* matches the StartTransaction in PostgresMain() */
210 CommitTransactionCommand();
213 /* Turn vacuum cost accounting on or off */
218 VacuumCostActive = (VacuumCostDelay > 0);
219 VacuumCostBalance = 0;
222 * Loop to process each selected relation.
224 foreach(cur, relations)
226 Oid relid = lfirst_oid(cur);
227 bool scanned_all = false;
229 if (vacstmt->options & VACOPT_VACUUM)
230 vacuum_rel(relid, vacstmt, do_toast, for_wraparound,
233 if (vacstmt->options & VACOPT_ANALYZE)
236 * If using separate xacts, start one for analyze. Otherwise,
237 * we can use the outer transaction.
241 StartTransactionCommand();
242 /* functions in indexes may want a snapshot set */
243 PushActiveSnapshot(GetTransactionSnapshot());
246 analyze_rel(relid, vacstmt, vac_strategy, !scanned_all);
251 CommitTransactionCommand();
258 /* Make sure cost accounting is turned off after error */
259 VacuumCostActive = false;
264 /* Turn off vacuum cost accounting */
265 VacuumCostActive = false;
268 * Finish up processing.
272 /* here, we are not in a transaction */
275 * This matches the CommitTransaction waiting for us in
278 StartTransactionCommand();
281 if ((vacstmt->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
284 * Update pg_database.datfrozenxid, and truncate pg_clog if possible.
285 * (autovacuum.c does this for itself.)
287 vac_update_datfrozenxid();
291 * Clean up working storage --- note we must do this after
292 * StartTransactionCommand, else we might be trying to delete the active
295 MemoryContextDelete(vac_context);
300 * Build a list of Oids for each relation to be processed
302 * The list is built in vac_context so that it will survive across our
303 * per-relation transactions.
306 get_rel_oids(Oid relid, const RangeVar *vacrel, const char *stmttype)
308 List *oid_list = NIL;
309 MemoryContext oldcontext;
311 /* OID supplied by VACUUM's caller? */
312 if (OidIsValid(relid))
314 oldcontext = MemoryContextSwitchTo(vac_context);
315 oid_list = lappend_oid(oid_list, relid);
316 MemoryContextSwitchTo(oldcontext);
320 /* Process a specific relation */
323 relid = RangeVarGetRelid(vacrel, false);
325 /* Make a relation list entry for this guy */
326 oldcontext = MemoryContextSwitchTo(vac_context);
327 oid_list = lappend_oid(oid_list, relid);
328 MemoryContextSwitchTo(oldcontext);
332 /* Process all plain relations listed in pg_class */
339 Anum_pg_class_relkind,
340 BTEqualStrategyNumber, F_CHAREQ,
341 CharGetDatum(RELKIND_RELATION));
343 pgclass = heap_open(RelationRelationId, AccessShareLock);
345 scan = heap_beginscan(pgclass, SnapshotNow, 1, &key);
347 while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
349 /* Make a relation list entry for this guy */
350 oldcontext = MemoryContextSwitchTo(vac_context);
351 oid_list = lappend_oid(oid_list, HeapTupleGetOid(tuple));
352 MemoryContextSwitchTo(oldcontext);
356 heap_close(pgclass, AccessShareLock);
363 * vacuum_set_xid_limits() -- compute oldest-Xmin and freeze cutoff points
366 vacuum_set_xid_limits(int freeze_min_age,
367 int freeze_table_age,
369 TransactionId *oldestXmin,
370 TransactionId *freezeLimit,
371 TransactionId *freezeTableLimit)
375 TransactionId safeLimit;
378 * We can always ignore processes running lazy vacuum. This is because we
379 * use these values only for deciding which tuples we must keep in the
380 * tables. Since lazy vacuum doesn't write its XID anywhere, it's safe to
381 * ignore it. In theory it could be problematic to ignore lazy vacuums in
382 * a full vacuum, but keep in mind that only one vacuum process can be
383 * working on a particular table at any time, and that each vacuum is
384 * always an independent transaction.
386 *oldestXmin = GetOldestXmin(sharedRel, true);
388 Assert(TransactionIdIsNormal(*oldestXmin));
391 * Determine the minimum freeze age to use: as specified by the caller, or
392 * vacuum_freeze_min_age, but in any case not more than half
393 * autovacuum_freeze_max_age, so that autovacuums to prevent XID
394 * wraparound won't occur too frequently.
396 freezemin = freeze_min_age;
398 freezemin = vacuum_freeze_min_age;
399 freezemin = Min(freezemin, autovacuum_freeze_max_age / 2);
400 Assert(freezemin >= 0);
403 * Compute the cutoff XID, being careful not to generate a "permanent" XID
405 limit = *oldestXmin - freezemin;
406 if (!TransactionIdIsNormal(limit))
407 limit = FirstNormalTransactionId;
410 * If oldestXmin is very far back (in practice, more than
411 * autovacuum_freeze_max_age / 2 XIDs old), complain and force a minimum
412 * freeze age of zero.
414 safeLimit = ReadNewTransactionId() - autovacuum_freeze_max_age;
415 if (!TransactionIdIsNormal(safeLimit))
416 safeLimit = FirstNormalTransactionId;
418 if (TransactionIdPrecedes(limit, safeLimit))
421 (errmsg("oldest xmin is far in the past"),
422 errhint("Close open transactions soon to avoid wraparound problems.")));
426 *freezeLimit = limit;
428 if (freezeTableLimit != NULL)
433 * Determine the table freeze age to use: as specified by the caller,
434 * or vacuum_freeze_table_age, but in any case not more than
435 * autovacuum_freeze_max_age * 0.95, so that if you have e.g nightly
436 * VACUUM schedule, the nightly VACUUM gets a chance to freeze tuples
437 * before anti-wraparound autovacuum is launched.
439 freezetable = freeze_min_age;
441 freezetable = vacuum_freeze_table_age;
442 freezetable = Min(freezetable, autovacuum_freeze_max_age * 0.95);
443 Assert(freezetable >= 0);
446 * Compute the cutoff XID, being careful not to generate a "permanent"
449 limit = ReadNewTransactionId() - freezetable;
450 if (!TransactionIdIsNormal(limit))
451 limit = FirstNormalTransactionId;
453 *freezeTableLimit = limit;
459 * vac_update_relstats() -- update statistics for one relation
461 * Update the whole-relation statistics that are kept in its pg_class
462 * row. There are additional stats that will be updated if we are
463 * doing ANALYZE, but we always update these stats. This routine works
464 * for both index and heap relation entries in pg_class.
466 * We violate transaction semantics here by overwriting the rel's
467 * existing pg_class tuple with the new values. This is reasonably
468 * safe since the new values are correct whether or not this transaction
469 * commits. The reason for this is that if we updated these tuples in
470 * the usual way, vacuuming pg_class itself wouldn't work very well ---
471 * by the time we got done with a vacuum cycle, most of the tuples in
472 * pg_class would've been obsoleted. Of course, this only works for
473 * fixed-size never-null columns, but these are.
475 * Note another assumption: that two VACUUMs/ANALYZEs on a table can't
476 * run in parallel, nor can VACUUM/ANALYZE run in parallel with a
477 * schema alteration such as adding an index, rule, or trigger. Otherwise
478 * our updates of relhasindex etc might overwrite uncommitted updates.
480 * Another reason for doing it this way is that when we are in a lazy
481 * VACUUM and have PROC_IN_VACUUM set, we mustn't do any updates ---
482 * somebody vacuuming pg_class might think they could delete a tuple
483 * marked with xmin = our xid.
485 * This routine is shared by VACUUM and stand-alone ANALYZE.
488 vac_update_relstats(Relation relation,
489 BlockNumber num_pages, double num_tuples,
490 bool hasindex, TransactionId frozenxid)
492 Oid relid = RelationGetRelid(relation);
495 Form_pg_class pgcform;
498 rd = heap_open(RelationRelationId, RowExclusiveLock);
500 /* Fetch a copy of the tuple to scribble on */
501 ctup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
502 if (!HeapTupleIsValid(ctup))
503 elog(ERROR, "pg_class entry for relid %u vanished during vacuuming",
505 pgcform = (Form_pg_class) GETSTRUCT(ctup);
507 /* Apply required updates, if any, to copied tuple */
510 if (pgcform->relpages != (int32) num_pages)
512 pgcform->relpages = (int32) num_pages;
515 if (pgcform->reltuples != (float4) num_tuples)
517 pgcform->reltuples = (float4) num_tuples;
520 if (pgcform->relhasindex != hasindex)
522 pgcform->relhasindex = hasindex;
527 * If we have discovered that there are no indexes, then there's no
528 * primary key either, nor any exclusion constraints. This could be done
533 if (pgcform->relhaspkey)
535 pgcform->relhaspkey = false;
538 if (pgcform->relhasexclusion && pgcform->relkind != RELKIND_INDEX)
540 pgcform->relhasexclusion = false;
545 /* We also clear relhasrules and relhastriggers if needed */
546 if (pgcform->relhasrules && relation->rd_rules == NULL)
548 pgcform->relhasrules = false;
551 if (pgcform->relhastriggers && relation->trigdesc == NULL)
553 pgcform->relhastriggers = false;
558 * relfrozenxid should never go backward. Caller can pass
559 * InvalidTransactionId if it has no new data.
561 if (TransactionIdIsNormal(frozenxid) &&
562 TransactionIdPrecedes(pgcform->relfrozenxid, frozenxid))
564 pgcform->relfrozenxid = frozenxid;
568 /* If anything changed, write out the tuple. */
570 heap_inplace_update(rd, ctup);
572 heap_close(rd, RowExclusiveLock);
577 * vac_update_datfrozenxid() -- update pg_database.datfrozenxid for our DB
579 * Update pg_database's datfrozenxid entry for our database to be the
580 * minimum of the pg_class.relfrozenxid values. If we are able to
581 * advance pg_database.datfrozenxid, also try to truncate pg_clog.
583 * We violate transaction semantics here by overwriting the database's
584 * existing pg_database tuple with the new value. This is reasonably
585 * safe since the new value is correct whether or not this transaction
586 * commits. As with vac_update_relstats, this avoids leaving dead tuples
587 * behind after a VACUUM.
590 vac_update_datfrozenxid(void)
593 Form_pg_database dbform;
597 TransactionId newFrozenXid;
601 * Initialize the "min" calculation with GetOldestXmin, which is a
602 * reasonable approximation to the minimum relfrozenxid for not-yet-
603 * committed pg_class entries for new tables; see AddNewRelationTuple().
604 * Se we cannot produce a wrong minimum by starting with this.
606 newFrozenXid = GetOldestXmin(true, true);
609 * We must seqscan pg_class to find the minimum Xid, because there is no
610 * index that can help us here.
612 relation = heap_open(RelationRelationId, AccessShareLock);
614 scan = systable_beginscan(relation, InvalidOid, false,
615 SnapshotNow, 0, NULL);
617 while ((classTup = systable_getnext(scan)) != NULL)
619 Form_pg_class classForm = (Form_pg_class) GETSTRUCT(classTup);
622 * Only consider heap and TOAST tables (anything else should have
623 * InvalidTransactionId in relfrozenxid anyway.)
625 if (classForm->relkind != RELKIND_RELATION &&
626 classForm->relkind != RELKIND_TOASTVALUE)
629 Assert(TransactionIdIsNormal(classForm->relfrozenxid));
631 if (TransactionIdPrecedes(classForm->relfrozenxid, newFrozenXid))
632 newFrozenXid = classForm->relfrozenxid;
635 /* we're done with pg_class */
636 systable_endscan(scan);
637 heap_close(relation, AccessShareLock);
639 Assert(TransactionIdIsNormal(newFrozenXid));
641 /* Now fetch the pg_database tuple we need to update. */
642 relation = heap_open(DatabaseRelationId, RowExclusiveLock);
644 /* Fetch a copy of the tuple to scribble on */
645 tuple = SearchSysCacheCopy1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));
646 if (!HeapTupleIsValid(tuple))
647 elog(ERROR, "could not find tuple for database %u", MyDatabaseId);
648 dbform = (Form_pg_database) GETSTRUCT(tuple);
651 * Don't allow datfrozenxid to go backward (probably can't happen anyway);
652 * and detect the common case where it doesn't go forward either.
654 if (TransactionIdPrecedes(dbform->datfrozenxid, newFrozenXid))
656 dbform->datfrozenxid = newFrozenXid;
661 heap_inplace_update(relation, tuple);
663 heap_freetuple(tuple);
664 heap_close(relation, RowExclusiveLock);
667 * If we were able to advance datfrozenxid, see if we can truncate pg_clog.
668 * Also do it if the shared XID-wrap-limit info is stale, since this
669 * action will update that too.
671 if (dirty || ForceTransactionIdLimitUpdate())
672 vac_truncate_clog(newFrozenXid);
677 * vac_truncate_clog() -- attempt to truncate the commit log
679 * Scan pg_database to determine the system-wide oldest datfrozenxid,
680 * and use it to truncate the transaction commit log (pg_clog).
681 * Also update the XID wrap limit info maintained by varsup.c.
683 * The passed XID is simply the one I just wrote into my pg_database
684 * entry. It's used to initialize the "min" calculation.
686 * This routine is only invoked when we've managed to change our
687 * DB's datfrozenxid entry, or we found that the shared XID-wrap-limit
691 vac_truncate_clog(TransactionId frozenXID)
693 TransactionId myXID = GetCurrentTransactionId();
698 bool frozenAlreadyWrapped = false;
700 /* init oldest_datoid to sync with my frozenXID */
701 oldest_datoid = MyDatabaseId;
704 * Scan pg_database to compute the minimum datfrozenxid
706 * Note: we need not worry about a race condition with new entries being
707 * inserted by CREATE DATABASE. Any such entry will have a copy of some
708 * existing DB's datfrozenxid, and that source DB cannot be ours because
709 * of the interlock against copying a DB containing an active backend.
710 * Hence the new entry will not reduce the minimum. Also, if two VACUUMs
711 * concurrently modify the datfrozenxid's of different databases, the
712 * worst possible outcome is that pg_clog is not truncated as aggressively
715 relation = heap_open(DatabaseRelationId, AccessShareLock);
717 scan = heap_beginscan(relation, SnapshotNow, 0, NULL);
719 while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
721 Form_pg_database dbform = (Form_pg_database) GETSTRUCT(tuple);
723 Assert(TransactionIdIsNormal(dbform->datfrozenxid));
725 if (TransactionIdPrecedes(myXID, dbform->datfrozenxid))
726 frozenAlreadyWrapped = true;
727 else if (TransactionIdPrecedes(dbform->datfrozenxid, frozenXID))
729 frozenXID = dbform->datfrozenxid;
730 oldest_datoid = HeapTupleGetOid(tuple);
736 heap_close(relation, AccessShareLock);
739 * Do not truncate CLOG if we seem to have suffered wraparound already;
740 * the computed minimum XID might be bogus. This case should now be
741 * impossible due to the defenses in GetNewTransactionId, but we keep the
744 if (frozenAlreadyWrapped)
747 (errmsg("some databases have not been vacuumed in over 2 billion transactions"),
748 errdetail("You might have already suffered transaction-wraparound data loss.")));
752 /* Truncate CLOG to the oldest frozenxid */
753 TruncateCLOG(frozenXID);
756 * Update the wrap limit for GetNewTransactionId. Note: this function
757 * will also signal the postmaster for an(other) autovac cycle if needed.
759 SetTransactionIdLimit(frozenXID, oldest_datoid);
764 * vacuum_rel() -- vacuum one heap relation
766 * Doing one heap at a time incurs extra overhead, since we need to
767 * check that the heap exists again just before we vacuum it. The
768 * reason that we do this is so that vacuuming can be spread across
769 * many small transactions. Otherwise, two-phase locking would require
770 * us to lock the entire database during one pass of the vacuum cleaner.
772 * We'll return true in *scanned_all if the vacuum scanned all heap
773 * pages, and updated pg_class.
775 * At entry and exit, we are not inside a transaction.
778 vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound,
786 int save_sec_context;
790 *scanned_all = false;
792 /* Begin a transaction for vacuuming this relation */
793 StartTransactionCommand();
796 * Functions in indexes may want a snapshot set. Also, setting a snapshot
797 * ensures that RecentGlobalXmin is kept truly recent.
799 PushActiveSnapshot(GetTransactionSnapshot());
801 if (!(vacstmt->options & VACOPT_FULL))
804 * In lazy vacuum, we can set the PROC_IN_VACUUM flag, which lets
805 * other concurrent VACUUMs know that they can ignore this one while
806 * determining their OldestXmin. (The reason we don't set it during a
807 * full VACUUM is exactly that we may have to run user-defined
808 * functions for functional indexes, and we want to make sure that if
809 * they use the snapshot set above, any tuples it requires can't get
810 * removed from other tables. An index function that depends on the
811 * contents of other tables is arguably broken, but we won't break it
812 * here by violating transaction semantics.)
814 * We also set the VACUUM_FOR_WRAPAROUND flag, which is passed down by
815 * autovacuum; it's used to avoid cancelling a vacuum that was invoked
818 * Note: these flags remain set until CommitTransaction or
819 * AbortTransaction. We don't want to clear them until we reset
820 * MyProc->xid/xmin, else OldestXmin might appear to go backwards,
821 * which is probably Not Good.
823 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
824 MyProc->vacuumFlags |= PROC_IN_VACUUM;
826 MyProc->vacuumFlags |= PROC_VACUUM_FOR_WRAPAROUND;
827 LWLockRelease(ProcArrayLock);
831 * Check for user-requested abort. Note we want this to be inside a
832 * transaction, so xact.c doesn't issue useless WARNING.
834 CHECK_FOR_INTERRUPTS();
837 * Determine the type of lock we want --- hard exclusive lock for a FULL
838 * vacuum, but just ShareUpdateExclusiveLock for concurrent vacuum. Either
839 * way, we can be sure that no other backend is vacuuming the same table.
841 lmode = (vacstmt->options & VACOPT_FULL) ? AccessExclusiveLock : ShareUpdateExclusiveLock;
844 * Open the relation and get the appropriate lock on it.
846 * There's a race condition here: the rel may have gone away since the
847 * last time we saw it. If so, we don't need to vacuum it.
849 onerel = try_relation_open(relid, lmode);
854 CommitTransactionCommand();
861 * We allow the user to vacuum a table if he is superuser, the table
862 * owner, or the database owner (but in the latter case, only if it's not
863 * a shared relation). pg_class_ownercheck includes the superuser case.
865 * Note we choose to treat permissions failure as a WARNING and keep
866 * trying to vacuum the rest of the DB --- is this appropriate?
868 if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) ||
869 (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared)))
871 if (onerel->rd_rel->relisshared)
873 (errmsg("skipping \"%s\" --- only superuser can vacuum it",
874 RelationGetRelationName(onerel))));
875 else if (onerel->rd_rel->relnamespace == PG_CATALOG_NAMESPACE)
877 (errmsg("skipping \"%s\" --- only superuser or database owner can vacuum it",
878 RelationGetRelationName(onerel))));
881 (errmsg("skipping \"%s\" --- only table or database owner can vacuum it",
882 RelationGetRelationName(onerel))));
883 relation_close(onerel, lmode);
885 CommitTransactionCommand();
890 * Check that it's a vacuumable table; we used to do this in
891 * get_rel_oids() but seems safer to check after we've locked the
894 if (onerel->rd_rel->relkind != RELKIND_RELATION &&
895 onerel->rd_rel->relkind != RELKIND_TOASTVALUE)
898 (errmsg("skipping \"%s\" --- cannot vacuum indexes, views, or special system tables",
899 RelationGetRelationName(onerel))));
900 relation_close(onerel, lmode);
902 CommitTransactionCommand();
907 * Silently ignore tables that are temp tables of other backends ---
908 * trying to vacuum these will lead to great unhappiness, since their
909 * contents are probably not up-to-date on disk. (We don't throw a
910 * warning here; it would just lead to chatter during a database-wide
913 if (RELATION_IS_OTHER_TEMP(onerel))
915 relation_close(onerel, lmode);
917 CommitTransactionCommand();
922 * Get a session-level lock too. This will protect our access to the
923 * relation across multiple transactions, so that we can vacuum the
924 * relation's TOAST table (if any) secure in the knowledge that no one is
925 * deleting the parent relation.
927 * NOTE: this cannot block, even if someone else is waiting for access,
928 * because the lock manager knows that both lock requests are from the
931 onerelid = onerel->rd_lockInfo.lockRelId;
932 LockRelationIdForSession(&onerelid, lmode);
935 * Remember the relation's TOAST relation for later, if the caller asked
936 * us to process it. In VACUUM FULL, though, the toast table is
937 * automatically rebuilt by cluster_rel so we shouldn't recurse to it.
939 if (do_toast && !(vacstmt->options & VACOPT_FULL))
940 toast_relid = onerel->rd_rel->reltoastrelid;
942 toast_relid = InvalidOid;
945 * Switch to the table owner's userid, so that any index functions are run
946 * as that user. Also lock down security-restricted operations and
947 * arrange to make GUC variable changes local to this command.
948 * (This is unnecessary, but harmless, for lazy VACUUM.)
950 GetUserIdAndSecContext(&save_userid, &save_sec_context);
951 SetUserIdAndSecContext(onerel->rd_rel->relowner,
952 save_sec_context | SECURITY_RESTRICTED_OPERATION);
953 save_nestlevel = NewGUCNestLevel();
956 * Do the actual work --- either FULL or "lazy" vacuum
958 if (vacstmt->options & VACOPT_FULL)
960 /* close relation before vacuuming, but hold lock until commit */
961 relation_close(onerel, NoLock);
964 /* VACUUM FULL is now a variant of CLUSTER; see cluster.c */
965 cluster_rel(relid, InvalidOid, false,
966 (vacstmt->options & VACOPT_VERBOSE) != 0,
967 vacstmt->freeze_min_age, vacstmt->freeze_table_age);
970 lazy_vacuum_rel(onerel, vacstmt, vac_strategy, scanned_all);
972 /* Roll back any GUC changes executed by index functions */
973 AtEOXact_GUC(false, save_nestlevel);
975 /* Restore userid and security context */
976 SetUserIdAndSecContext(save_userid, save_sec_context);
978 /* all done with this class, but hold lock until commit */
980 relation_close(onerel, NoLock);
983 * Complete the transaction and free all temporary memory used.
986 CommitTransactionCommand();
989 * If the relation has a secondary toast rel, vacuum that too while we
990 * still hold the session lock on the master table. Note however that
991 * "analyze" will not get done on the toast table. This is good, because
992 * the toaster always uses hardcoded index access and statistics are
993 * totally unimportant for toast relations.
995 if (toast_relid != InvalidOid)
996 vacuum_rel(toast_relid, vacstmt, false, for_wraparound, NULL);
999 * Now release the session-level lock on the master table.
1001 UnlockRelationIdForSession(&onerelid, lmode);
1006 * Open all the indexes of the given relation, obtaining the specified kind
1007 * of lock on each. Return an array of Relation pointers for the indexes
1008 * into *Irel, and the number of indexes into *nindexes.
1011 vac_open_indexes(Relation relation, LOCKMODE lockmode,
1012 int *nindexes, Relation **Irel)
1015 ListCell *indexoidscan;
1018 Assert(lockmode != NoLock);
1020 indexoidlist = RelationGetIndexList(relation);
1022 *nindexes = list_length(indexoidlist);
1025 *Irel = (Relation *) palloc(*nindexes * sizeof(Relation));
1030 foreach(indexoidscan, indexoidlist)
1032 Oid indexoid = lfirst_oid(indexoidscan);
1034 (*Irel)[i++] = index_open(indexoid, lockmode);
1037 list_free(indexoidlist);
1041 * Release the resources acquired by vac_open_indexes. Optionally release
1042 * the locks (say NoLock to keep 'em).
1045 vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode)
1052 Relation ind = Irel[nindexes];
1054 index_close(ind, lockmode);
1060 * vacuum_delay_point --- check for interrupts and cost-based delay.
1062 * This should be called in each major loop of VACUUM processing,
1063 * typically once per page processed.
1066 vacuum_delay_point(void)
1068 /* Always check for interrupts */
1069 CHECK_FOR_INTERRUPTS();
1071 /* Nap if appropriate */
1072 if (VacuumCostActive && !InterruptPending &&
1073 VacuumCostBalance >= VacuumCostLimit)
1077 msec = VacuumCostDelay * VacuumCostBalance / VacuumCostLimit;
1078 if (msec > VacuumCostDelay * 4)
1079 msec = VacuumCostDelay * 4;
1081 pg_usleep(msec * 1000L);
1083 VacuumCostBalance = 0;
1085 /* update balance values for workers */
1086 AutoVacuumUpdateDelay();
1088 /* Might have gotten an interrupt while sleeping */
1089 CHECK_FOR_INTERRUPTS();