On Wed, Jun 29, 2022 at 01:17:33PM +0900, Michael Paquier wrote: > On Sat, Jun 25, 2022 at 11:04:37AM -0500, Justin Pryzby wrote: > > > I'll concede that a cluster which has no tables sounds a lot like a toy, > > but I > > find it disturbing that nothing prevents running the process twice, up to > > the > > point that it's evidently corrupted the catalog. > > I have heard of cases where instances were only used with a set of > foreign tables, for example. Not sure that this is spread enough to > worry about, but this would fail as much as your case.
foreign tables have OIDs too. ts=# SELECT * FROM pg_class WHERE relkind ='f'; oid | 1554544611 > > While looking at this, I noticed that starting postgres --single immediately > > after initdb allows creating objects with OIDs below FirstNormalObjectId > > (thereby defeating pg_upgrade's check). I'm not familiar with the > > behavioral > > differences of single user mode, and couldn't find anything in the > > documentation. > > This one comes from NextOID in the control data file after a fresh > initdb, and GetNewObjectId() would enforce that in a postmaster > environment to be FirstNormalObjectId when assigning the first user > OID. Would you imply an extra step at the end of initdb to update the > control data file of the new cluster to reflect FirstNormalObjectId? I added a call to reset xlog, similar to what's in pg_upgrade. Unfortunately, I don't see an easy way to silence it. -- Justin
>From bb8133a01b61e2b3b1ee123bafc4a59b9f4a0c70 Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryz...@telsasoft.com> Date: Wed, 6 Jul 2022 08:55:11 -0500 Subject: [PATCH] wip: initdb should advance the OID counter to FirstNormal Otherwise, a cluster started in single-user mode immediately after initdb can create objects in the range of system OIDs. --- src/backend/access/transam/varsup.c | 5 ++--- src/bin/initdb/initdb.c | 9 +++++++++ src/bin/pg_upgrade/controldata.c | 17 +---------------- src/bin/pg_upgrade/pg_upgrade.c | 11 ----------- src/bin/pg_upgrade/pg_upgrade.h | 1 - 5 files changed, 12 insertions(+), 31 deletions(-) diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c index 849a7ce9d6d..d93974fcaa5 100644 --- a/src/backend/access/transam/varsup.c +++ b/src/backend/access/transam/varsup.c @@ -543,8 +543,7 @@ GetNewObjectId(void) * * During initdb, we start the OID generator at FirstGenbkiObjectId, so we * only wrap if before that point when in bootstrap or standalone mode. - * The first time through this routine after normal postmaster start, the - * counter will be forced up to FirstNormalObjectId. This mechanism + * This mechanism * leaves the OIDs between FirstGenbkiObjectId and FirstNormalObjectId * available for automatic assignment during initdb, while ensuring they * will never conflict with user-assigned OIDs. @@ -553,7 +552,7 @@ GetNewObjectId(void) { if (IsPostmasterEnvironment) { - /* wraparound, or first post-initdb assignment, in normal mode */ + /* wraparound */ ShmemVariableCache->nextOid = FirstNormalObjectId; ShmemVariableCache->oidCount = 0; } diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 89b888eaa5a..b3f248b649a 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -59,6 +59,7 @@ #include "sys/mman.h" #endif +#include "access/transam.h" #include "access/xlog_internal.h" #include "catalog/pg_authid_d.h" #include "catalog/pg_class_d.h" /* pgrminclude ignore */ @@ -2788,6 +2789,14 @@ initialize_data_directory(void) PG_CMD_CLOSE; + /* Set FirstNormal OID */ + snprintf(cmd, sizeof(cmd), + "\"%s/pg_resetwal\" -o %u %s", + bin_path, FirstNormalObjectId, pg_data); + + PG_CMD_OPEN; + PG_CMD_CLOSE; + check_ok(); } diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index 41b8f69b8cb..26b569f7102 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -41,7 +41,6 @@ get_control_data(ClusterInfo *cluster, bool live_check) bool got_log_id = false; bool got_log_seg = false; bool got_xid = false; - bool got_oid = false; bool got_multi = false; bool got_oldestmulti = false; bool got_oldestxid = false; @@ -291,17 +290,6 @@ get_control_data(ClusterInfo *cluster, bool live_check) cluster->controldata.chkpnt_nxtxid = str2uint(p); got_xid = true; } - else if ((p = strstr(bufin, "Latest checkpoint's NextOID:")) != NULL) - { - p = strchr(p, ':'); - - if (p == NULL || strlen(p) <= 1) - pg_fatal("%d: controldata retrieval problem\n", __LINE__); - - p++; /* remove ':' char */ - cluster->controldata.chkpnt_nxtoid = str2uint(p); - got_oid = true; - } else if ((p = strstr(bufin, "Latest checkpoint's NextMultiXactId:")) != NULL) { p = strchr(p, ':'); @@ -555,7 +543,7 @@ get_control_data(ClusterInfo *cluster, bool live_check) } /* verify that we got all the mandatory pg_control data */ - if (!got_xid || !got_oid || + if (!got_xid || !got_multi || !got_oldestxid || (!got_oldestmulti && cluster->controldata.cat_ver >= MULTIXACT_FORMATCHANGE_CAT_VER) || @@ -577,9 +565,6 @@ get_control_data(ClusterInfo *cluster, bool live_check) if (!got_xid) pg_log(PG_REPORT, " checkpoint next XID\n"); - if (!got_oid) - pg_log(PG_REPORT, " latest checkpoint next OID\n"); - if (!got_multi) pg_log(PG_REPORT, " latest checkpoint next MultiXactId\n"); diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 265d8294906..785fe8dd18d 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -168,17 +168,6 @@ main(int argc, char **argv) transfer_all_new_tablespaces(&old_cluster.dbarr, &new_cluster.dbarr, old_cluster.pgdata, new_cluster.pgdata); - /* - * Assuming OIDs are only used in system tables, there is no need to - * restore the OID counter because we have not transferred any OIDs from - * the old system, but we do it anyway just in case. We do it late here - * because there is no need to have the schema load use new oids. - */ - prep_status("Setting next OID for new cluster"); - exec_prog(UTILITY_LOG_FILE, NULL, true, true, - "\"%s/pg_resetwal\" -o %u \"%s\"", - new_cluster.bindir, old_cluster.controldata.chkpnt_nxtoid, - new_cluster.pgdata); check_ok(); if (user_opts.do_sync) diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index 50dfe9e81c1..7062da0ceb1 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -200,7 +200,6 @@ typedef struct char nextxlogfile[25]; uint32 chkpnt_nxtxid; uint32 chkpnt_nxtepoch; - uint32 chkpnt_nxtoid; uint32 chkpnt_nxtmulti; uint32 chkpnt_nxtmxoff; uint32 chkpnt_oldstMulti; -- 2.17.1