mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
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.
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.119 2010/02/03 01:14:17 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.120 2010/02/09 21:43:30 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -161,6 +161,9 @@ smgropen(RelFileNode rnode)
|
||||
|
||||
/* hash_search already filled in the lookup key */
|
||||
reln->smgr_owner = NULL;
|
||||
reln->smgr_targblock = InvalidBlockNumber;
|
||||
reln->smgr_fsm_nblocks = InvalidBlockNumber;
|
||||
reln->smgr_vm_nblocks = InvalidBlockNumber;
|
||||
reln->smgr_which = 0; /* we only have md.c at present */
|
||||
|
||||
/* mark it not open */
|
||||
@@ -351,6 +354,16 @@ smgr_internal_unlink(RelFileNode rnode, ForkNumber forknum,
|
||||
* anyway).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Send a shared-inval message to force other backends to close any
|
||||
* dangling smgr references they may have for this rel. We should do
|
||||
* this before starting the actual unlinking, in case we fail partway
|
||||
* through that step. Note that the sinval message will eventually come
|
||||
* back to this backend, too, and thereby provide a backstop that we
|
||||
* closed our own smgr rel.
|
||||
*/
|
||||
CacheInvalidateSmgr(rnode);
|
||||
|
||||
/*
|
||||
* Delete the physical file(s).
|
||||
*
|
||||
@@ -359,14 +372,6 @@ smgr_internal_unlink(RelFileNode rnode, ForkNumber forknum,
|
||||
* xact.
|
||||
*/
|
||||
(*(smgrsw[which].smgr_unlink)) (rnode, forknum, isRedo);
|
||||
|
||||
/*
|
||||
* Lastly, send a shared-inval message to force other backends to close
|
||||
* any dangling smgr references they may have for this rel. We do this
|
||||
* last because the sinval will eventually come back to this backend, too,
|
||||
* and thereby provide a backstop that we closed our own smgr rel.
|
||||
*/
|
||||
CacheInvalidateSmgr(rnode);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -459,21 +464,23 @@ smgrtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks,
|
||||
*/
|
||||
DropRelFileNodeBuffers(reln->smgr_rnode, forknum, isTemp, nblocks);
|
||||
|
||||
/*
|
||||
* Send a shared-inval message to force other backends to close any smgr
|
||||
* references they may have for this rel. This is useful because they
|
||||
* might have open file pointers to segments that got removed, and/or
|
||||
* smgr_targblock variables pointing past the new rel end. (The inval
|
||||
* message will come back to our backend, too, causing a
|
||||
* probably-unnecessary local smgr flush. But we don't expect that this
|
||||
* is a performance-critical path.) As in the unlink code, we want to
|
||||
* be sure the message is sent before we start changing things on-disk.
|
||||
*/
|
||||
CacheInvalidateSmgr(reln->smgr_rnode);
|
||||
|
||||
/*
|
||||
* Do the truncation.
|
||||
*/
|
||||
(*(smgrsw[reln->smgr_which].smgr_truncate)) (reln, forknum, nblocks,
|
||||
isTemp);
|
||||
|
||||
/*
|
||||
* Send a shared-inval message to force other backends to close any smgr
|
||||
* references they may have for this rel. This is useful because they
|
||||
* might have open file pointers to segments that got removed. (The inval
|
||||
* message will come back to our backend, too, causing a
|
||||
* probably-unnecessary smgr flush. But we don't expect that this is
|
||||
* a performance-critical path.)
|
||||
*/
|
||||
CacheInvalidateSmgr(reln->smgr_rnode);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user