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.
This commit is contained in:
parent
90cbc63fd1
commit
3b0347b36e
@ -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
|
|||||||
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);
|
|||||||
*
|
*
|
||||||
* 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);
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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,
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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 @@
|
|||||||
#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)
|
|||||||
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)
|
|||||||
/* 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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
* 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,
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
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 @@
|
|||||||
* 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,7 +20,8 @@
|
|||||||
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);
|
||||||
|
@ -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,
|
|||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user