REINDEX under WAL.

This commit is contained in:
Hiroshi Inoue 2000-12-08 06:17:58 +00:00
parent 8d7c0851a3
commit d7892e0263
5 changed files with 252 additions and 27 deletions

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.130 2000/11/16 22:30:17 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.131 2000/12/08 06:17:57 inoue Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -76,7 +76,7 @@ static void DefaultBuild(Relation heapRelation, Relation indexRelation,
IndexInfo *indexInfo, Node *oldPred, IndexInfo *indexInfo, Node *oldPred,
IndexStrategy indexStrategy); IndexStrategy indexStrategy);
static Oid IndexGetRelation(Oid indexId); static Oid IndexGetRelation(Oid indexId);
static bool activate_index(Oid indexId, bool activate); static bool activate_index(Oid indexId, bool activate, bool inplace);
static bool reindexing = false; static bool reindexing = false;
@ -1430,7 +1430,11 @@ setRelhasindex(Oid relid, bool hasindex)
*/ */
pg_class = heap_openr(RelationRelationName, RowExclusiveLock); pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
#ifdef OLD_FILE_NAMING
if (!IsIgnoringSystemIndexes()) if (!IsIgnoringSystemIndexes())
#else
if (!IsIgnoringSystemIndexes() && (!IsReindexProcessing() || pg_class->rd_rel->relhasindex))
#endif /* OLD_FILE_NAMING */
{ {
tuple = SearchSysCacheCopy(RELOID, tuple = SearchSysCacheCopy(RELOID,
ObjectIdGetDatum(relid), ObjectIdGetDatum(relid),
@ -1462,7 +1466,11 @@ setRelhasindex(Oid relid, bool hasindex)
* Update hasindex in pg_class. * Update hasindex in pg_class.
* ---------------- * ----------------
*/ */
if (pg_class_scan)
LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_EXCLUSIVE);
((Form_pg_class) GETSTRUCT(tuple))->relhasindex = hasindex; ((Form_pg_class) GETSTRUCT(tuple))->relhasindex = hasindex;
if (pg_class_scan)
LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
if (pg_class_scan) if (pg_class_scan)
{ {
@ -1471,6 +1479,7 @@ setRelhasindex(Oid relid, bool hasindex)
/* Send out shared cache inval if necessary */ /* Send out shared cache inval if necessary */
if (!IsBootstrapProcessingMode()) if (!IsBootstrapProcessingMode())
RelationInvalidateHeapTuple(pg_class, tuple); RelationInvalidateHeapTuple(pg_class, tuple);
BufferSync();
} }
else else
{ {
@ -1496,6 +1505,75 @@ setRelhasindex(Oid relid, bool hasindex)
heap_close(pg_class, RowExclusiveLock); heap_close(pg_class, RowExclusiveLock);
} }
#ifndef OLD_FILE_NAMING
void
setNewRelfilenode(Relation relation)
{
Relation pg_class, idescs[Num_pg_class_indices];
Oid newrelfilenode;
bool in_place_update = false;
HeapTupleData lockTupleData;
HeapTuple classTuple;
Buffer buffer;
RelationData workrel;
Assert(!IsSystemRelationName(NameStr(relation->rd_rel->relname)) || relation->rd_rel->relkind == RELKIND_INDEX);
pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
/* Fetch and lock the classTuple associated with this relation */
if (!LockClassinfoForUpdate(relation->rd_id, &lockTupleData, &buffer, true))
elog(ERROR, "setNewRelfilenode impossible to lock class tuple");
if (IsIgnoringSystemIndexes())
in_place_update = true;
/* Allocate a new relfilenode */
newrelfilenode = newoid();
/* update pg_class tuple with new relfilenode */
if (!in_place_update)
{
classTuple = heap_copytuple(&lockTupleData);
ReleaseBuffer(buffer);
((Form_pg_class) GETSTRUCT(classTuple))->relfilenode = newrelfilenode;
heap_update(pg_class, &classTuple->t_self, classTuple, NULL);
}
/* unlink old relfilenode */
DropRelationBuffers(relation);
smgrunlink(DEFAULT_SMGR, relation);
/* cleanup pg_internal.init if necessary */
if (relation->rd_isnailed)
unlink(RELCACHE_INIT_FILENAME);
/* create another storage file. Is it a little ugly ? */
memcpy((char *) &workrel, relation, sizeof(RelationData));
workrel.rd_node.relNode = newrelfilenode;
heap_storage_create(&workrel);
/* update pg_class tuple with new relfilenode in place */
if (in_place_update)
{
classTuple = &lockTupleData;
/* Send out shared cache inval if necessary */
if (!IsBootstrapProcessingMode())
RelationInvalidateHeapTuple(pg_class, classTuple);
/* Update the buffer in-place */
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
((Form_pg_class) GETSTRUCT(classTuple))->relfilenode = newrelfilenode;
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
WriteBuffer(buffer);
BufferSync();
}
/* Keep the catalog indices up to date */
if (!in_place_update && pg_class->rd_rel->relhasindex)
{
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices,
idescs);
CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, classTuple);
CatalogCloseIndices(Num_pg_class_indices, idescs);
heap_freetuple(classTuple);
}
heap_close(pg_class, NoLock);
/* Make sure the relfilenode change */
CommandCounterIncrement();
}
#endif /* OLD_FILE_NAMING */
/* ---------------- /* ----------------
* UpdateStats * UpdateStats
* ---------------- * ----------------
@ -1552,7 +1630,12 @@ UpdateStats(Oid relid, long reltuples)
*/ */
pg_class = heap_openr(RelationRelationName, RowExclusiveLock); pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
#ifdef OLD_FILE_NAMING
in_place_upd = (IsReindexProcessing() || IsBootstrapProcessingMode()); in_place_upd = (IsReindexProcessing() || IsBootstrapProcessingMode());
#else
in_place_upd = (IsIgnoringSystemIndexes() || (IsReindexProcessing() &&
relid == RelOid_pg_class));
#endif /* OLD_FILE_NAMING */
if (!in_place_upd) if (!in_place_upd)
{ {
@ -1631,8 +1714,10 @@ UpdateStats(Oid relid, long reltuples)
* visibility of changes, so we cheat. Also cheat if REINDEX. * visibility of changes, so we cheat. Also cheat if REINDEX.
*/ */
rd_rel = (Form_pg_class) GETSTRUCT(tuple); rd_rel = (Form_pg_class) GETSTRUCT(tuple);
LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_EXCLUSIVE);
rd_rel->relpages = relpages; rd_rel->relpages = relpages;
rd_rel->reltuples = reltuples; rd_rel->reltuples = reltuples;
LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
WriteNoReleaseBuffer(pg_class_scan->rs_cbuf); WriteNoReleaseBuffer(pg_class_scan->rs_cbuf);
if (!IsBootstrapProcessingMode()) if (!IsBootstrapProcessingMode())
RelationInvalidateHeapTuple(pg_class, tuple); RelationInvalidateHeapTuple(pg_class, tuple);
@ -1924,11 +2009,11 @@ IndexGetRelation(Oid indexId)
* --------------------------------- * ---------------------------------
*/ */
static bool static bool
activate_index(Oid indexId, bool activate) activate_index(Oid indexId, bool activate, bool inplace)
{ {
if (!activate) /* Currently does nothing */ if (!activate) /* Currently does nothing */
return true; return true;
return reindex_index(indexId, false); return reindex_index(indexId, false, inplace);
} }
/* -------------------------------- /* --------------------------------
@ -1936,7 +2021,7 @@ activate_index(Oid indexId, bool activate)
* -------------------------------- * --------------------------------
*/ */
bool bool
reindex_index(Oid indexId, bool force) reindex_index(Oid indexId, bool force, bool inplace)
{ {
Relation iRel, Relation iRel,
indexRelation, indexRelation,
@ -1996,9 +2081,15 @@ reindex_index(Oid indexId, bool force)
if (iRel == NULL) if (iRel == NULL)
elog(ERROR, "reindex_index: can't open index relation"); elog(ERROR, "reindex_index: can't open index relation");
#ifndef OLD_FILE_NAMING
if (!inplace)
setNewRelfilenode(iRel);
#endif /* OLD_FILE_NAMING */
/* Obtain exclusive lock on it, just to be sure */ /* Obtain exclusive lock on it, just to be sure */
LockRelation(iRel, AccessExclusiveLock); LockRelation(iRel, AccessExclusiveLock);
if (inplace)
{
/* /*
* Release any buffers associated with this index. If they're dirty, * Release any buffers associated with this index. If they're dirty,
* they're just dropped without bothering to flush to disk. * they're just dropped without bothering to flush to disk.
@ -2008,6 +2099,7 @@ reindex_index(Oid indexId, bool force)
/* Now truncate the actual data and set blocks to zero */ /* Now truncate the actual data and set blocks to zero */
smgrtruncate(DEFAULT_SMGR, iRel, 0); smgrtruncate(DEFAULT_SMGR, iRel, 0);
iRel->rd_nblocks = 0; iRel->rd_nblocks = 0;
}
/* Initialize the index and rebuild */ /* Initialize the index and rebuild */
InitIndexStrategy(indexInfo->ii_NumIndexAttrs, iRel, accessMethodId); InitIndexStrategy(indexInfo->ii_NumIndexAttrs, iRel, accessMethodId);
@ -2064,8 +2156,48 @@ reindex_relation(Oid relid, bool force)
bool old, bool old,
reindexed; reindexed;
bool deactivate_needed, overwrite, upd_pg_class_inplace;
#ifdef OLD_FILE_NAMING
overwrite = upd_pg_class_inplace = deactivate_needed = true;
#else
Relation rel;
overwrite = upd_pg_class_inplace = deactivate_needed = false;
/*
* avoid heap_update() pg_class tuples while processing
* reindex for pg_class.
*/
if (IsIgnoringSystemIndexes())
upd_pg_class_inplace = true;
/*
* ignore the indexes of the target system relation while processing
* reindex.
*/
rel = RelationIdGetRelation(relid);
if (!IsIgnoringSystemIndexes() && IsSystemRelationName(NameStr(rel->rd_rel->relname)))
deactivate_needed = true;
#ifndef ENABLE_REINDEX_NAILED_RELATIONS
/*
* nailed relations are never updated.
* We couldn't keep the consistency between the relation
* descriptors and pg_class tuples.
*/
if (rel->rd_isnailed)
{
if (IsIgnoringSystemIndexes())
{
overwrite = true;
deactivate_needed = true;
}
else
elog(ERROR, "the target relation %u is nailed", relid);
}
#endif /* ENABLE_REINDEX_NAILED_RELATIONS */
RelationClose(rel);
#endif /* OLD_FILE_NAMING */
old = SetReindexProcessing(true); old = SetReindexProcessing(true);
if (IndexesAreActive(relid, true)) if (deactivate_needed)
{
if (IndexesAreActive(relid, upd_pg_class_inplace))
{ {
if (!force) if (!force)
{ {
@ -2073,6 +2205,8 @@ reindex_relation(Oid relid, bool force)
return false; return false;
} }
activate_indexes_of_a_table(relid, false); activate_indexes_of_a_table(relid, false);
CommandCounterIncrement();
}
} }
indexRelation = heap_openr(IndexRelationName, AccessShareLock); indexRelation = heap_openr(IndexRelationName, AccessShareLock);
@ -2085,7 +2219,7 @@ reindex_relation(Oid relid, bool force)
{ {
Form_pg_index index = (Form_pg_index) GETSTRUCT(indexTuple); Form_pg_index index = (Form_pg_index) GETSTRUCT(indexTuple);
if (activate_index(index->indexrelid, true)) if (activate_index(index->indexrelid, true, overwrite))
reindexed = true; reindexed = true;
else else
{ {
@ -2096,7 +2230,30 @@ reindex_relation(Oid relid, bool force)
heap_endscan(scan); heap_endscan(scan);
heap_close(indexRelation, AccessShareLock); heap_close(indexRelation, AccessShareLock);
if (reindexed) if (reindexed)
/*
* Ok,we could use the reindexed indexes of the target
* system relation now.
*/
{
if (deactivate_needed)
{
if (!overwrite && relid == RelOid_pg_class)
{
/*
* For pg_class, relhasindex should be set
* to true here in place.
*/
setRelhasindex(relid, true); setRelhasindex(relid, true);
CommandCounterIncrement();
/*
* However the following setRelhasindex()
* is needed to keep consistency with WAL.
*/
}
setRelhasindex(relid, true);
}
}
SetReindexProcessing(old); SetReindexProcessing(old);
return reindexed; return reindexed;
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.41 2000/11/16 22:30:18 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.42 2000/12/08 06:17:58 inoue Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -653,7 +653,11 @@ ReindexIndex(const char *name, bool force /* currently unused */ )
elog(ERROR, "relation \"%s\" is of type \"%c\"", elog(ERROR, "relation \"%s\" is of type \"%c\"",
name, ((Form_pg_class) GETSTRUCT(tuple))->relkind); name, ((Form_pg_class) GETSTRUCT(tuple))->relkind);
if (!reindex_index(tuple->t_data->t_oid, force)) #ifdef OLD_FILE_NAMING
if (!reindex_index(tuple->t_data->t_oid, force, false))
#else
if (!reindex_index(tuple->t_data->t_oid, force, false))
#endif /* OLD_FILE_NAMING */
elog(NOTICE, "index \"%s\" wasn't reindexed", name); elog(NOTICE, "index \"%s\" wasn't reindexed", name);
ReleaseSysCache(tuple); ReleaseSysCache(tuple);

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.103 2000/11/16 22:30:30 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.104 2000/12/08 06:17:58 inoue Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -866,6 +866,7 @@ ProcessUtility(Node *parsetree,
relname = (char *) stmt->name; relname = (char *) stmt->name;
if (IsSystemRelationName(relname)) if (IsSystemRelationName(relname))
{ {
#ifdef OLD_FILE_NAMING
if (!allowSystemTableMods && IsSystemRelationName(relname)) if (!allowSystemTableMods && IsSystemRelationName(relname))
elog(ERROR, "\"%s\" is a system table. call REINDEX under standalone postgres with -O -P options", elog(ERROR, "\"%s\" is a system table. call REINDEX under standalone postgres with -O -P options",
relname); relname);
@ -873,6 +874,7 @@ ProcessUtility(Node *parsetree,
elog(ERROR, "\"%s\" is a system table. call REINDEX under standalone postgres with -P -O options", elog(ERROR, "\"%s\" is a system table. call REINDEX under standalone postgres with -P -O options",
relname); relname);
#endif /* OLD_FILE_NAMING */
} }
if (!pg_ownercheck(GetUserId(), relname, RELNAME)) if (!pg_ownercheck(GetUserId(), relname, RELNAME))
elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]); elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.118 2000/11/30 18:38:46 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.119 2000/12/08 06:17:56 inoue Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -250,6 +250,10 @@ do { \
/* non-export function prototypes */ /* non-export function prototypes */
static void RelationClearRelation(Relation relation, bool rebuildIt); static void RelationClearRelation(Relation relation, bool rebuildIt);
#ifdef ENABLE_REINDEX_NAILED_RELATIONS
static void RelationReloadClassinfo(Relation relation);
#endif /* ENABLE_REINDEX_NAILED_RELATIONS */
static void RelationResetRelation(Relation relation, bool rebuildIt);
static void RelationFlushRelation(Relation *relationPtr, static void RelationFlushRelation(Relation *relationPtr,
int skipLocalRelations); int skipLocalRelations);
static Relation RelationNameCacheGetRelation(const char *relationName); static Relation RelationNameCacheGetRelation(const char *relationName);
@ -387,6 +391,15 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo)
HeapTuple return_tuple; HeapTuple return_tuple;
pg_class_desc = heap_openr(RelationRelationName, AccessShareLock); pg_class_desc = heap_openr(RelationRelationName, AccessShareLock);
/*
* If the indexes of pg_class are deactivated
* we have to call scan_pg_rel_seq() instead.
*/
if (!pg_class_desc->rd_rel->relhasindex)
{
heap_close(pg_class_desc, AccessShareLock);
return scan_pg_rel_seq(buildinfo);
}
switch (buildinfo.infotype) switch (buildinfo.infotype)
{ {
@ -1555,6 +1568,45 @@ RelationClose(Relation relation)
RelationDecrementReferenceCount(relation); RelationDecrementReferenceCount(relation);
} }
#ifdef ENABLE_REINDEX_NAILED_RELATIONS
/* --------------------------------
* RelationReloadClassinfo
*
* This function is especially for nailed relations.
* relhasindex/relfilenode could be changed even for
* nailed relations.
* --------------------------------
*/
static void
RelationReloadClassinfo(Relation relation)
{
RelationBuildDescInfo buildinfo;
HeapTuple pg_class_tuple;
Form_pg_class relp;
if (!relation->rd_rel)
return;
buildinfo.infotype = INFO_RELID;
buildinfo.i.info_id = relation->rd_id;
pg_class_tuple = ScanPgRelation(buildinfo);
if (!HeapTupleIsValid(pg_class_tuple))
{
elog(ERROR, "RelationReloadClassinfo system relation id=%d doesn't exist", relation->rd_id);
return;
}
RelationCacheDelete(relation);
relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
relation->rd_node.relNode = relp->relfilenode;
RelationCacheInsert(relation);
heap_freetuple(pg_class_tuple);
fprintf(stderr, "RelationClearRelation nailed %s hasindex=%d relfilenode=%d,%d\n",
RelationGetRelationName(relation), relation->rd_rel->relhasindex,
relation->rd_rel->relfilenode, relation->rd_node.relNode);
return;
}
#endif /* ENABLE_REINDEX_NAILED_RELATIONS */
/* -------------------------------- /* --------------------------------
* RelationClearRelation * RelationClearRelation
* *
@ -1588,7 +1640,14 @@ RelationClearRelation(Relation relation, bool rebuildIt)
* we'd be unable to recover. * we'd be unable to recover.
*/ */
if (relation->rd_isnailed) if (relation->rd_isnailed)
#ifdef ENABLE_REINDEX_NAILED_RELATIONS
{
RelationReloadClassinfo(relation);
#endif /* ENABLE_REINDEX_NAILED_RELATIONS */
return; return;
#ifdef ENABLE_REINDEX_NAILED_RELATIONS
}
#endif /* ENABLE_REINDEX_NAILED_RELATIONS */
/* /*
* Remove relation from hash tables * Remove relation from hash tables

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: index.h,v 1.30 2000/11/08 22:10:01 tgl Exp $ * $Id: index.h,v 1.31 2000/12/08 06:17:56 inoue Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -49,13 +49,16 @@ extern void FormIndexDatum(IndexInfo *indexInfo,
extern void UpdateStats(Oid relid, long reltuples); extern void UpdateStats(Oid relid, long reltuples);
extern bool IndexesAreActive(Oid relid, bool comfirmCommitted); extern bool IndexesAreActive(Oid relid, bool comfirmCommitted);
extern void setRelhasindex(Oid relid, bool hasindex); extern void setRelhasindex(Oid relid, bool hasindex);
#ifndef OLD_FILE_NAMING
extern void setNewRelfilenode(Relation relation);
#endif /* OLD_FILE_NAMING */
extern bool SetReindexProcessing(bool processing); extern bool SetReindexProcessing(bool processing);
extern bool IsReindexProcessing(void); extern bool IsReindexProcessing(void);
extern void index_build(Relation heapRelation, Relation indexRelation, extern void index_build(Relation heapRelation, Relation indexRelation,
IndexInfo *indexInfo, Node *oldPred); IndexInfo *indexInfo, Node *oldPred);
extern bool reindex_index(Oid indexId, bool force); extern bool reindex_index(Oid indexId, bool force, bool inplace);
extern bool activate_indexes_of_a_table(Oid relid, bool activate); extern bool activate_indexes_of_a_table(Oid relid, bool activate);
extern bool reindex_relation(Oid relid, bool force); extern bool reindex_relation(Oid relid, bool force);