diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2010-02-09 21:43:30 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2010-02-09 21:43:30 +0000 |
commit | cbe9d6beb4ae1cb20c08cab29b534be4923b6768 (patch) | |
tree | a9476492cd8c7eda7718f95b0ad5a45d41e55a3a /src/backend/utils/cache | |
parent | 79647eed86cc972e80ea165dcb0b7f6fef876169 (diff) | |
download | postgresql-cbe9d6beb4ae1cb20c08cab29b534be4923b6768.tar.gz postgresql-cbe9d6beb4ae1cb20c08cab29b534be4923b6768.zip |
Fix up rickety handling of relation-truncation interlocks.
Move rd_targblock, rd_fsm_nblocks, and rd_vm_nblocks from relcache to the smgr
relation entries, so that they will get reset to InvalidBlockNumber whenever
an smgr-level flush happens. Because we now send smgr invalidation messages
immediately (not at end of transaction) when a relation truncation occurs,
this ensures that other backends will reset their values before they next
access the relation. We no longer need the unreliable assumption that a
VACUUM that's doing a truncation will hold its AccessExclusive lock until
commit --- in fact, we can intentionally release that lock as soon as we've
completed the truncation. This patch therefore reverts (most of) Alvaro's
patch of 2009-11-10, as well as my marginal hacking on it yesterday. We can
also get rid of assorted no-longer-needed relcache flushes, which are far more
expensive than an smgr flush because they kill a lot more state.
In passing this patch fixes smgr_redo's failure to perform visibility-map
truncation, and cleans up some rather dubious assumptions in freespace.c and
visibilitymap.c about when rd_fsm_nblocks and rd_vm_nblocks can be out of
date.
Diffstat (limited to 'src/backend/utils/cache')
-rw-r--r-- | src/backend/utils/cache/relcache.c | 39 |
1 files changed, 4 insertions, 35 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 6137b096772..0492f73e2e0 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.304 2010/02/08 05:53:55 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.305 2010/02/09 21:43:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -328,13 +328,6 @@ AllocateRelationDesc(Form_pg_class relp) */ relation = (Relation) palloc0(sizeof(RelationData)); - /* - * clear fields of reldesc that should initialize to something non-zero - */ - relation->rd_targblock = InvalidBlockNumber; - relation->rd_fsm_nblocks = InvalidBlockNumber; - relation->rd_vm_nblocks = InvalidBlockNumber; - /* make sure relation is marked as having no open file yet */ relation->rd_smgr = NULL; @@ -1413,9 +1406,6 @@ formrdesc(const char *relationName, Oid relationReltype, * allocate new relation desc, clear all fields of reldesc */ relation = (Relation) palloc0(sizeof(RelationData)); - relation->rd_targblock = InvalidBlockNumber; - relation->rd_fsm_nblocks = InvalidBlockNumber; - relation->rd_vm_nblocks = InvalidBlockNumber; /* make sure relation is marked as having no open file yet */ relation->rd_smgr = NULL; @@ -1714,14 +1704,7 @@ RelationReloadIndexInfo(Relation relation) /* Should be closed at smgr level */ Assert(relation->rd_smgr == NULL); - /* - * Must reset targblock, fsm_nblocks and vm_nblocks in case rel was - * truncated - */ - relation->rd_targblock = InvalidBlockNumber; - relation->rd_fsm_nblocks = InvalidBlockNumber; - relation->rd_vm_nblocks = InvalidBlockNumber; - /* Must free any AM cached data, too */ + /* Must free any AM cached data upon relcache flush */ if (relation->rd_amcache) pfree(relation->rd_amcache); relation->rd_amcache = NULL; @@ -1867,11 +1850,8 @@ RelationClearRelation(Relation relation, bool rebuild) /* * Never, never ever blow away a nailed-in system relation, because we'd - * be unable to recover. However, we must reset rd_targblock, in case we - * got called because of a relation cache flush that was triggered by - * VACUUM. Likewise reset the fsm and vm size info. Also, redo - * RelationInitPhysicalAddr in case it is a mapped relation whose mapping - * changed. + * be unable to recover. However, we must redo RelationInitPhysicalAddr + * in case it is a mapped relation whose mapping changed. * * If it's a nailed index, then we need to re-read the pg_class row to see * if its relfilenode changed. We can't necessarily do that here, because @@ -1882,10 +1862,6 @@ RelationClearRelation(Relation relation, bool rebuild) */ if (relation->rd_isnailed) { - relation->rd_targblock = InvalidBlockNumber; - relation->rd_fsm_nblocks = InvalidBlockNumber; - relation->rd_vm_nblocks = InvalidBlockNumber; - /* We must recalculate physical address in case it changed */ RelationInitPhysicalAddr(relation); if (relation->rd_rel->relkind == RELKIND_INDEX) @@ -2502,10 +2478,6 @@ RelationBuildLocalRelation(const char *relname, */ rel = (Relation) palloc0(sizeof(RelationData)); - rel->rd_targblock = InvalidBlockNumber; - rel->rd_fsm_nblocks = InvalidBlockNumber; - rel->rd_vm_nblocks = InvalidBlockNumber; - /* make sure relation is marked as having no open file yet */ rel->rd_smgr = NULL; @@ -4169,9 +4141,6 @@ load_relcache_init_file(bool shared) * Reset transient-state fields in the relcache entry */ rel->rd_smgr = NULL; - rel->rd_targblock = InvalidBlockNumber; - rel->rd_fsm_nblocks = InvalidBlockNumber; - rel->rd_vm_nblocks = InvalidBlockNumber; if (rel->rd_isnailed) rel->rd_refcnt = 1; else |