1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-04 20:11:56 +03:00

Create a "relation mapping" infrastructure to support changing the relfilenodes

of shared or nailed system catalogs.  This has two key benefits:

* The new CLUSTER-based VACUUM FULL can be applied safely to all catalogs.

* We no longer have to use an unsafe reindex-in-place approach for reindexing
  shared catalogs.

CLUSTER on nailed catalogs now works too, although I left it disabled on
shared catalogs because the resulting pg_index.indisclustered update would
only be visible in one database.

Since reindexing shared system catalogs is now fully transactional and
crash-safe, the former special cases in REINDEX behavior have been removed;
shared catalogs are treated the same as non-shared.

This commit does not do anything about the recently-discussed problem of
deadlocks between VACUUM FULL/CLUSTER on a system catalog and other
concurrent queries; will address that in a separate patch.  As a stopgap,
parallel_schedule has been tweaked to run vacuum.sql by itself, to avoid
such failures during the regression tests.
This commit is contained in:
Tom Lane
2010-02-07 20:48:13 +00:00
parent 7fc30c488f
commit b9b8831ad6
54 changed files with 2316 additions and 585 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.148 2010/01/02 16:57:55 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.149 2010/02/07 20:48:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -28,6 +28,7 @@
#endif
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/resowner.h"
@@ -679,17 +680,6 @@ ResetCatalogCaches(void)
* or a temp table being dropped at end of transaction, or a table created
* during the current transaction that is being dropped because of abort.)
* Remove all cache entries relevant to the specified relation OID.
*
* A special case occurs when relId is itself one of the cacheable system
* tables --- although those'll never be dropped, they can get flushed from
* the relcache (VACUUM causes this, for example). In that case we need
* to flush all cache entries that came from that table. (At one point we
* also tried to force re-execution of CatalogCacheInitializeCache for
* the cache(s) on that table. This is a bad idea since it leads to all
* kinds of trouble if a cache flush occurs while loading cache entries.
* We now avoid the need to do it by copying cc_tupdesc out of the relcache,
* rather than relying on the relcache to keep a tupdesc for us. Of course
* this assumes the tupdesc of a cachable system table will not change...)
*/
void
CatalogCacheFlushRelation(Oid relId)
@@ -706,14 +696,6 @@ CatalogCacheFlushRelation(Oid relId)
if (cache->cc_tupdesc == NULL)
continue;
/* Does this cache store tuples of the target relation itself? */
if (cache->cc_tupdesc->attrs[0]->attrelid == relId)
{
/* Yes, so flush all its contents */
ResetCatalogCache(cache);
continue;
}
/* Does this cache store tuples associated with relations at all? */
if (cache->cc_reloidattr == 0)
continue; /* nope, leave it alone */
@@ -775,6 +757,46 @@ CatalogCacheFlushRelation(Oid relId)
CACHE1_elog(DEBUG2, "end of CatalogCacheFlushRelation call");
}
/*
* CatalogCacheFlushCatalog
*
* Flush all catcache entries that came from the specified system catalog.
* This is needed after VACUUM FULL/CLUSTER on the catalog, since the
* tuples very likely now have different TIDs than before. (At one point
* we also tried to force re-execution of CatalogCacheInitializeCache for
* the cache(s) on that catalog. This is a bad idea since it leads to all
* kinds of trouble if a cache flush occurs while loading cache entries.
* We now avoid the need to do it by copying cc_tupdesc out of the relcache,
* rather than relying on the relcache to keep a tupdesc for us. Of course
* this assumes the tupdesc of a cachable system table will not change...)
*/
void
CatalogCacheFlushCatalog(Oid catId)
{
CatCache *cache;
CACHE2_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
for (cache = CacheHdr->ch_caches; cache; cache = cache->cc_next)
{
/* We can ignore uninitialized caches, since they must be empty */
if (cache->cc_tupdesc == NULL)
continue;
/* Does this cache store tuples of the target catalog? */
if (cache->cc_tupdesc->attrs[0]->attrelid == catId)
{
/* Yes, so flush all its contents */
ResetCatalogCache(cache);
/* Tell inval.c to call syscache callbacks for this cache */
CallSyscacheCallbacks(cache->id, NULL);
}
}
CACHE1_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
}
/*
* InitCatCache
*