diff options
Diffstat (limited to 'src/backend/commands/vacuum.c')
-rw-r--r-- | src/backend/commands/vacuum.c | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index b1f187dc47d..eb0fce72edb 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -13,7 +13,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.335 2006/07/14 14:52:18 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.336 2006/07/30 02:07:18 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -37,6 +37,7 @@ #include "postmaster/autovacuum.h" #include "storage/freespace.h" #include "storage/pmsignal.h" +#include "storage/proc.h" #include "storage/procarray.h" #include "utils/acl.h" #include "utils/builtins.h" @@ -589,7 +590,16 @@ vacuum_set_xid_limits(VacuumStmt *vacstmt, bool sharedRel, { TransactionId limit; - *oldestXmin = GetOldestXmin(sharedRel); + /* + * We can always ignore processes running lazy vacuum. This is because we + * use these values only for deciding which tuples we must keep in the + * tables. Since lazy vacuum doesn't write its xid to the table, it's + * safe to ignore it. In theory it could be problematic to ignore lazy + * vacuums on 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. + */ + *oldestXmin = GetOldestXmin(sharedRel, true); Assert(TransactionIdIsNormal(*oldestXmin)); @@ -645,6 +655,11 @@ vacuum_set_xid_limits(VacuumStmt *vacstmt, bool sharedRel, * pg_class would've been obsoleted. Of course, this only works for * fixed-size never-null columns, but these are. * + * Another reason for doing it this way is that when we are in a lazy + * VACUUM and have inVacuum set, we mustn't do any updates --- somebody + * vacuuming pg_class might think they could delete a tuple marked with + * xmin = our xid. + * * This routine is shared by full VACUUM, lazy VACUUM, and stand-alone * ANALYZE. */ @@ -996,8 +1011,35 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) /* Begin a transaction for vacuuming this relation */ StartTransactionCommand(); - /* functions in indexes may want a snapshot set */ - ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); + + if (vacstmt->full) + { + /* functions in indexes may want a snapshot set */ + ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); + } + else + { + /* + * During a lazy VACUUM we do not run any user-supplied functions, + * and so it should be safe to not create a transaction snapshot. + * + * We can furthermore set the inVacuum flag, which lets other + * concurrent VACUUMs know that they can ignore this one while + * determining their OldestXmin. (The reason we don't set inVacuum + * during a full VACUUM is exactly that we may have to run user- + * defined 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.) + * + * Note: the inVacuum flag remains set until CommitTransaction or + * AbortTransaction. We don't want to clear it until we reset + * MyProc->xid/xmin, else OldestXmin might appear to go backwards, + * which is probably Not Good. + */ + MyProc->inVacuum = true; + } /* * Tell the cache replacement strategy that vacuum is causing all |