aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/heap/heapam.c
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2011-07-08 22:19:30 -0400
committerRobert Haas <rhaas@postgresql.org>2011-07-08 22:19:30 -0400
commit4240e429d0c2d889d0cda23c618f94e12c13ade7 (patch)
tree306e1fac6085c29b55287f383ce8831d947e1312 /src/backend/access/heap/heapam.c
parent9d522cb35d8b4f266abadd0d019f68eb8802ae05 (diff)
downloadpostgresql-4240e429d0c2d889d0cda23c618f94e12c13ade7.tar.gz
postgresql-4240e429d0c2d889d0cda23c618f94e12c13ade7.zip
Try to acquire relation locks in RangeVarGetRelid.
In the previous coding, we would look up a relation in RangeVarGetRelid, lock the resulting OID, and then AcceptInvalidationMessages(). While this was sufficient to ensure that we noticed any changes to the relation definition before building the relcache entry, it didn't handle the possibility that the name we looked up no longer referenced the same OID. This was particularly problematic in the case where a table had been dropped and recreated: we'd latch on to the entry for the old relation and fail later on. Now, we acquire the relation lock inside RangeVarGetRelid, and retry the name lookup if we notice that invalidation messages have been processed meanwhile. Many operations that would previously have failed with an error in the presence of concurrent DDL will now succeed. There is a good deal of work remaining to be done here: many callers of RangeVarGetRelid still pass NoLock for one reason or another. In addition, nothing in this patch guards against the possibility that the meaning of an unqualified name might change due to the creation of a relation in a schema earlier in the user's search path than the one where it was previously found. Furthermore, there's nothing at all here to guard against similar race conditions for non-relations. For all that, it's a start. Noah Misch and Robert Haas
Diffstat (limited to 'src/backend/access/heap/heapam.c')
-rw-r--r--src/backend/access/heap/heapam.c42
1 files changed, 6 insertions, 36 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index c9b1d5fd04c..9f1bcf1de4a 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -975,26 +975,11 @@ relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
{
Oid relOid;
- /*
- * Check for shared-cache-inval messages before trying to open the
- * relation. This is needed to cover the case where the name identifies a
- * rel that has been dropped and recreated since the start of our
- * transaction: if we don't flush the old syscache entry then we'll latch
- * onto that entry and suffer an error when we do RelationIdGetRelation.
- * Note that relation_open does not need to do this, since a relation's
- * OID never changes.
- *
- * We skip this if asked for NoLock, on the assumption that the caller has
- * already ensured some appropriate lock is held.
- */
- if (lockmode != NoLock)
- AcceptInvalidationMessages();
-
- /* Look up the appropriate relation using namespace search */
- relOid = RangeVarGetRelid(relation, false);
+ /* Look up and lock the appropriate relation using namespace search */
+ relOid = RangeVarGetRelid(relation, lockmode, false, false);
/* Let relation_open do the rest */
- return relation_open(relOid, lockmode);
+ return relation_open(relOid, NoLock);
}
/* ----------------
@@ -1012,30 +997,15 @@ relation_openrv_extended(const RangeVar *relation, LOCKMODE lockmode,
{
Oid relOid;
- /*
- * Check for shared-cache-inval messages before trying to open the
- * relation. This is needed to cover the case where the name identifies a
- * rel that has been dropped and recreated since the start of our
- * transaction: if we don't flush the old syscache entry then we'll latch
- * onto that entry and suffer an error when we do RelationIdGetRelation.
- * Note that relation_open does not need to do this, since a relation's
- * OID never changes.
- *
- * We skip this if asked for NoLock, on the assumption that the caller has
- * already ensured some appropriate lock is held.
- */
- if (lockmode != NoLock)
- AcceptInvalidationMessages();
-
- /* Look up the appropriate relation using namespace search */
- relOid = RangeVarGetRelid(relation, missing_ok);
+ /* Look up and lock the appropriate relation using namespace search */
+ relOid = RangeVarGetRelid(relation, lockmode, missing_ok, false);
/* Return NULL on not-found */
if (!OidIsValid(relOid))
return NULL;
/* Let relation_open do the rest */
- return relation_open(relOid, lockmode);
+ return relation_open(relOid, NoLock);
}
/* ----------------