Ahh ... you know what, never mind about stack traces, let's just see if
the attached patch doesn't fix it.
I still haven't reproduced the behavior here, but I think I see what
must be happening: we are getting an sinval reset while attempting to
open pg_class_oid_index. The latter condition causes its refcount to
be above 1, which will cause RelationClearRelation to directly call
RelationReloadIndexInfo, which enables the following sequence of calls:
RelationCacheInvalidate -> RelationClearRelation -> RelationReloadIndexInfo.
And the problem is that RelationCacheInvalidate intentionally forces
pg_class_oid_index to be updated first. That was okay when the code was
written, because the relcache entry for pg_class itself never really
needed any updates. Now it does, so we have to make sure pg_class gets
updated first, *then* pg_class_oid_index (which might result in a
seqscan of pg_class), then everything else (for which we'll try to use
pg_class_oid_index to locate their pg_class tuples).
regards, tom lane
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 81cea8b..0e4b17c 100644
*** a/src/backend/utils/cache/relcache.c
--- b/src/backend/utils/cache/relcache.c
*************** RelationCacheInvalidate(void)
*** 2185,2204 ****
{
/*
* Add this entry to list of stuff to rebuild in second pass.
! * pg_class_oid_index goes on the front of rebuildFirstList, other
! * nailed indexes on the back, and everything else into
! * rebuildList (in no particular order).
*/
! if (relation->rd_isnailed &&
! relation->rd_rel->relkind == RELKIND_INDEX)
{
if (RelationGetRelid(relation) == ClassOidIndexId)
- rebuildFirstList = lcons(relation, rebuildFirstList);
- else
rebuildFirstList = lappend(rebuildFirstList, relation);
}
else
! rebuildList = lcons(relation, rebuildList);
}
}
--- 2185,2207 ----
{
/*
* Add this entry to list of stuff to rebuild in second pass.
! * pg_class goes on the front of rebuildFirstList,
! * pg_class_oid_index goes to the back of rebuildFirstList, other
! * nailed indexes go on the front of rebuildList, and everything
! * else goes to the back of rebuildList.
*/
! if (RelationGetRelid(relation) == RelationRelationId)
! rebuildFirstList = lcons(relation, rebuildFirstList);
! else if (relation->rd_isnailed &&
! relation->rd_rel->relkind == RELKIND_INDEX)
{
if (RelationGetRelid(relation) == ClassOidIndexId)
rebuildFirstList = lappend(rebuildFirstList, relation);
+ else
+ rebuildList = lcons(relation, rebuildList);
}
else
! rebuildList = lappend(rebuildList, relation);
}
}
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers