* 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 $
*
*-------------------------------------------------------------------------
*/
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 */
*
* 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,
*/
RewriteState
begin_heap_rewrite(Relation new_heap, TransactionId oldest_xmin,
- bool use_wal)
+ TransactionId freeze_xid, bool use_wal)
{
RewriteState state;
MemoryContext rw_cxt;
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 */
/*
* 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
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.
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.
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
HeapTuple tuple;
bool use_wal;
TransactionId OldestXmin;
+ TransactionId FreezeXid;
RewriteState rwstate;
/*
/* 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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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)
{
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);
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);
/*
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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));
* 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 $
*
*-------------------------------------------------------------------------
*/
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 */
* 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 $
*
*-------------------------------------------------------------------------
*/
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);