Re: reldesc does not exit - Mailing list pgsql-general
From | Tom Lane |
---|---|
Subject | Re: reldesc does not exit |
Date | |
Msg-id | 6542.970340224@sss.pgh.pa.us Whole thread Raw |
In response to | Re: reldesc does not exit (Tom Lane <tgl@sss.pgh.pa.us>) |
List | pgsql-general |
I wrote: > "Darrin Ladd" <dladd@newfoundcomm.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); }
pgsql-general by date: