diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c index be389c647aa8460dc165e13efbef1ec39d55221a..fe8edeedae7e3527cb17eff79a2516ec1efa05cf 100644 --- a/src/backend/access/heap/rewriteheap.c +++ b/src/backend/access/heap/rewriteheap.c @@ -96,7 +96,7 @@ * Portions Copyright (c) 1994-5, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/heap/rewriteheap.c,v 1.4 2007/05/16 16:36:56 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/rewriteheap.c,v 1.5 2007/05/17 15:28:29 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -123,6 +123,8 @@ typedef struct RewriteStateData bool rs_use_wal; /* must we WAL-log inserts? */ TransactionId rs_oldest_xmin; /* oldest xmin used by caller to * determine tuple visibility */ + TransactionId rs_freeze_xid; /* Xid that will be used as freeze + * cutoff point */ MemoryContext rs_cxt; /* for hash tables and entries and * tuples in them */ HTAB *rs_unresolved_tups; /* unmatched A tuples */ @@ -171,6 +173,7 @@ static void raw_heap_insert(RewriteState state, HeapTuple tup); * * new_heap new, locked heap relation to insert tuples to * oldest_xmin xid used by the caller to determine which tuples are dead + * freeze_xid xid before which tuples will be frozen * use_wal should the inserts to the new heap be WAL-logged? * * Returns an opaque RewriteState, allocated in current memory context, @@ -178,7 +181,7 @@ static void raw_heap_insert(RewriteState state, HeapTuple tup); */ RewriteState begin_heap_rewrite(Relation new_heap, TransactionId oldest_xmin, - bool use_wal) + TransactionId freeze_xid, bool use_wal) { RewriteState state; MemoryContext rw_cxt; @@ -206,6 +209,7 @@ begin_heap_rewrite(Relation new_heap, TransactionId oldest_xmin, state->rs_buffer_valid = false; state->rs_use_wal = use_wal; state->rs_oldest_xmin = oldest_xmin; + state->rs_freeze_xid = freeze_xid; state->rs_cxt = rw_cxt; /* Initialize hash tables used to track update chains */ @@ -292,7 +296,9 @@ end_heap_rewrite(RewriteState state) /* * Add a tuple to the new heap. * - * Visibility information is copied from the original tuple. + * Visibility information is copied from the original tuple, except that + * we "freeze" very-old tuples. Note that since we scribble on new_tuple, + * it had better be temp storage not a pointer to the original tuple. * * state opaque state as returned by begin_heap_rewrite * old_tuple original tuple in the old heap @@ -323,6 +329,17 @@ rewrite_heap_tuple(RewriteState state, new_tuple->t_data->t_infomask |= old_tuple->t_data->t_infomask & HEAP_XACT_MASK; + /* + * While we have our hands on the tuple, we may as well freeze any + * very-old xmin or xmax, so that future VACUUM effort can be saved. + * + * Note we abuse heap_freeze_tuple() a bit here, since it's expecting + * to be given a pointer to a tuple in a disk buffer. It happens + * though that we can get the right things to happen by passing + * InvalidBuffer for the buffer. + */ + heap_freeze_tuple(new_tuple->t_data, state->rs_freeze_xid, InvalidBuffer); + /* * Invalid ctid means that ctid should point to the tuple itself. * We'll override it later if the tuple is part of an update chain. @@ -538,8 +555,6 @@ raw_heap_insert(RewriteState state, HeapTuple tup) OffsetNumber newoff; HeapTuple heaptup; - heap_freeze_tuple(tup->t_data, state->rs_oldest_xmin, InvalidBuffer); - /* * If the new tuple is too big for storage or contains already toasted * out-of-line attributes from some other relation, invoke the toaster. diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 656d7d710f04df45c65b7be416dd197eb7d04677..3eee46fbd0a27de62644efd3b13a519b24613f21 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.159 2007/04/08 01:26:28 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.160 2007/05/17 15:28:29 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -29,6 +29,7 @@ #include "catalog/namespace.h" #include "catalog/toasting.h" #include "commands/cluster.h" +#include "commands/vacuum.h" #include "miscadmin.h" #include "storage/procarray.h" #include "utils/acl.h" @@ -657,6 +658,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex) HeapTuple tuple; bool use_wal; TransactionId OldestXmin; + TransactionId FreezeXid; RewriteState rwstate; /* @@ -688,11 +690,16 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex) /* use_wal off requires rd_targblock be initially invalid */ Assert(NewHeap->rd_targblock == InvalidBlockNumber); - /* Get the cutoff xmin we'll use to weed out dead tuples */ - OldestXmin = GetOldestXmin(OldHeap->rd_rel->relisshared, true); + /* + * compute xids used to freeze and weed out dead tuples. We use -1 + * freeze_min_age to avoid having CLUSTER freeze tuples earlier than + * a plain VACUUM would. + */ + vacuum_set_xid_limits(-1, OldHeap->rd_rel->relisshared, + &OldestXmin, &FreezeXid); /* Initialize the rewrite operation */ - rwstate = begin_heap_rewrite(NewHeap, OldestXmin, use_wal); + rwstate = begin_heap_rewrite(NewHeap, OldestXmin, FreezeXid, use_wal); /* * Scan through the OldHeap in OldIndex order and copy each tuple into the diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index f275448756f506b6e5bcdd6c4ce43837908eb242..93885579cbb39a49e7e99937c4a24ad3ecfaa192 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.350 2007/04/16 18:29:50 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.351 2007/05/17 15:28:29 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -566,7 +566,7 @@ get_rel_oids(List *relids, const RangeVar *vacrel, const char *stmttype) * vacuum_set_xid_limits() -- compute oldest-Xmin and freeze cutoff points */ void -vacuum_set_xid_limits(VacuumStmt *vacstmt, bool sharedRel, +vacuum_set_xid_limits(int freeze_min_age, bool sharedRel, TransactionId *oldestXmin, TransactionId *freezeLimit) { @@ -588,12 +588,12 @@ vacuum_set_xid_limits(VacuumStmt *vacstmt, bool sharedRel, Assert(TransactionIdIsNormal(*oldestXmin)); /* - * Determine the minimum freeze age to use: as specified in the vacstmt, + * 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 * autovacuum_freeze_max_age, so that autovacuums to prevent XID * wraparound won't occur too frequently. */ - freezemin = vacstmt->freeze_min_age; + freezemin = freeze_min_age; if (freezemin < 0) freezemin = vacuum_freeze_min_age; freezemin = Min(freezemin, autovacuum_freeze_max_age / 2); @@ -1154,7 +1154,7 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) i; VRelStats *vacrelstats; - vacuum_set_xid_limits(vacstmt, onerel->rd_rel->relisshared, + vacuum_set_xid_limits(vacstmt->freeze_min_age, onerel->rd_rel->relisshared, &OldestXmin, &FreezeLimit); /* diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index 2b6d8a07f76b93f5700abd924f64761539ce706f..2c9a80540c39e1783c628a550fb3f1c6682c70fe 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -36,7 +36,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.88 2007/04/30 03:23:48 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.89 2007/05/17 15:28:29 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -158,7 +158,7 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) else elevel = DEBUG2; - vacuum_set_xid_limits(vacstmt, onerel->rd_rel->relisshared, + vacuum_set_xid_limits(vacstmt->freeze_min_age, onerel->rd_rel->relisshared, &OldestXmin, &FreezeLimit); vacrelstats = (LVRelStats *) palloc0(sizeof(LVRelStats)); diff --git a/src/include/access/rewriteheap.h b/src/include/access/rewriteheap.h index e8f53246a81008ea3c828e5384a8ab4f815e82b7..4f9515d566f46b5c1677ddeb4579e3ccf3a89717 100644 --- a/src/include/access/rewriteheap.h +++ b/src/include/access/rewriteheap.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994-5, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/rewriteheap.h,v 1.1 2007/04/08 01:26:33 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/rewriteheap.h,v 1.2 2007/05/17 15:28:29 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -20,10 +20,11 @@ typedef struct RewriteStateData *RewriteState; extern RewriteState begin_heap_rewrite(Relation NewHeap, - TransactionId OldestXmin, bool use_wal); + TransactionId OldestXmin, TransactionId FreezeXid, + bool use_wal); extern void end_heap_rewrite(RewriteState state); extern void rewrite_heap_tuple(RewriteState state, HeapTuple oldTuple, - HeapTuple newTuple); + HeapTuple newTuple); extern void rewrite_heap_dead_tuple(RewriteState state, HeapTuple oldTuple); #endif /* REWRITE_HEAP_H */ diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index b77fbf4c7197e77b7164450aa00dddcd951bef31..acb2f623e2729ac4f392c5390af45467b643410a 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/commands/vacuum.h,v 1.70 2007/03/13 00:33:43 tgl Exp $ + * $PostgreSQL: pgsql/src/include/commands/vacuum.h,v 1.71 2007/05/17 15:28:29 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -119,7 +119,7 @@ extern void vac_update_relstats(Oid relid, double num_tuples, bool hasindex, TransactionId frozenxid); -extern void vacuum_set_xid_limits(VacuumStmt *vacstmt, bool sharedRel, +extern void vacuum_set_xid_limits(int freeze_min_age, bool sharedRel, TransactionId *oldestXmin, TransactionId *freezeLimit); extern void vac_update_datfrozenxid(void);