From a61daa14d56867e90dc011bbba52ef771cea6770 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Wed, 2 Jul 2014 15:29:38 -0400 Subject: [PATCH] pg_upgrade: preserve database and relation minmxid values Also set these values for pre-9.3 old clusters that don't have values to preserve. Analysis by Alvaro Backpatch through 9.3 --- contrib/pg_upgrade/pg_upgrade.c | 68 +++++++++++----- contrib/pg_upgrade/server.c | 13 ++-- src/bin/pg_dump/pg_dump.c | 132 +++++++++++++++++++++----------- src/bin/pg_dump/pg_dump.h | 2 + src/bin/pg_dump/pg_dumpall.c | 39 ++++++---- 5 files changed, 171 insertions(+), 83 deletions(-) diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c index f19d9116d2..3e97b66476 100644 --- a/contrib/pg_upgrade/pg_upgrade.c +++ b/contrib/pg_upgrade/pg_upgrade.c @@ -46,7 +46,7 @@ static void prepare_new_cluster(void); static void prepare_new_databases(void); static void create_new_objects(void); static void copy_clog_xlog_xid(void); -static void set_frozenxids(void); +static void set_frozenxids(bool minmxid_only); static void setup(char *argv0, bool *live_check); static void cleanup(void); @@ -250,8 +250,8 @@ prepare_new_cluster(void) /* * We do freeze after analyze so pg_statistic is also frozen. template0 is * not frozen here, but data rows were frozen by initdb, and we set its - * datfrozenxid and relfrozenxids later to match the new xid counter - * later. + * datfrozenxid, relfrozenxids, and relminmxid later to match the new xid + * counter later. */ prep_status("Freezing all rows on the new cluster"); exec_prog(UTILITY_LOG_FILE, NULL, true, @@ -273,7 +273,7 @@ prepare_new_databases(void) * set. */ - set_frozenxids(); + set_frozenxids(false); prep_status("Restoring global objects in the new cluster"); @@ -356,6 +356,13 @@ create_new_objects(void) end_progress_output(); check_ok(); + /* + * We don't have minmxids for databases or relations in pre-9.3 + * clusters, so set those after we have restores the schemas. + */ + if (GET_MAJOR_VERSION(old_cluster.major_version) < 903) + set_frozenxids(true); + /* regenerate now that we have objects in the databases */ get_db_and_rel_infos(&new_cluster); @@ -489,15 +496,15 @@ copy_clog_xlog_xid(void) /* * set_frozenxids() * - * We have frozen all xids, so set relfrozenxid and datfrozenxid - * to be the old cluster's xid counter, which we just set in the new - * cluster. User-table frozenxid values will be set by pg_dump - * --binary-upgrade, but objects not set by the pg_dump must have - * proper frozen counters. + * 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. */ static void -set_frozenxids(void) +set_frozenxids(bool minmxid_only) { int dbnum; PGconn *conn, @@ -507,15 +514,25 @@ set_frozenxids(void) int i_datname; int i_datallowconn; - prep_status("Setting frozenxid counters in new cluster"); + if (!minmxid_only) + prep_status("Setting frozenxid and minmxid counters in new cluster"); + else + prep_status("Setting minmxid counter in new cluster"); conn_template1 = connectToServer(&new_cluster, "template1"); - /* set pg_database.datfrozenxid */ + if (!minmxid_only) + /* set pg_database.datfrozenxid */ + PQclear(executeQueryOrDie(conn_template1, + "UPDATE pg_catalog.pg_database " + "SET datfrozenxid = '%u'", + old_cluster.controldata.chkpnt_nxtxid)); + + /* set pg_database.datminmxid */ PQclear(executeQueryOrDie(conn_template1, "UPDATE pg_catalog.pg_database " - "SET datfrozenxid = '%u'", - old_cluster.controldata.chkpnt_nxtxid)); + "SET datminmxid = '%u'", + old_cluster.controldata.chkpnt_nxtmulti)); /* get database names */ dbres = executeQueryOrDie(conn_template1, @@ -533,10 +550,10 @@ set_frozenxids(void) /* * We must update databases where datallowconn = false, e.g. - * template0, because autovacuum increments their datfrozenxids and - * relfrozenxids even if autovacuum is turned off, and even though all - * the data rows are already frozen To enable this, we temporarily - * change datallowconn. + * template0, because autovacuum increments their datfrozenxids, + * relfrozenxids, and relminmxid even if autovacuum is turned off, + * and even though all the data rows are already frozen To enable + * this, we temporarily change datallowconn. */ if (strcmp(datallowconn, "f") == 0) PQclear(executeQueryOrDie(conn_template1, @@ -545,13 +562,22 @@ set_frozenxids(void) conn = connectToServer(&new_cluster, datname); - /* set pg_class.relfrozenxid */ + if (!minmxid_only) + /* set pg_class.relfrozenxid */ + PQclear(executeQueryOrDie(conn, + "UPDATE pg_catalog.pg_class " + "SET relfrozenxid = '%u' " + /* only heap, materialized view, and TOAST are vacuumed */ + "WHERE relkind IN ('r', 'm', 't')", + old_cluster.controldata.chkpnt_nxtxid)); + + /* set pg_class.relminmxid */ PQclear(executeQueryOrDie(conn, "UPDATE pg_catalog.pg_class " - "SET relfrozenxid = '%u' " + "SET relminmxid = '%u' " /* only heap, materialized view, and TOAST are vacuumed */ "WHERE relkind IN ('r', 'm', 't')", - old_cluster.controldata.chkpnt_nxtxid)); + old_cluster.controldata.chkpnt_nxtmulti)); PQfinish(conn); /* Reset datallowconn flag */ diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c index 5f4b5307cb..901aa21f2e 100644 --- a/contrib/pg_upgrade/server.c +++ b/contrib/pg_upgrade/server.c @@ -203,10 +203,11 @@ start_postmaster(ClusterInfo *cluster, bool throw_error) /* * 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 - * a gap of 2000000000 from the current xid counter, so autovacuum will - * not touch them. + * vacuums can still happen, so we set autovacuum_freeze_max_age and + * autovacuum_multixact_freeze_max_age to their maximums. We assume all + * datfrozenxid, relfrozenxid, and relminmxid values are less than a gap + * of 2000000000 from the current xid counter, so autovacuum will not + * touch them. * * Turn off durability requirements to improve object creation speed, and * we only modify the new cluster, so only use it there. If there is a @@ -214,11 +215,13 @@ start_postmaster(ClusterInfo *cluster, bool throw_error) * win on ext4. */ snprintf(cmd, sizeof(cmd), - "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d%s%s %s%s\" start", + "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d%s%s %s%s%s\" start", cluster->bindir, SERVER_LOG_FILE, cluster->pgconfig, cluster->port, (cluster->controldata.cat_ver >= BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? " -b" : " -c autovacuum=off -c autovacuum_freeze_max_age=2000000000", + (GET_MAJOR_VERSION(cluster->major_version) >= 903) ? + " -c autovacuum_multixact_freeze_max_age=2000000000" : "", (cluster == &new_cluster) ? " -c synchronous_commit=off -c fsync=off -c full_page_writes=off" : "", cluster->pgopts ? cluster->pgopts : "", socket_string); diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 799637d62e..412f52f707 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -2156,6 +2156,7 @@ dumpDatabase(Archive *fout) i_collate, i_ctype, i_frozenxid, + i_minmxid, i_tablespace; CatalogId dbCatId; DumpId dbDumpId; @@ -2165,7 +2166,7 @@ dumpDatabase(Archive *fout) *collate, *ctype, *tablespace; - uint32 frozenxid; + uint32 frozenxid, minmxid; datname = PQdb(conn); @@ -2176,12 +2177,26 @@ dumpDatabase(Archive *fout) selectSourceSchema(fout, "pg_catalog"); /* Get the database owner and parameters from pg_database */ - if (fout->remoteVersion >= 80400) + if (fout->remoteVersion >= 90300) { appendPQExpBuffer(dbQry, "SELECT tableoid, oid, " "(%s datdba) AS dba, " "pg_encoding_to_char(encoding) AS encoding, " - "datcollate, datctype, datfrozenxid, " + "datcollate, datctype, datfrozenxid, datminmxid, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, " + "shobj_description(oid, 'pg_database') AS description " + + "FROM pg_database " + "WHERE datname = ", + username_subquery); + appendStringLiteralAH(dbQry, datname, fout); + } + else if (fout->remoteVersion >= 80400) + { + appendPQExpBuffer(dbQry, "SELECT tableoid, oid, " + "(%s datdba) AS dba, " + "pg_encoding_to_char(encoding) AS encoding, " + "datcollate, datctype, datfrozenxid, 0 AS datminmxid, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, " "shobj_description(oid, 'pg_database') AS description " @@ -2195,7 +2210,7 @@ dumpDatabase(Archive *fout) appendPQExpBuffer(dbQry, "SELECT tableoid, oid, " "(%s datdba) AS dba, " "pg_encoding_to_char(encoding) AS encoding, " - "NULL AS datcollate, NULL AS datctype, datfrozenxid, " + "NULL AS datcollate, NULL AS datctype, datfrozenxid, 0 AS datminmxid, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, " "shobj_description(oid, 'pg_database') AS description " @@ -2209,7 +2224,7 @@ dumpDatabase(Archive *fout) appendPQExpBuffer(dbQry, "SELECT tableoid, oid, " "(%s datdba) AS dba, " "pg_encoding_to_char(encoding) AS encoding, " - "NULL AS datcollate, NULL AS datctype, datfrozenxid, " + "NULL AS datcollate, NULL AS datctype, datfrozenxid, 0 AS datminmxid, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace " "FROM pg_database " "WHERE datname = ", @@ -2222,7 +2237,7 @@ dumpDatabase(Archive *fout) "(%s datdba) AS dba, " "pg_encoding_to_char(encoding) AS encoding, " "NULL AS datcollate, NULL AS datctype, " - "0 AS datfrozenxid, " + "0 AS datfrozenxid, 0 AS datminmxid, " "NULL AS tablespace " "FROM pg_database " "WHERE datname = ", @@ -2237,7 +2252,7 @@ dumpDatabase(Archive *fout) "(%s datdba) AS dba, " "pg_encoding_to_char(encoding) AS encoding, " "NULL AS datcollate, NULL AS datctype, " - "0 AS datfrozenxid, " + "0 AS datfrozenxid, 0 AS datminmxid, " "NULL AS tablespace " "FROM pg_database " "WHERE datname = ", @@ -2254,6 +2269,7 @@ dumpDatabase(Archive *fout) i_collate = PQfnumber(res, "datcollate"); i_ctype = PQfnumber(res, "datctype"); i_frozenxid = PQfnumber(res, "datfrozenxid"); + i_minmxid = PQfnumber(res, "datminmxid"); i_tablespace = PQfnumber(res, "tablespace"); dbCatId.tableoid = atooid(PQgetvalue(res, 0, i_tableoid)); @@ -2263,6 +2279,7 @@ dumpDatabase(Archive *fout) collate = PQgetvalue(res, 0, i_collate); ctype = PQgetvalue(res, 0, i_ctype); frozenxid = atooid(PQgetvalue(res, 0, i_frozenxid)); + minmxid = atooid(PQgetvalue(res, 0, i_minmxid)); tablespace = PQgetvalue(res, 0, i_tablespace); appendPQExpBuffer(creaQry, "CREATE DATABASE %s WITH TEMPLATE = template0", @@ -2289,11 +2306,11 @@ dumpDatabase(Archive *fout) if (binary_upgrade) { - appendPQExpBufferStr(creaQry, "\n-- For binary upgrade, set datfrozenxid.\n"); + appendPQExpBufferStr(creaQry, "\n-- For binary upgrade, set datfrozenxid and datminmxid.\n"); appendPQExpBuffer(creaQry, "UPDATE pg_catalog.pg_database\n" - "SET datfrozenxid = '%u'\n" + "SET datfrozenxid = '%u', datminmxid = '%u'\n" "WHERE datname = ", - frozenxid); + frozenxid, minmxid); appendStringLiteralAH(creaQry, datname, fout); appendPQExpBufferStr(creaQry, ";\n"); @@ -2324,32 +2341,40 @@ dumpDatabase(Archive *fout) /* * pg_largeobject and pg_largeobject_metadata come from the old system - * intact, so set their relfrozenxids. + * intact, so set their relfrozenxids and relminmxids. */ if (binary_upgrade) { PGresult *lo_res; PQExpBuffer loFrozenQry = createPQExpBuffer(); PQExpBuffer loOutQry = createPQExpBuffer(); - int i_relfrozenxid; + int i_relfrozenxid, i_relminmxid; /* * pg_largeobject */ - appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid\n" - "FROM pg_catalog.pg_class\n" - "WHERE oid = %u;\n", - LargeObjectRelationId); + if (fout->remoteVersion >= 90300) + appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid, relminmxid\n" + "FROM pg_catalog.pg_class\n" + "WHERE oid = %u;\n", + LargeObjectRelationId); + else + appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid, 0 AS relminmxid\n" + "FROM pg_catalog.pg_class\n" + "WHERE oid = %u;\n", + LargeObjectRelationId); lo_res = ExecuteSqlQueryForSingleRow(fout, loFrozenQry->data); i_relfrozenxid = PQfnumber(lo_res, "relfrozenxid"); + i_relminmxid = PQfnumber(lo_res, "relminmxid"); - appendPQExpBufferStr(loOutQry, "\n-- For binary upgrade, set pg_largeobject.relfrozenxid\n"); + appendPQExpBufferStr(loOutQry, "\n-- For binary upgrade, set pg_largeobject relfrozenxid and relminmxid\n"); appendPQExpBuffer(loOutQry, "UPDATE pg_catalog.pg_class\n" - "SET relfrozenxid = '%u'\n" + "SET relfrozenxid = '%u', relminmxid = '%u'\n" "WHERE oid = %u;\n", atoi(PQgetvalue(lo_res, 0, i_relfrozenxid)), + atoi(PQgetvalue(lo_res, 0, i_relminmxid)), LargeObjectRelationId); ArchiveEntry(fout, nilCatalogId, createDumpId(), "pg_largeobject", NULL, NULL, "", @@ -2368,7 +2393,13 @@ dumpDatabase(Archive *fout) resetPQExpBuffer(loFrozenQry); resetPQExpBuffer(loOutQry); - appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid\n" + if (fout->remoteVersion >= 90300) + appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid, relminmxid\n" + "FROM pg_catalog.pg_class\n" + "WHERE oid = %u;\n", + LargeObjectMetadataRelationId); + else + appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid, 0 AS relminmxid\n" "FROM pg_catalog.pg_class\n" "WHERE oid = %u;\n", LargeObjectMetadataRelationId); @@ -2376,12 +2407,14 @@ dumpDatabase(Archive *fout) lo_res = ExecuteSqlQueryForSingleRow(fout, loFrozenQry->data); i_relfrozenxid = PQfnumber(lo_res, "relfrozenxid"); + i_relminmxid = PQfnumber(lo_res, "relminmxid"); - appendPQExpBufferStr(loOutQry, "\n-- For binary upgrade, set pg_largeobject_metadata.relfrozenxid\n"); + appendPQExpBufferStr(loOutQry, "\n-- For binary upgrade, set pg_largeobject_metadata relfrozenxid and relminmxid\n"); appendPQExpBuffer(loOutQry, "UPDATE pg_catalog.pg_class\n" - "SET relfrozenxid = '%u'\n" + "SET relfrozenxid = '%u', relminmxid = '%u'\n" "WHERE oid = %u;\n", atoi(PQgetvalue(lo_res, 0, i_relfrozenxid)), + atoi(PQgetvalue(lo_res, 0, i_relminmxid)), LargeObjectMetadataRelationId); ArchiveEntry(fout, nilCatalogId, createDumpId(), "pg_largeobject_metadata", NULL, NULL, "", @@ -4255,8 +4288,10 @@ getTables(Archive *fout, int *numTables) int i_relhasrules; int i_relhasoids; int i_relfrozenxid; + int i_relminmxid; int i_toastoid; int i_toastfrozenxid; + int i_toastminmxid; int i_relpersistence; int i_relispopulated; int i_relreplident; @@ -4304,8 +4339,9 @@ getTables(Archive *fout, int *numTables) "(%s c.relowner) AS rolname, " "c.relchecks, c.relhastriggers, " "c.relhasindex, c.relhasrules, c.relhasoids, " - "c.relfrozenxid, tc.oid AS toid, " + "c.relfrozenxid, c.relminmxid, tc.oid AS toid, " "tc.relfrozenxid AS tfrozenxid, " + "tc.relminmxid AS tminmxid, " "c.relpersistence, c.relispopulated, " "c.relreplident, c.relpages, " "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, " @@ -4343,8 +4379,9 @@ getTables(Archive *fout, int *numTables) "(%s c.relowner) AS rolname, " "c.relchecks, c.relhastriggers, " "c.relhasindex, c.relhasrules, c.relhasoids, " - "c.relfrozenxid, tc.oid AS toid, " + "c.relfrozenxid, c.relminmxid, tc.oid AS toid, " "tc.relfrozenxid AS tfrozenxid, " + "tc.relminmxid AS tminmxid, " "c.relpersistence, c.relispopulated, " "'d' AS relreplident, c.relpages, " "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, " @@ -4382,8 +4419,9 @@ getTables(Archive *fout, int *numTables) "(%s c.relowner) AS rolname, " "c.relchecks, c.relhastriggers, " "c.relhasindex, c.relhasrules, c.relhasoids, " - "c.relfrozenxid, tc.oid AS toid, " + "c.relfrozenxid, 0 AS relminmxid, tc.oid AS toid, " "tc.relfrozenxid AS tfrozenxid, " + "0 AS tminmxid, " "c.relpersistence, 't' as relispopulated, " "'d' AS relreplident, c.relpages, " "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, " @@ -4419,8 +4457,9 @@ getTables(Archive *fout, int *numTables) "(%s c.relowner) AS rolname, " "c.relchecks, c.relhastriggers, " "c.relhasindex, c.relhasrules, c.relhasoids, " - "c.relfrozenxid, tc.oid AS toid, " + "c.relfrozenxid, 0 AS relminmxid, tc.oid AS toid, " "tc.relfrozenxid AS tfrozenxid, " + "0 AS tminmxid, " "'p' AS relpersistence, 't' as relispopulated, " "'d' AS relreplident, c.relpages, " "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, " @@ -4455,8 +4494,9 @@ getTables(Archive *fout, int *numTables) "(%s c.relowner) AS rolname, " "c.relchecks, c.relhastriggers, " "c.relhasindex, c.relhasrules, c.relhasoids, " - "c.relfrozenxid, tc.oid AS toid, " + "c.relfrozenxid, 0 AS relminmxid, tc.oid AS toid, " "tc.relfrozenxid AS tfrozenxid, " + "0 AS tminmxid, " "'p' AS relpersistence, 't' as relispopulated, " "'d' AS relreplident, c.relpages, " "NULL AS reloftype, " @@ -4491,8 +4531,9 @@ getTables(Archive *fout, int *numTables) "(%s c.relowner) AS rolname, " "c.relchecks, (c.reltriggers <> 0) AS relhastriggers, " "c.relhasindex, c.relhasrules, c.relhasoids, " - "c.relfrozenxid, tc.oid AS toid, " + "c.relfrozenxid, 0 AS relminmxid, tc.oid AS toid, " "tc.relfrozenxid AS tfrozenxid, " + "0 AS tminmxid, " "'p' AS relpersistence, 't' as relispopulated, " "'d' AS relreplident, c.relpages, " "NULL AS reloftype, " @@ -4527,9 +4568,9 @@ getTables(Archive *fout, int *numTables) "(%s relowner) AS rolname, " "relchecks, (reltriggers <> 0) AS relhastriggers, " "relhasindex, relhasrules, relhasoids, " - "0 AS relfrozenxid, " + "0 AS relfrozenxid, 0 AS relminmxid," "0 AS toid, " - "0 AS tfrozenxid, " + "0 AS tfrozenxid, 0 AS tminmxid," "'p' AS relpersistence, 't' as relispopulated, " "'d' AS relreplident, relpages, " "NULL AS reloftype, " @@ -4563,9 +4604,9 @@ getTables(Archive *fout, int *numTables) "(%s relowner) AS rolname, " "relchecks, (reltriggers <> 0) AS relhastriggers, " "relhasindex, relhasrules, relhasoids, " - "0 AS relfrozenxid, " + "0 AS relfrozenxid, 0 AS relminmxid," "0 AS toid, " - "0 AS tfrozenxid, " + "0 AS tfrozenxid, 0 AS tminmxid," "'p' AS relpersistence, 't' as relispopulated, " "'d' AS relreplident, relpages, " "NULL AS reloftype, " @@ -4595,9 +4636,9 @@ getTables(Archive *fout, int *numTables) "(%s relowner) AS rolname, " "relchecks, (reltriggers <> 0) AS relhastriggers, " "relhasindex, relhasrules, relhasoids, " - "0 AS relfrozenxid, " + "0 AS relfrozenxid, 0 AS relminmxid," "0 AS toid, " - "0 AS tfrozenxid, " + "0 AS tfrozenxid, 0 AS tminmxid," "'p' AS relpersistence, 't' as relispopulated, " "'d' AS relreplident, relpages, " "NULL AS reloftype, " @@ -4622,9 +4663,9 @@ getTables(Archive *fout, int *numTables) "relchecks, (reltriggers <> 0) AS relhastriggers, " "relhasindex, relhasrules, " "'t'::bool AS relhasoids, " - "0 AS relfrozenxid, " + "0 AS relfrozenxid, 0 AS relminmxid," "0 AS toid, " - "0 AS tfrozenxid, " + "0 AS tfrozenxid, 0 AS tminmxid," "'p' AS relpersistence, 't' as relispopulated, " "'d' AS relreplident, relpages, " "NULL AS reloftype, " @@ -4659,9 +4700,9 @@ getTables(Archive *fout, int *numTables) "relchecks, (reltriggers <> 0) AS relhastriggers, " "relhasindex, relhasrules, " "'t'::bool AS relhasoids, " - "0 as relfrozenxid, " + "0 AS relfrozenxid, 0 AS relminmxid," "0 AS toid, " - "0 AS tfrozenxid, " + "0 AS tfrozenxid, 0 AS tminmxid," "'p' AS relpersistence, 't' as relispopulated, " "'d' AS relreplident, 0 AS relpages, " "NULL AS reloftype, " @@ -4708,8 +4749,10 @@ getTables(Archive *fout, int *numTables) i_relhasrules = PQfnumber(res, "relhasrules"); i_relhasoids = PQfnumber(res, "relhasoids"); i_relfrozenxid = PQfnumber(res, "relfrozenxid"); + i_relminmxid = PQfnumber(res, "relminmxid"); i_toastoid = PQfnumber(res, "toid"); i_toastfrozenxid = PQfnumber(res, "tfrozenxid"); + i_toastminmxid = PQfnumber(res, "tminmxid"); i_relpersistence = PQfnumber(res, "relpersistence"); i_relispopulated = PQfnumber(res, "relispopulated"); i_relreplident = PQfnumber(res, "relreplident"); @@ -4760,8 +4803,10 @@ getTables(Archive *fout, int *numTables) tblinfo[i].relreplident = *(PQgetvalue(res, i, i_relreplident)); tblinfo[i].relpages = atoi(PQgetvalue(res, i, i_relpages)); tblinfo[i].frozenxid = atooid(PQgetvalue(res, i, i_relfrozenxid)); + tblinfo[i].minmxid = atooid(PQgetvalue(res, i, i_relminmxid)); tblinfo[i].toast_oid = atooid(PQgetvalue(res, i, i_toastoid)); tblinfo[i].toast_frozenxid = atooid(PQgetvalue(res, i, i_toastfrozenxid)); + tblinfo[i].toast_minmxid = atooid(PQgetvalue(res, i, i_toastminmxid)); if (PQgetisnull(res, i, i_reloftype)) tblinfo[i].reloftype = NULL; else @@ -13525,22 +13570,23 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) tbinfo->reloftype); } - appendPQExpBufferStr(q, "\n-- For binary upgrade, set heap's relfrozenxid\n"); + appendPQExpBufferStr(q, "\n-- For binary upgrade, set heap's relfrozenxid and relminmxid\n"); appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n" - "SET relfrozenxid = '%u'\n" + "SET relfrozenxid = '%u', relminmxid = '%u'\n" "WHERE oid = ", - tbinfo->frozenxid); + tbinfo->frozenxid, tbinfo->minmxid); appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout); appendPQExpBufferStr(q, "::pg_catalog.regclass;\n"); if (tbinfo->toast_oid) { /* We preserve the toast oids, so we can use it during restore */ - appendPQExpBufferStr(q, "\n-- For binary upgrade, set toast's relfrozenxid\n"); + appendPQExpBufferStr(q, "\n-- For binary upgrade, set toast's relfrozenxid and relminmxid\n"); appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n" - "SET relfrozenxid = '%u'\n" + "SET relfrozenxid = '%u', relminmxid = '%u'\n" "WHERE oid = '%u';\n", - tbinfo->toast_frozenxid, tbinfo->toast_oid); + tbinfo->toast_frozenxid, + tbinfo->toast_minmxid, tbinfo->toast_oid); } } diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index daf98bcb54..d184187580 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -247,8 +247,10 @@ typedef struct _tableInfo bool hastriggers; /* does it have any triggers? */ bool hasoids; /* does it have OIDs? */ uint32 frozenxid; /* for restore frozen xid */ + uint32 minmxid; /* for restore min multi xid */ Oid toast_oid; /* for restore toast frozen xid */ uint32 toast_frozenxid; /* for restore toast frozen xid */ + uint32 toast_minmxid; /* for restore toast min multi xid */ int ncheck; /* # of CHECK expressions */ char *reloftype; /* underlying type for typed table */ /* these two are set only if table is a sequence owned by a column: */ diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 9dec6f3b14..a15d14b6ac 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -1241,12 +1241,22 @@ dumpCreateDB(PGconn *conn) PQclear(res); /* Now collect all the information about databases to dump */ - if (server_version >= 80400) + if (server_version >= 90300) + res = executeQuery(conn, + "SELECT datname, " + "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), " + "pg_encoding_to_char(d.encoding), " + "datcollate, datctype, datfrozenxid, datminmxid, " + "datistemplate, datacl, datconnlimit, " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace " + "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) " + "WHERE datallowconn ORDER BY 1"); + else if (server_version >= 80400) res = executeQuery(conn, "SELECT datname, " "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), " "pg_encoding_to_char(d.encoding), " - "datcollate, datctype, datfrozenxid, " + "datcollate, datctype, datfrozenxid, 0 AS datminmxid, " "datistemplate, datacl, datconnlimit, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace " "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) " @@ -1256,7 +1266,7 @@ dumpCreateDB(PGconn *conn) "SELECT datname, " "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), " "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, datfrozenxid, " + "null::text AS datcollate, null::text AS datctype, datfrozenxid, 0 AS datminmxid, " "datistemplate, datacl, datconnlimit, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace " "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) " @@ -1266,7 +1276,7 @@ dumpCreateDB(PGconn *conn) "SELECT datname, " "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, datfrozenxid, " + "null::text AS datcollate, null::text AS datctype, datfrozenxid, 0 AS datminmxid, " "datistemplate, datacl, -1 as datconnlimit, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace " "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) " @@ -1276,7 +1286,7 @@ dumpCreateDB(PGconn *conn) "SELECT datname, " "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, datfrozenxid, " + "null::text AS datcollate, null::text AS datctype, datfrozenxid, 0 AS datminmxid, " "datistemplate, datacl, -1 as datconnlimit, " "'pg_default' AS dattablespace " "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) " @@ -1288,7 +1298,7 @@ dumpCreateDB(PGconn *conn) "(select usename from pg_shadow where usesysid=datdba), " "(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid, " + "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid, 0 AS datminmxid, " "datistemplate, '' as datacl, -1 as datconnlimit, " "'pg_default' AS dattablespace " "FROM pg_database d " @@ -1303,7 +1313,7 @@ dumpCreateDB(PGconn *conn) "SELECT datname, " "(select usename from pg_shadow where usesysid=datdba), " "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid, " + "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid, 0 AS datminmxid, " "'f' as datistemplate, " "'' as datacl, -1 as datconnlimit, " "'pg_default' AS dattablespace " @@ -1319,10 +1329,11 @@ dumpCreateDB(PGconn *conn) char *dbcollate = PQgetvalue(res, i, 3); char *dbctype = PQgetvalue(res, i, 4); uint32 dbfrozenxid = atooid(PQgetvalue(res, i, 5)); - char *dbistemplate = PQgetvalue(res, i, 6); - char *dbacl = PQgetvalue(res, i, 7); - char *dbconnlimit = PQgetvalue(res, i, 8); - char *dbtablespace = PQgetvalue(res, i, 9); + uint32 dbminmxid = atooid(PQgetvalue(res, i, 6)); + char *dbistemplate = PQgetvalue(res, i, 7); + char *dbacl = PQgetvalue(res, i, 8); + char *dbconnlimit = PQgetvalue(res, i, 9); + char *dbtablespace = PQgetvalue(res, i, 10); char *fdbname; fdbname = pg_strdup(fmtId(dbname)); @@ -1385,11 +1396,11 @@ dumpCreateDB(PGconn *conn) if (binary_upgrade) { - appendPQExpBufferStr(buf, "-- For binary upgrade, set datfrozenxid.\n"); + appendPQExpBufferStr(buf, "-- For binary upgrade, set datfrozenxid and datminmxid.\n"); appendPQExpBuffer(buf, "UPDATE pg_catalog.pg_database " - "SET datfrozenxid = '%u' " + "SET datfrozenxid = '%u', datminmxid = '%u' " "WHERE datname = ", - dbfrozenxid); + dbfrozenxid, dbminmxid); appendStringLiteralConn(buf, dbname, conn); appendPQExpBufferStr(buf, ";\n"); } -- 2.40.0