提交 3b0347b3 编写于 作者: A Alvaro Herrera

Move the tuple freezing point in CLUSTER to a point further back in the past,

to avoid losing useful Xid information in not-so-old tuples.  This makes
CLUSTER behave the same as VACUUM as far a tuple-freezing behavior goes
(though CLUSTER does not yet advance the table's relfrozenxid).

While at it, move the actual freezing operation in rewriteheap.c to a more
appropriate place, and document it thoroughly.  This part of the patch from
Tom Lane.
上级 90cbc63f
...@@ -96,7 +96,7 @@ ...@@ -96,7 +96,7 @@
* Portions Copyright (c) 1994-5, Regents of the University of California * Portions Copyright (c) 1994-5, Regents of the University of California
* *
* IDENTIFICATION * 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 ...@@ -123,6 +123,8 @@ typedef struct RewriteStateData
bool rs_use_wal; /* must we WAL-log inserts? */ bool rs_use_wal; /* must we WAL-log inserts? */
TransactionId rs_oldest_xmin; /* oldest xmin used by caller to TransactionId rs_oldest_xmin; /* oldest xmin used by caller to
* determine tuple visibility */ * 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 MemoryContext rs_cxt; /* for hash tables and entries and
* tuples in them */ * tuples in them */
HTAB *rs_unresolved_tups; /* unmatched A tuples */ HTAB *rs_unresolved_tups; /* unmatched A tuples */
...@@ -171,6 +173,7 @@ static void raw_heap_insert(RewriteState state, HeapTuple tup); ...@@ -171,6 +173,7 @@ static void raw_heap_insert(RewriteState state, HeapTuple tup);
* *
* new_heap new, locked heap relation to insert tuples to * new_heap new, locked heap relation to insert tuples to
* oldest_xmin xid used by the caller to determine which tuples are dead * 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? * use_wal should the inserts to the new heap be WAL-logged?
* *
* Returns an opaque RewriteState, allocated in current memory context, * Returns an opaque RewriteState, allocated in current memory context,
...@@ -178,7 +181,7 @@ static void raw_heap_insert(RewriteState state, HeapTuple tup); ...@@ -178,7 +181,7 @@ static void raw_heap_insert(RewriteState state, HeapTuple tup);
*/ */
RewriteState RewriteState
begin_heap_rewrite(Relation new_heap, TransactionId oldest_xmin, begin_heap_rewrite(Relation new_heap, TransactionId oldest_xmin,
bool use_wal) TransactionId freeze_xid, bool use_wal)
{ {
RewriteState state; RewriteState state;
MemoryContext rw_cxt; MemoryContext rw_cxt;
...@@ -206,6 +209,7 @@ begin_heap_rewrite(Relation new_heap, TransactionId oldest_xmin, ...@@ -206,6 +209,7 @@ begin_heap_rewrite(Relation new_heap, TransactionId oldest_xmin,
state->rs_buffer_valid = false; state->rs_buffer_valid = false;
state->rs_use_wal = use_wal; state->rs_use_wal = use_wal;
state->rs_oldest_xmin = oldest_xmin; state->rs_oldest_xmin = oldest_xmin;
state->rs_freeze_xid = freeze_xid;
state->rs_cxt = rw_cxt; state->rs_cxt = rw_cxt;
/* Initialize hash tables used to track update chains */ /* Initialize hash tables used to track update chains */
...@@ -292,7 +296,9 @@ end_heap_rewrite(RewriteState state) ...@@ -292,7 +296,9 @@ end_heap_rewrite(RewriteState state)
/* /*
* Add a tuple to the new heap. * 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 * state opaque state as returned by begin_heap_rewrite
* old_tuple original tuple in the old heap * old_tuple original tuple in the old heap
...@@ -323,6 +329,17 @@ rewrite_heap_tuple(RewriteState state, ...@@ -323,6 +329,17 @@ rewrite_heap_tuple(RewriteState state,
new_tuple->t_data->t_infomask |= new_tuple->t_data->t_infomask |=
old_tuple->t_data->t_infomask & HEAP_XACT_MASK; 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. * 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. * 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) ...@@ -538,8 +555,6 @@ raw_heap_insert(RewriteState state, HeapTuple tup)
OffsetNumber newoff; OffsetNumber newoff;
HeapTuple heaptup; 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 * If the new tuple is too big for storage or contains already toasted
* out-of-line attributes from some other relation, invoke the toaster. * out-of-line attributes from some other relation, invoke the toaster.
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -29,6 +29,7 @@
#include "catalog/namespace.h" #include "catalog/namespace.h"
#include "catalog/toasting.h" #include "catalog/toasting.h"
#include "commands/cluster.h" #include "commands/cluster.h"
#include "commands/vacuum.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "storage/procarray.h" #include "storage/procarray.h"
#include "utils/acl.h" #include "utils/acl.h"
...@@ -657,6 +658,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex) ...@@ -657,6 +658,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
HeapTuple tuple; HeapTuple tuple;
bool use_wal; bool use_wal;
TransactionId OldestXmin; TransactionId OldestXmin;
TransactionId FreezeXid;
RewriteState rwstate; RewriteState rwstate;
/* /*
...@@ -688,11 +690,16 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex) ...@@ -688,11 +690,16 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
/* use_wal off requires rd_targblock be initially invalid */ /* use_wal off requires rd_targblock be initially invalid */
Assert(NewHeap->rd_targblock == InvalidBlockNumber); 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 */ /* 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 * Scan through the OldHeap in OldIndex order and copy each tuple into the
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -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 * vacuum_set_xid_limits() -- compute oldest-Xmin and freeze cutoff points
*/ */
void void
vacuum_set_xid_limits(VacuumStmt *vacstmt, bool sharedRel, vacuum_set_xid_limits(int freeze_min_age, bool sharedRel,
TransactionId *oldestXmin, TransactionId *oldestXmin,
TransactionId *freezeLimit) TransactionId *freezeLimit)
{ {
...@@ -588,12 +588,12 @@ vacuum_set_xid_limits(VacuumStmt *vacstmt, bool sharedRel, ...@@ -588,12 +588,12 @@ vacuum_set_xid_limits(VacuumStmt *vacstmt, bool sharedRel,
Assert(TransactionIdIsNormal(*oldestXmin)); 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 * or vacuum_freeze_min_age, but in any case not more than half
* autovacuum_freeze_max_age, so that autovacuums to prevent XID * autovacuum_freeze_max_age, so that autovacuums to prevent XID
* wraparound won't occur too frequently. * wraparound won't occur too frequently.
*/ */
freezemin = vacstmt->freeze_min_age; freezemin = freeze_min_age;
if (freezemin < 0) if (freezemin < 0)
freezemin = vacuum_freeze_min_age; freezemin = vacuum_freeze_min_age;
freezemin = Min(freezemin, autovacuum_freeze_max_age / 2); freezemin = Min(freezemin, autovacuum_freeze_max_age / 2);
...@@ -1154,7 +1154,7 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) ...@@ -1154,7 +1154,7 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
i; i;
VRelStats *vacrelstats; 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); &OldestXmin, &FreezeLimit);
/* /*
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -158,7 +158,7 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
else else
elevel = DEBUG2; 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); &OldestXmin, &FreezeLimit);
vacrelstats = (LVRelStats *) palloc0(sizeof(LVRelStats)); vacrelstats = (LVRelStats *) palloc0(sizeof(LVRelStats));
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California * 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 @@ ...@@ -20,10 +20,11 @@
typedef struct RewriteStateData *RewriteState; typedef struct RewriteStateData *RewriteState;
extern RewriteState begin_heap_rewrite(Relation NewHeap, 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 end_heap_rewrite(RewriteState state);
extern void rewrite_heap_tuple(RewriteState state, HeapTuple oldTuple, extern void rewrite_heap_tuple(RewriteState state, HeapTuple oldTuple,
HeapTuple newTuple); HeapTuple newTuple);
extern void rewrite_heap_dead_tuple(RewriteState state, HeapTuple oldTuple); extern void rewrite_heap_dead_tuple(RewriteState state, HeapTuple oldTuple);
#endif /* REWRITE_HEAP_H */ #endif /* REWRITE_HEAP_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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, ...@@ -119,7 +119,7 @@ extern void vac_update_relstats(Oid relid,
double num_tuples, double num_tuples,
bool hasindex, bool hasindex,
TransactionId frozenxid); 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 *oldestXmin,
TransactionId *freezeLimit); TransactionId *freezeLimit);
extern void vac_update_datfrozenxid(void); extern void vac_update_datfrozenxid(void);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册