aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2022-01-17 13:32:44 -0500
committerRobert Haas <rhaas@postgresql.org>2022-01-17 13:40:27 -0500
commit9a974cbcba005256a19991203583a94b4f9a21a9 (patch)
tree25f8acab4c3df251d52150b32fa3597fea84cc41 /src/backend
parent2131c049d338fcc41612b24b91eabe27163c3c61 (diff)
downloadpostgresql-9a974cbcba005256a19991203583a94b4f9a21a9.tar.gz
postgresql-9a974cbcba005256a19991203583a94b4f9a21a9.zip
pg_upgrade: Preserve relfilenodes and tablespace OIDs.
Currently, database OIDs, relfilenodes, and tablespace OIDs can all change when a cluster is upgraded using pg_upgrade. It seems better to preserve them, because (1) it makes troubleshooting pg_upgrade easier, since you don't have to do a lot of work to match up files in the old and new clusters, (2) it allows 'rsync' to save bandwidth when used to re-sync a cluster after an upgrade, and (3) if we ever encrypt or sign blocks, we would likely want to use a nonce that depends on these values. This patch only arranges to preserve relfilenodes and tablespace OIDs. The task of preserving database OIDs is left for another patch, since it involves some complexities that don't exist in these cases. Database OIDs have a similar issue, but there are some tricky points in that case that do not apply to these cases, so that problem is left for another patch. Shruthi KC, based on an earlier patch from Antonin Houska, reviewed and with some adjustments by me. Discussion: http://postgr.es/m/CA+TgmoYgTwYcUmB=e8+hRHOFA0kkS6Kde85+UNdon6q7bt1niQ@mail.gmail.com
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/bootstrap/bootparse.y3
-rw-r--r--src/backend/catalog/heap.c63
-rw-r--r--src/backend/catalog/index.c23
-rw-r--r--src/backend/commands/tablespace.c17
-rw-r--r--src/backend/utils/adt/pg_upgrade_support.c44
5 files changed, 130 insertions, 20 deletions
diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y
index f1dd95cfad8..142433f63f3 100644
--- a/src/backend/bootstrap/bootparse.y
+++ b/src/backend/bootstrap/bootparse.y
@@ -212,7 +212,8 @@ Boot_CreateStmt:
mapped_relation,
true,
&relfrozenxid,
- &relminmxid);
+ &relminmxid,
+ true);
elog(DEBUG4, "bootstrap relation created");
}
else
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 56215496ffe..7e99de88b34 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -91,7 +91,9 @@
/* Potentially set by pg_upgrade_support functions */
Oid binary_upgrade_next_heap_pg_class_oid = InvalidOid;
+Oid binary_upgrade_next_heap_pg_class_relfilenode = InvalidOid;
Oid binary_upgrade_next_toast_pg_class_oid = InvalidOid;
+Oid binary_upgrade_next_toast_pg_class_relfilenode = InvalidOid;
static void AddNewRelationTuple(Relation pg_class_desc,
Relation new_rel_desc,
@@ -285,8 +287,12 @@ SystemAttributeByName(const char *attname)
* heap_create - Create an uncataloged heap relation
*
* Note API change: the caller must now always provide the OID
- * to use for the relation. The relfilenode may (and, normally,
- * should) be left unspecified.
+ * to use for the relation. The relfilenode may be (and in
+ * the simplest cases is) left unspecified.
+ *
+ * create_storage indicates whether or not to create the storage.
+ * However, even if create_storage is true, no storage will be
+ * created if the relkind is one that doesn't have storage.
*
* rel->rd_rel is initialized by RelationBuildLocalRelation,
* and is mostly zeroes at return.
@@ -306,9 +312,9 @@ heap_create(const char *relname,
bool mapped_relation,
bool allow_system_table_mods,
TransactionId *relfrozenxid,
- MultiXactId *relminmxid)
+ MultiXactId *relminmxid,
+ bool create_storage)
{
- bool create_storage;
Relation rel;
/* The caller must have provided an OID for the relation. */
@@ -343,17 +349,17 @@ heap_create(const char *relname,
if (!RELKIND_HAS_TABLESPACE(relkind))
reltablespace = InvalidOid;
- /*
- * Decide whether to create storage. If caller passed a valid relfilenode,
- * storage is already created, so don't do it here. Also don't create it
- * for relkinds without physical storage.
- */
- if (!RELKIND_HAS_STORAGE(relkind) || OidIsValid(relfilenode))
+ /* Don't create storage for relkinds without physical storage. */
+ if (!RELKIND_HAS_STORAGE(relkind))
create_storage = false;
else
{
- create_storage = true;
- relfilenode = relid;
+ /*
+ * If relfilenode is unspecified by the caller then create storage
+ * with oid same as relid.
+ */
+ if (!OidIsValid(relfilenode))
+ relfilenode = relid;
}
/*
@@ -1121,6 +1127,9 @@ heap_create_with_catalog(const char *relname,
Oid existing_relid;
Oid old_type_oid;
Oid new_type_oid;
+
+ /* By default set to InvalidOid unless overridden by binary-upgrade */
+ Oid relfilenode = InvalidOid;
TransactionId relfrozenxid;
MultiXactId relminmxid;
@@ -1183,7 +1192,7 @@ heap_create_with_catalog(const char *relname,
*/
if (!OidIsValid(relid))
{
- /* Use binary-upgrade override for pg_class.oid/relfilenode? */
+ /* Use binary-upgrade override for pg_class.oid and relfilenode */
if (IsBinaryUpgrade)
{
/*
@@ -1200,6 +1209,14 @@ heap_create_with_catalog(const char *relname,
{
relid = binary_upgrade_next_toast_pg_class_oid;
binary_upgrade_next_toast_pg_class_oid = InvalidOid;
+
+ if (!OidIsValid(binary_upgrade_next_toast_pg_class_relfilenode))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("toast relfilenode value not set when in binary upgrade mode")));
+
+ relfilenode = binary_upgrade_next_toast_pg_class_relfilenode;
+ binary_upgrade_next_toast_pg_class_relfilenode = InvalidOid;
}
}
else
@@ -1211,6 +1228,17 @@ heap_create_with_catalog(const char *relname,
relid = binary_upgrade_next_heap_pg_class_oid;
binary_upgrade_next_heap_pg_class_oid = InvalidOid;
+
+ if (RELKIND_HAS_STORAGE(relkind))
+ {
+ if (!OidIsValid(binary_upgrade_next_heap_pg_class_relfilenode))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("relfilenode value not set when in binary upgrade mode")));
+
+ relfilenode = binary_upgrade_next_heap_pg_class_relfilenode;
+ binary_upgrade_next_heap_pg_class_relfilenode = InvalidOid;
+ }
}
}
@@ -1250,12 +1278,16 @@ heap_create_with_catalog(const char *relname,
* Create the relcache entry (mostly dummy at this point) and the physical
* disk file. (If we fail further down, it's the smgr's responsibility to
* remove the disk file again.)
+ *
+ * NB: Note that passing create_storage = true is correct even for binary
+ * upgrade. The storage we create here will be replaced later, but we need
+ * to have something on disk in the meanwhile.
*/
new_rel_desc = heap_create(relname,
relnamespace,
reltablespace,
relid,
- InvalidOid,
+ relfilenode,
accessmtd,
tupdesc,
relkind,
@@ -1264,7 +1296,8 @@ heap_create_with_catalog(const char *relname,
mapped_relation,
allow_system_table_mods,
&relfrozenxid,
- &relminmxid);
+ &relminmxid,
+ true);
Assert(relid == RelationGetRelid(new_rel_desc));
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 4506cbcf031..e4203819a0e 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -87,6 +87,7 @@
/* Potentially set by pg_upgrade_support functions */
Oid binary_upgrade_next_index_pg_class_oid = InvalidOid;
+Oid binary_upgrade_next_index_pg_class_relfilenode = InvalidOid;
/*
* Pointer-free representation of variables used when reindexing system
@@ -733,6 +734,7 @@ index_create(Relation heapRelation,
char relkind;
TransactionId relfrozenxid;
MultiXactId relminmxid;
+ bool create_storage = !OidIsValid(relFileNode);
/* constraint flags can only be set when a constraint is requested */
Assert((constr_flags == 0) ||
@@ -904,7 +906,7 @@ index_create(Relation heapRelation,
*/
if (!OidIsValid(indexRelationId))
{
- /* Use binary-upgrade override for pg_class.oid/relfilenode? */
+ /* Use binary-upgrade override for pg_class.oid and relfilenode */
if (IsBinaryUpgrade)
{
if (!OidIsValid(binary_upgrade_next_index_pg_class_oid))
@@ -914,6 +916,22 @@ index_create(Relation heapRelation,
indexRelationId = binary_upgrade_next_index_pg_class_oid;
binary_upgrade_next_index_pg_class_oid = InvalidOid;
+
+ /* Overide the index relfilenode */
+ if ((relkind == RELKIND_INDEX) &&
+ (!OidIsValid(binary_upgrade_next_index_pg_class_relfilenode)))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("index relfilenode value not set when in binary upgrade mode")));
+ relFileNode = binary_upgrade_next_index_pg_class_relfilenode;
+ binary_upgrade_next_index_pg_class_relfilenode = InvalidOid;
+
+ /*
+ * Note that we want create_storage = true for binary upgrade.
+ * The storage we create here will be replaced later, but we need
+ * to have something on disk in the meanwhile.
+ */
+ Assert(create_storage);
}
else
{
@@ -940,7 +958,8 @@ index_create(Relation heapRelation,
mapped_relation,
allow_system_table_mods,
&relfrozenxid,
- &relminmxid);
+ &relminmxid,
+ create_storage);
Assert(relfrozenxid == InvalidTransactionId);
Assert(relminmxid == InvalidMultiXactId);
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index 7123b4069b4..b2ccf5e06ef 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -89,6 +89,7 @@ char *default_tablespace = NULL;
char *temp_tablespaces = NULL;
bool allow_in_place_tablespaces = false;
+Oid binary_upgrade_next_pg_tablespace_oid = InvalidOid;
static void create_tablespace_directories(const char *location,
const Oid tablespaceoid);
@@ -340,8 +341,20 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
MemSet(nulls, false, sizeof(nulls));
- tablespaceoid = GetNewOidWithIndex(rel, TablespaceOidIndexId,
- Anum_pg_tablespace_oid);
+ if (IsBinaryUpgrade)
+ {
+ /* Use binary-upgrade override for tablespace oid */
+ if (!OidIsValid(binary_upgrade_next_pg_tablespace_oid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("pg_tablespace OID value not set when in binary upgrade mode")));
+
+ tablespaceoid = binary_upgrade_next_pg_tablespace_oid;
+ binary_upgrade_next_pg_tablespace_oid = InvalidOid;
+ }
+ else
+ tablespaceoid = GetNewOidWithIndex(rel, TablespaceOidIndexId,
+ Anum_pg_tablespace_oid);
values[Anum_pg_tablespace_oid - 1] = ObjectIdGetDatum(tablespaceoid);
values[Anum_pg_tablespace_spcname - 1] =
DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename));
diff --git a/src/backend/utils/adt/pg_upgrade_support.c b/src/backend/utils/adt/pg_upgrade_support.c
index c651f0eb814..67b9675e92a 100644
--- a/src/backend/utils/adt/pg_upgrade_support.c
+++ b/src/backend/utils/adt/pg_upgrade_support.c
@@ -30,6 +30,17 @@ do { \
} while (0)
Datum
+binary_upgrade_set_next_pg_tablespace_oid(PG_FUNCTION_ARGS)
+{
+ Oid tbspoid = PG_GETARG_OID(0);
+
+ CHECK_IS_BINARY_UPGRADE;
+ binary_upgrade_next_pg_tablespace_oid = tbspoid;
+
+ PG_RETURN_VOID();
+}
+
+Datum
binary_upgrade_set_next_pg_type_oid(PG_FUNCTION_ARGS)
{
Oid typoid = PG_GETARG_OID(0);
@@ -85,6 +96,17 @@ binary_upgrade_set_next_heap_pg_class_oid(PG_FUNCTION_ARGS)
}
Datum
+binary_upgrade_set_next_heap_relfilenode(PG_FUNCTION_ARGS)
+{
+ Oid nodeoid = PG_GETARG_OID(0);
+
+ CHECK_IS_BINARY_UPGRADE;
+ binary_upgrade_next_heap_pg_class_relfilenode = nodeoid;
+
+ PG_RETURN_VOID();
+}
+
+Datum
binary_upgrade_set_next_index_pg_class_oid(PG_FUNCTION_ARGS)
{
Oid reloid = PG_GETARG_OID(0);
@@ -96,6 +118,17 @@ binary_upgrade_set_next_index_pg_class_oid(PG_FUNCTION_ARGS)
}
Datum
+binary_upgrade_set_next_index_relfilenode(PG_FUNCTION_ARGS)
+{
+ Oid nodeoid = PG_GETARG_OID(0);
+
+ CHECK_IS_BINARY_UPGRADE;
+ binary_upgrade_next_index_pg_class_relfilenode = nodeoid;
+
+ PG_RETURN_VOID();
+}
+
+Datum
binary_upgrade_set_next_toast_pg_class_oid(PG_FUNCTION_ARGS)
{
Oid reloid = PG_GETARG_OID(0);
@@ -107,6 +140,17 @@ binary_upgrade_set_next_toast_pg_class_oid(PG_FUNCTION_ARGS)
}
Datum
+binary_upgrade_set_next_toast_relfilenode(PG_FUNCTION_ARGS)
+{
+ Oid nodeoid = PG_GETARG_OID(0);
+
+ CHECK_IS_BINARY_UPGRADE;
+ binary_upgrade_next_toast_pg_class_relfilenode = nodeoid;
+
+ PG_RETURN_VOID();
+}
+
+Datum
binary_upgrade_set_next_pg_enum_oid(PG_FUNCTION_ARGS)
{
Oid enumoid = PG_GETARG_OID(0);