From 76dd09bbec893c02376e3440a6a86a3b994d804c Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Mon, 25 Apr 2011 12:00:21 -0400 Subject: [PATCH] Add postmaster/postgres undocumented -b option for binary upgrades. This option turns off autovacuum, prevents non-super-user connections, and enables oid setting hooks in the backend. The code continues to use the old autoavacuum disable settings for servers with earlier catalog versions. This includes a catalog version bump to identify servers that support the -b option. --- contrib/pg_upgrade/check.c | 2 +- contrib/pg_upgrade/pg_upgrade.h | 4 +++- contrib/pg_upgrade/server.c | 22 ++++++++++++---------- src/backend/catalog/heap.c | 6 ++++-- src/backend/catalog/index.c | 3 ++- src/backend/catalog/pg_enum.c | 3 ++- src/backend/catalog/pg_type.c | 4 ++-- src/backend/catalog/toasting.c | 5 +++-- src/backend/commands/typecmds.c | 2 +- src/backend/commands/user.c | 2 +- src/backend/postmaster/postmaster.c | 18 ++++++++++++++---- src/backend/tcop/postgres.c | 7 ++++++- src/backend/utils/init/globals.c | 1 + src/backend/utils/init/postinit.c | 10 ++++++++++ src/include/catalog/catversion.h | 2 +- src/include/miscadmin.h | 1 + 16 files changed, 64 insertions(+), 28 deletions(-) diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c index d1dc5dbeaa..415f95b616 100644 --- a/contrib/pg_upgrade/check.c +++ b/contrib/pg_upgrade/check.c @@ -264,7 +264,7 @@ check_cluster_compatibility(bool live_check) /* Is it 9.0 but without tablespace directories? */ if (GET_MAJOR_VERSION(new_cluster.major_version) == 900 && - new_cluster.controldata.cat_ver < TABLE_SPACE_SUBDIRS) + new_cluster.controldata.cat_ver < TABLE_SPACE_SUBDIRS_CAT_VER) pg_log(PG_FATAL, "This utility can only upgrade to PostgreSQL version 9.0 after 2010-01-11\n" "because of backend API changes made during development.\n"); } diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h index 5ca570eb15..5865315d9e 100644 --- a/contrib/pg_upgrade/pg_upgrade.h +++ b/contrib/pg_upgrade/pg_upgrade.h @@ -58,7 +58,9 @@ #define atooid(x) ((Oid) strtoul((x), NULL, 10)) /* OID system catalog preservation added during PG 9.0 development */ -#define TABLE_SPACE_SUBDIRS 201001111 +#define TABLE_SPACE_SUBDIRS_CAT_VER 201001111 +/* postmaster/postgres -b (binary_upgrade) flag added during PG 9.1 development */ +#define BINARY_UPGRADE_SERVER_FLAG_CAT_VER 201104251 /* * Each relation is represented by a relinfo structure. diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c index 2a0f50eb2a..ab8d8c7334 100644 --- a/contrib/pg_upgrade/server.c +++ b/contrib/pg_upgrade/server.c @@ -173,6 +173,11 @@ start_postmaster(ClusterInfo *cluster, bool quiet) const char *datadir; unsigned short port; bool exit_hook_registered = false; +#ifndef WIN32 + char *output_filename = log_opts.filename; +#else + char *output_filename = DEVNULL; +#endif bindir = cluster->bindir; datadir = cluster->pgdata; @@ -193,7 +198,6 @@ start_postmaster(ClusterInfo *cluster, bool quiet) * same file because we get the error: "The process cannot access the file * because it is being used by another process." so we have to send all * other output to 'nul'. - * * Using autovacuum=off disables cleanup vacuum and analyze, but freeze * vacuums can still happen, so we set autovacuum_freeze_max_age to its * maximum. We assume all datfrozenxid and relfrozen values are less than @@ -202,15 +206,13 @@ start_postmaster(ClusterInfo *cluster, bool quiet) */ snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "\"%s/pg_ctl\" -l \"%s\" -D \"%s\" " - "-o \"-p %d -c autovacuum=off " - "-c autovacuum_freeze_max_age=2000000000\" " - "start >> \"%s\" 2>&1" SYSTEMQUOTE, - bindir, -#ifndef WIN32 - log_opts.filename, datadir, port, log_opts.filename); -#else - DEVNULL, datadir, port, DEVNULL); -#endif + "-o \"-p %d %s\" start >> \"%s\" 2>&1" SYSTEMQUOTE, + bindir, output_filename, datadir, port, + (cluster->controldata.cat_ver >= + BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? "-b" : + "-c autovacuum=off -c autovacuum_freeze_max_age=2000000000", + log_opts.filename); + exec_prog(true, "%s", cmd); /* wait for the server to start properly */ diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 28d5c549a3..4c08967703 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -1053,7 +1053,8 @@ heap_create_with_catalog(const char *relname, * Use binary-upgrade override for pg_class.oid/relfilenode, if * supplied. */ - if (OidIsValid(binary_upgrade_next_heap_pg_class_oid) && + if (IsBinaryUpgrade && + OidIsValid(binary_upgrade_next_heap_pg_class_oid) && (relkind == RELKIND_RELATION || relkind == RELKIND_SEQUENCE || relkind == RELKIND_VIEW || relkind == RELKIND_COMPOSITE_TYPE || relkind == RELKIND_FOREIGN_TABLE)) @@ -1061,7 +1062,8 @@ heap_create_with_catalog(const char *relname, relid = binary_upgrade_next_heap_pg_class_oid; binary_upgrade_next_heap_pg_class_oid = InvalidOid; } - else if (OidIsValid(binary_upgrade_next_toast_pg_class_oid) && + else if (IsBinaryUpgrade && + OidIsValid(binary_upgrade_next_toast_pg_class_oid) && relkind == RELKIND_TOASTVALUE) { relid = binary_upgrade_next_toast_pg_class_oid; diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index bc630a6f3a..a0898e0048 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -789,7 +789,8 @@ index_create(Relation heapRelation, * Use binary-upgrade override for pg_class.oid/relfilenode, if * supplied. */ - if (OidIsValid(binary_upgrade_next_index_pg_class_oid)) + if (IsBinaryUpgrade && + OidIsValid(binary_upgrade_next_index_pg_class_oid)) { indexRelationId = binary_upgrade_next_index_pg_class_oid; binary_upgrade_next_index_pg_class_oid = InvalidOid; diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c index 08d8aa13f3..61a9322d90 100644 --- a/src/backend/catalog/pg_enum.c +++ b/src/backend/catalog/pg_enum.c @@ -21,6 +21,7 @@ #include "catalog/pg_enum.h" #include "catalog/pg_type.h" #include "storage/lmgr.h" +#include "miscadmin.h" #include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/rel.h" @@ -311,7 +312,7 @@ restart: } /* Get a new OID for the new label */ - if (OidIsValid(binary_upgrade_next_pg_enum_oid)) + if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_pg_enum_oid)) { /* * Use binary-upgrade override for pg_enum.oid, if supplied. During diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index b691257878..de5c63defe 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -125,7 +125,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId) tup = heap_form_tuple(tupDesc, values, nulls); /* Use binary-upgrade override for pg_type.oid, if supplied. */ - if (OidIsValid(binary_upgrade_next_pg_type_oid)) + if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_pg_type_oid)) { HeapTupleSetOid(tup, binary_upgrade_next_pg_type_oid); binary_upgrade_next_pg_type_oid = InvalidOid; @@ -430,7 +430,7 @@ TypeCreate(Oid newTypeOid, if (OidIsValid(newTypeOid)) HeapTupleSetOid(tup, newTypeOid); /* Use binary-upgrade override for pg_type.oid, if supplied. */ - else if (OidIsValid(binary_upgrade_next_pg_type_oid)) + else if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_pg_type_oid)) { HeapTupleSetOid(tup, binary_upgrade_next_pg_type_oid); binary_upgrade_next_pg_type_oid = InvalidOid; diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c index 85fe57fb2a..362d26d9d1 100644 --- a/src/backend/catalog/toasting.c +++ b/src/backend/catalog/toasting.c @@ -157,7 +157,8 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptio * creation even if it seems not to need one. */ if (!needs_toast_table(rel) && - !OidIsValid(binary_upgrade_next_toast_pg_class_oid)) + (!IsBinaryUpgrade || + !OidIsValid(binary_upgrade_next_toast_pg_class_oid))) return false; /* @@ -202,7 +203,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptio namespaceid = PG_TOAST_NAMESPACE; /* Use binary-upgrade override for pg_type.oid, if supplied. */ - if (OidIsValid(binary_upgrade_next_toast_pg_type_oid)) + if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_toast_pg_type_oid)) { toast_typid = binary_upgrade_next_toast_pg_type_oid; binary_upgrade_next_toast_pg_type_oid = InvalidOid; diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 7388e5a3db..f8eb5bc4a6 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -1550,7 +1550,7 @@ AssignTypeArrayOid(void) Oid type_array_oid; /* Use binary-upgrade override for pg_type.typarray, if supplied. */ - if (OidIsValid(binary_upgrade_next_array_pg_type_oid)) + if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_array_pg_type_oid)) { type_array_oid = binary_upgrade_next_array_pg_type_oid; binary_upgrade_next_array_pg_type_oid = InvalidOid; diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 3f7d4992af..838d6eba20 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -388,7 +388,7 @@ CreateRole(CreateRoleStmt *stmt) * pg_largeobject_metadata contains pg_authid.oid's, so we use the * binary-upgrade override, if specified. */ - if (OidIsValid(binary_upgrade_next_pg_authid_oid)) + if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_pg_authid_oid)) { HeapTupleSetOid(tuple, binary_upgrade_next_pg_authid_oid); binary_upgrade_next_pg_authid_oid = InvalidOid; diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 6e7f66472f..c0cf0336a1 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -529,7 +529,7 @@ PostmasterMain(int argc, char *argv[]) * tcop/postgres.c (the option sets should not conflict) and with the * common help() function in main/main.c. */ - while ((opt = getopt(argc, argv, "A:B:c:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:W:-:")) != -1) + while ((opt = getopt(argc, argv, "A:B:bc:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:W:-:")) != -1) { switch (opt) { @@ -541,6 +541,11 @@ PostmasterMain(int argc, char *argv[]) SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV); break; + case 'b': + /* Undocumented flag used for binary upgrades */ + IsBinaryUpgrade = true; + break; + case 'D': userDoption = optarg; break; @@ -1480,8 +1485,13 @@ ServerLoop(void) if (WalWriterPID == 0 && pmState == PM_RUN) WalWriterPID = StartWalWriter(); - /* If we have lost the autovacuum launcher, try to start a new one */ - if (AutoVacPID == 0 && + /* + * If we have lost the autovacuum launcher, try to start a new one. + * We don't want autovacuum to run in binary upgrade mode because + * autovacuum might update relfrozenxid for empty tables before + * the physical files are put in place. + */ + if (!IsBinaryUpgrade && AutoVacPID == 0 && (AutoVacuumingActive() || start_autovac_launcher) && pmState == PM_RUN) { @@ -2413,7 +2423,7 @@ reaper(SIGNAL_ARGS) */ if (WalWriterPID == 0) WalWriterPID = StartWalWriter(); - if (AutoVacuumingActive() && AutoVacPID == 0) + if (!IsBinaryUpgrade && AutoVacuumingActive() && AutoVacPID == 0) AutoVacPID = StartAutoVacLauncher(); if (XLogArchivingActive() && PgArchPID == 0) PgArchPID = pgarch_start(); diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 59b7666c10..a07661f02a 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -3238,7 +3238,7 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx) * postmaster/postmaster.c (the option sets should not conflict) and with * the common help() function in main/main.c. */ - while ((flag = getopt(argc, argv, "A:B:c:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:v:W:-:")) != -1) + while ((flag = getopt(argc, argv, "A:B:bc:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:v:W:-:")) != -1) { switch (flag) { @@ -3250,6 +3250,11 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx) SetConfigOption("shared_buffers", optarg, ctx, gucsource); break; + case 'b': + /* Undocumented flag used for binary upgrades */ + IsBinaryUpgrade = true; + break; + case 'D': if (secure) userDoption = strdup(optarg); diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index 984ffd0c73..c4c41544a2 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -85,6 +85,7 @@ pid_t PostmasterPid = 0; */ bool IsPostmasterEnvironment = false; bool IsUnderPostmaster = false; +bool IsBinaryUpgrade = false; bool ExitOnAnyError = false; diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index a4c5d4c69a..1f6fba5f75 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -625,6 +625,16 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, errmsg("must be superuser to connect during database shutdown"))); } + /* + * Binary upgrades only allowed super-user connections + */ + if (IsBinaryUpgrade && !am_superuser) + { + ereport(FATAL, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("must be superuser to connect in binary upgrade mode"))); + } + /* * The last few connections slots are reserved for superusers. Although * replication connections currently require superuser privileges, we diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 53c684aa4e..2df489f32e 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201104181 +#define CATALOG_VERSION_NO 201104251 #endif diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index aa8cce5ca8..9d194171a5 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -124,6 +124,7 @@ do { \ extern pid_t PostmasterPid; extern bool IsPostmasterEnvironment; extern PGDLLIMPORT bool IsUnderPostmaster; +extern bool IsBinaryUpgrade; extern bool ExitOnAnyError;