Re: reldesc does not exit

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: "Darrin Ladd" <dladd(at)newfoundcomm(dot)net>
Cc: "PGSQL General" <pgsql-general(at)postgresql(dot)org>
Subject: Re: reldesc does not exit
Date: 2000-09-30 18:57:04
Message-ID: 6542.970340224@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

I wrote:
> "Darrin Ladd" <dladd(at)newfoundcomm(dot)net> writes:
>> Uh oh, yes, I do get the same notice when truncating other tables, even
>> tables not in the same database :(

> OK, so it's not so data-dependent after all. Sounds like it's probably
> a flat-out bug associated with 64-bit-int machines.

No, I was guessing wrong. Turns out it's a fundamental bug in TRUNCATE
that could show up on any machine, depending on chance behavior of
memory allocation, with consequences up to and including backend
coredump. (TRUNCATE on a table with indexes would fail unless closing and
re-opening the relcache entry recreated the relcache entry at exactly
the same memory address it had before :-(.)

Apparently the RedHat LinuxAlpha distro is somewhat more likely than
other platforms to move things around in memory, for reasons not
immediately obvious; else we'd have seen this sooner on other machines.

I have fixed this for 7.0.3, due out soon. If you need a fix now
the patch against 7.0.2 is attached.

regards, tom lane

*** heap.c.orig Thu May 25 17:25:32 2000
--- heap.c Sat Sep 30 14:41:51 2000
***************
*** 1091,1134 ****
* RelationTruncateIndexes - This routine is used to truncate all
* indices associated with the heap relation to zero tuples.
* The routine will truncate and then reconstruct the indices on
! * the relation specified by the heapRelation parameter.
* --------------------------------
*/
static void
! RelationTruncateIndexes(Relation heapRelation)
{
! Relation indexRelation,
! currentIndex;
ScanKeyData entry;
HeapScanDesc scan;
! HeapTuple indexTuple,
! procTuple,
! classTuple;
! Form_pg_index index;
! Oid heapId,
! indexId,
! procId,
! accessMethodId;
! Node *oldPred = NULL;
! PredInfo *predInfo;
! List *cnfPred = NULL;
! AttrNumber *attributeNumberA;
! FuncIndexInfo fInfo,
! *funcInfo = NULL;
! int i,
! numberOfAttributes;
! char *predString;
!
! heapId = RelationGetRelid(heapRelation);
!
! /* Scan pg_index to find indexes on heapRelation */

indexRelation = heap_openr(IndexRelationName, AccessShareLock);
ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid, F_OIDEQ,
ObjectIdGetDatum(heapId));
scan = heap_beginscan(indexRelation, false, SnapshotNow, 1, &entry);
while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0)))
{

/*
* For each index, fetch index attributes so we can apply
--- 1091,1132 ----
* RelationTruncateIndexes - This routine is used to truncate all
* indices associated with the heap relation to zero tuples.
* The routine will truncate and then reconstruct the indices on
! * the relation specified by the heapId parameter.
* --------------------------------
*/
static void
! RelationTruncateIndexes(Oid heapId)
{
! Relation indexRelation;
ScanKeyData entry;
HeapScanDesc scan;
! HeapTuple indexTuple;

+ /* Scan pg_index to find indexes on specified heap */
indexRelation = heap_openr(IndexRelationName, AccessShareLock);
ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid, F_OIDEQ,
ObjectIdGetDatum(heapId));
scan = heap_beginscan(indexRelation, false, SnapshotNow, 1, &entry);
+
while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0)))
{
+ Relation heapRelation,
+ currentIndex;
+ HeapTuple procTuple,
+ classTuple;
+ Form_pg_index index;
+ Oid indexId,
+ procId,
+ accessMethodId;
+ Node *oldPred = NULL;
+ PredInfo *predInfo;
+ List *cnfPred = NULL;
+ AttrNumber *attributeNumberA;
+ FuncIndexInfo fInfo,
+ *funcInfo = NULL;
+ int i,
+ numberOfAttributes;
+ char *predString;

/*
* For each index, fetch index attributes so we can apply
***************
*** 1183,1192 ****
elog(ERROR, "RelationTruncateIndexes: index access method not found");
accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam;

/* Open our index relation */
currentIndex = index_open(indexId);
- if (currentIndex == NULL)
- elog(ERROR, "RelationTruncateIndexes: can't open index relation");

/* Obtain exclusive lock on it, just to be sure */
LockRelation(currentIndex, AccessExclusiveLock);
--- 1181,1197 ----
elog(ERROR, "RelationTruncateIndexes: index access method not found");
accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam;

+ /*
+ * We have to re-open the heap rel each time through this loop
+ * because index_build will close it again. We need grab no lock,
+ * however, because we assume heap_truncate is holding an exclusive
+ * lock on the heap rel.
+ */
+ heapRelation = heap_open(heapId, NoLock);
+ Assert(heapRelation != NULL);
+
/* Open our index relation */
currentIndex = index_open(indexId);

/* Obtain exclusive lock on it, just to be sure */
LockRelation(currentIndex, AccessExclusiveLock);
***************
*** 1205,1220 ****
InitIndexStrategy(numberOfAttributes, currentIndex, accessMethodId);
index_build(heapRelation, currentIndex, numberOfAttributes,
attributeNumberA, 0, NULL, funcInfo, predInfo);
-
/*
* index_build will close both the heap and index relations (but
! * not give up the locks we hold on them). That's fine for the
! * index, but we need to open the heap again. We need no new
! * lock, since this backend still has the exclusive lock grabbed
! * by heap_truncate.
*/
- heapRelation = heap_open(heapId, NoLock);
- Assert(heapRelation != NULL);
}

/* Complete the scan and close pg_index */
--- 1210,1219 ----
InitIndexStrategy(numberOfAttributes, currentIndex, accessMethodId);
index_build(heapRelation, currentIndex, numberOfAttributes,
attributeNumberA, 0, NULL, funcInfo, predInfo);
/*
* index_build will close both the heap and index relations (but
! * not give up the locks we hold on them).
*/
}

/* Complete the scan and close pg_index */
***************
*** 1270,1286 ****
rel->rd_nblocks = 0;

/* If this relation has indexes, truncate the indexes too */
! RelationTruncateIndexes(rel);

/*
* Close the relation, but keep exclusive lock on it until commit.
*/
heap_close(rel, NoLock);
-
- /*
- * Is this really necessary?
- */
- RelationForgetRelation(rid);
}


--- 1269,1280 ----
rel->rd_nblocks = 0;

/* If this relation has indexes, truncate the indexes too */
! RelationTruncateIndexes(rid);

/*
* Close the relation, but keep exclusive lock on it until commit.
*/
heap_close(rel, NoLock);
}

In response to

Browse pgsql-general by date

  From Date Subject
Next Message Philip Warner 2000-10-01 00:45:29 Re: Checking number of entries
Previous Message Stephan Szabo 2000-09-30 18:25:03 Re: Checking number of entries