diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c index 2ee9bad029c..9fd30c395e5 100644 --- a/contrib/pg_upgrade/pg_upgrade.c +++ b/contrib/pg_upgrade/pg_upgrade.c @@ -437,13 +437,13 @@ static void prepare_new_databases(void) { /* - * We set autovacuum_freeze_max_age to its maximum value so autovacuum - * does not launch here and delete clog files, before the frozen xids are - * set. + * Before we restore anything, set frozenxids of initdb-created tables. */ - set_frozenxids(false); + /* + * Now restore global objects (roles and tablespaces). + */ prep_status("Restoring global objects in the new cluster"); /* @@ -681,14 +681,25 @@ copy_clog_xlog_xid(void) /* * set_frozenxids() * - * We have frozen all xids, so set datfrozenxid, relfrozenxid, and - * relminmxid to be the old cluster's xid counter, which we just set - * in the new cluster. User-table frozenxid and minmxid values will - * be set by pg_dump --binary-upgrade, but objects not set by the pg_dump - * must have proper frozen counters. + * This is called on the new cluster before we restore anything, with + * minmxid_only = false. Its purpose is to ensure that all initdb-created + * vacuumable tables have relfrozenxid/relminmxid matching the old cluster's + * xid/mxid counters. We also initialize the datfrozenxid/datminmxid of the + * built-in databases to match. + * + * As we create user tables later, their relfrozenxid/relminmxid fields will + * be restored properly by the binary-upgrade restore script. Likewise for + * user-database datfrozenxid/datminmxid. However, if we're upgrading from a + * pre-9.3 database, which does not store per-table or per-DB minmxid, then + * the relminmxid/datminmxid values filled in by the restore script will just + * be zeroes. + * + * Hence, with a pre-9.3 source database, a second call occurs after + * everything is restored, with minmxid_only = true. This pass will + * initialize all tables and databases, both those made by initdb and user + * objects, with the desired minmxid value. frozenxid values are left alone. */ -static -void +static void set_frozenxids(bool minmxid_only) { int dbnum; diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 17e6f118c53..6f8ef709215 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -13589,6 +13589,13 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) * order. That also means we have to take care about setting * attislocal correctly, plus fix up any inherited CHECK constraints. * Analogously, we set up typed tables using ALTER TABLE / OF here. + * + * We process foreign tables here, even though they lack heap storage, + * because they can participate in inheritance relationships and we + * want this stuff to be consistent across the inheritance tree. We + * exclude indexes, toast tables, sequences and matviews, even though + * they have storage, because we don't support altering or dropping + * columns in them, nor can they be part of inheritance trees. */ if (binary_upgrade && (tbinfo->relkind == RELKIND_RELATION || tbinfo->relkind == RELKIND_FOREIGN_TABLE)) @@ -13679,7 +13686,19 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) fmtId(tbinfo->dobj.name), tbinfo->reloftype); } + } + /* + * In binary_upgrade mode, arrange to restore the old relfrozenxid and + * relminmxid of all vacuumable relations. (While vacuum.c processes + * TOAST tables semi-independently, here we see them only as children + * of other relations; so this "if" lacks RELKIND_TOASTVALUE, and the + * child toast table is handled below.) + */ + if (binary_upgrade && + (tbinfo->relkind == RELKIND_RELATION || + tbinfo->relkind == RELKIND_MATVIEW)) + { appendPQExpBufferStr(q, "\n-- For binary upgrade, set heap's relfrozenxid and relminmxid\n"); appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n" "SET relfrozenxid = '%u', relminmxid = '%u'\n" @@ -13690,7 +13709,10 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) if (tbinfo->toast_oid) { - /* We preserve the toast oids, so we can use it during restore */ + /* + * The toast table will have the same OID at restore, so we + * can safely target it by OID. + */ appendPQExpBufferStr(q, "\n-- For binary upgrade, set toast's relfrozenxid and relminmxid\n"); appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n" "SET relfrozenxid = '%u', relminmxid = '%u'\n" @@ -13704,7 +13726,8 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) * In binary_upgrade mode, restore matviews' populated status by * poking pg_class directly. This is pretty ugly, but we can't use * REFRESH MATERIALIZED VIEW since it's possible that some underlying - * matview is not populated even though this matview is. + * matview is not populated even though this matview is; in any case, + * we want to transfer the matview's heap storage, not run REFRESH. */ if (binary_upgrade && tbinfo->relkind == RELKIND_MATVIEW && tbinfo->relispopulated)