diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 40e71d513d..65cd1e7290 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.249 2006/10/04 00:30:00 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.250 2006/11/05 23:40:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -3586,3 +3586,25 @@ RelationCacheInitFileInvalidate(bool beforeSend) LWLockRelease(RelCacheInitLock); } } + +/* + * Remove the init file for a given database during postmaster startup. + * + * We used to keep the init file across restarts, but that is unsafe in PITR + * scenarios, and even in simple crash-recovery cases there are windows for + * the init file to become out-of-sync with the database. So now we just + * remove it during startup and expect the first backend launch to rebuild it. + * Of course, this has to happen in each database of the cluster. For + * simplicity this is driven by flatfiles.c, which has to scan pg_database + * anyway. + */ +void +RelationCacheInitFileRemove(const char *dbPath) +{ + char initfilename[MAXPGPATH]; + + snprintf(initfilename, sizeof(initfilename), "%s/%s", + dbPath, RELCACHE_INIT_FILENAME); + unlink(initfilename); + /* ignore any error, since it might not be there at all */ +} diff --git a/src/backend/utils/init/flatfiles.c b/src/backend/utils/init/flatfiles.c index dc117145fc..ec104bb52a 100644 --- a/src/backend/utils/init/flatfiles.c +++ b/src/backend/utils/init/flatfiles.c @@ -23,7 +23,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.22 2006/11/05 22:42:09 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.23 2006/11/05 23:40:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,6 +36,7 @@ #include "access/transam.h" #include "access/twophase_rmgr.h" #include "access/xact.h" +#include "catalog/catalog.h" #include "catalog/pg_auth_members.h" #include "catalog/pg_authid.h" #include "catalog/pg_database.h" @@ -47,6 +48,7 @@ #include "storage/pmsignal.h" #include "utils/builtins.h" #include "utils/flatfiles.h" +#include "utils/relcache.h" #include "utils/resowner.h" @@ -165,9 +167,14 @@ name_okay(const char *str) * * A side effect is to determine the oldest database's datfrozenxid * so we can set or update the XID wrap limit. + * + * Also, if "startup" is true, we tell relcache.c to clear out the relcache + * init file in each database. That's a bit nonmodular, but scanning + * pg_database twice during system startup seems too high a price for keeping + * things better separated. */ static void -write_database_file(Relation drel) +write_database_file(Relation drel, bool startup) { char *filename, *tempname; @@ -248,6 +255,17 @@ write_database_file(Relation drel) fputs_quote(datname, fp); fprintf(fp, " %u %u %u\n", datoid, dattablespace, datfrozenxid); + + /* + * Also clear relcache init file for each DB if starting up. + */ + if (startup) + { + char *dbpath = GetDatabasePath(datoid, dattablespace); + + RelationCacheInitFileRemove(dbpath); + pfree(dbpath); + } } heap_endscan(scan); @@ -669,6 +687,9 @@ write_auth_file(Relation rel_authid, Relation rel_authmem) * policy means we need not force initdb to change the format of the * flat files. * + * We also cause relcache init files to be flushed, for largely the same + * reasons. + * * In a standalone backend we pass database_only = true to skip processing * the auth file. We won't need it, and building it could fail if there's * something corrupt in the authid/authmem catalogs. @@ -699,7 +720,7 @@ BuildFlatFiles(bool database_only) /* No locking is needed because no one else is alive yet */ rel_db = XLogOpenRelation(rnode); - write_database_file(rel_db); + write_database_file(rel_db, true); if (!database_only) { @@ -811,7 +832,7 @@ AtEOXact_UpdateFlatFiles(bool isCommit) if (database_file_update_subid != InvalidSubTransactionId) { database_file_update_subid = InvalidSubTransactionId; - write_database_file(drel); + write_database_file(drel, false); heap_close(drel, NoLock); } diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h index aa2b1608c1..ae09f4aa82 100644 --- a/src/include/utils/relcache.h +++ b/src/include/utils/relcache.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/relcache.h,v 1.55 2006/07/31 20:09:10 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/relcache.h,v 1.56 2006/11/05 23:40:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -69,6 +69,7 @@ extern void AtEOSubXact_RelationCache(bool isCommit, SubTransactionId mySubid, */ extern bool RelationIdIsInInitFile(Oid relationId); extern void RelationCacheInitFileInvalidate(bool beforeSend); +extern void RelationCacheInitFileRemove(const char *dbPath); /* should be used only by relcache.c and catcache.c */ extern bool criticalRelcachesBuilt;