Commit a61daa14 authored by Bruce Momjian's avatar Bruce Momjian

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
parent a36a8fa3
...@@ -46,7 +46,7 @@ static void prepare_new_cluster(void); ...@@ -46,7 +46,7 @@ static void prepare_new_cluster(void);
static void prepare_new_databases(void); static void prepare_new_databases(void);
static void create_new_objects(void); static void create_new_objects(void);
static void copy_clog_xlog_xid(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 setup(char *argv0, bool *live_check);
static void cleanup(void); static void cleanup(void);
...@@ -250,8 +250,8 @@ prepare_new_cluster(void) ...@@ -250,8 +250,8 @@ prepare_new_cluster(void)
/* /*
* We do freeze after analyze so pg_statistic is also frozen. template0 is * 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 * not frozen here, but data rows were frozen by initdb, and we set its
* datfrozenxid and relfrozenxids later to match the new xid counter * datfrozenxid, relfrozenxids, and relminmxid later to match the new xid
* later. * counter later.
*/ */
prep_status("Freezing all rows on the new cluster"); prep_status("Freezing all rows on the new cluster");
exec_prog(UTILITY_LOG_FILE, NULL, true, exec_prog(UTILITY_LOG_FILE, NULL, true,
...@@ -273,7 +273,7 @@ prepare_new_databases(void) ...@@ -273,7 +273,7 @@ prepare_new_databases(void)
* set. * set.
*/ */
set_frozenxids(); set_frozenxids(false);
prep_status("Restoring global objects in the new cluster"); prep_status("Restoring global objects in the new cluster");
...@@ -356,6 +356,13 @@ create_new_objects(void) ...@@ -356,6 +356,13 @@ create_new_objects(void)
end_progress_output(); end_progress_output();
check_ok(); 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 */ /* regenerate now that we have objects in the databases */
get_db_and_rel_infos(&new_cluster); get_db_and_rel_infos(&new_cluster);
...@@ -489,15 +496,15 @@ copy_clog_xlog_xid(void) ...@@ -489,15 +496,15 @@ copy_clog_xlog_xid(void)
/* /*
* set_frozenxids() * set_frozenxids()
* *
* We have frozen all xids, so set relfrozenxid and datfrozenxid * We have frozen all xids, so set datfrozenxid, relfrozenxid, and
* to be the old cluster's xid counter, which we just set in the new * relminmxid to be the old cluster's xid counter, which we just set
* cluster. User-table frozenxid values will be set by pg_dump * in the new cluster. User-table frozenxid and minmxid values will
* --binary-upgrade, but objects not set by the pg_dump must have * be set by pg_dump --binary-upgrade, but objects not set by the pg_dump
* proper frozen counters. * must have proper frozen counters.
*/ */
static static
void void
set_frozenxids(void) set_frozenxids(bool minmxid_only)
{ {
int dbnum; int dbnum;
PGconn *conn, PGconn *conn,
...@@ -507,16 +514,26 @@ set_frozenxids(void) ...@@ -507,16 +514,26 @@ set_frozenxids(void)
int i_datname; int i_datname;
int i_datallowconn; 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"); conn_template1 = connectToServer(&new_cluster, "template1");
if (!minmxid_only)
/* set pg_database.datfrozenxid */ /* set pg_database.datfrozenxid */
PQclear(executeQueryOrDie(conn_template1, PQclear(executeQueryOrDie(conn_template1,
"UPDATE pg_catalog.pg_database " "UPDATE pg_catalog.pg_database "
"SET datfrozenxid = '%u'", "SET datfrozenxid = '%u'",
old_cluster.controldata.chkpnt_nxtxid)); old_cluster.controldata.chkpnt_nxtxid));
/* set pg_database.datminmxid */
PQclear(executeQueryOrDie(conn_template1,
"UPDATE pg_catalog.pg_database "
"SET datminmxid = '%u'",
old_cluster.controldata.chkpnt_nxtmulti));
/* get database names */ /* get database names */
dbres = executeQueryOrDie(conn_template1, dbres = executeQueryOrDie(conn_template1,
"SELECT datname, datallowconn " "SELECT datname, datallowconn "
...@@ -533,10 +550,10 @@ set_frozenxids(void) ...@@ -533,10 +550,10 @@ set_frozenxids(void)
/* /*
* We must update databases where datallowconn = false, e.g. * We must update databases where datallowconn = false, e.g.
* template0, because autovacuum increments their datfrozenxids and * template0, because autovacuum increments their datfrozenxids,
* relfrozenxids even if autovacuum is turned off, and even though all * relfrozenxids, and relminmxid even if autovacuum is turned off,
* the data rows are already frozen To enable this, we temporarily * and even though all the data rows are already frozen To enable
* change datallowconn. * this, we temporarily change datallowconn.
*/ */
if (strcmp(datallowconn, "f") == 0) if (strcmp(datallowconn, "f") == 0)
PQclear(executeQueryOrDie(conn_template1, PQclear(executeQueryOrDie(conn_template1,
...@@ -545,6 +562,7 @@ set_frozenxids(void) ...@@ -545,6 +562,7 @@ set_frozenxids(void)
conn = connectToServer(&new_cluster, datname); conn = connectToServer(&new_cluster, datname);
if (!minmxid_only)
/* set pg_class.relfrozenxid */ /* set pg_class.relfrozenxid */
PQclear(executeQueryOrDie(conn, PQclear(executeQueryOrDie(conn,
"UPDATE pg_catalog.pg_class " "UPDATE pg_catalog.pg_class "
...@@ -552,6 +570,14 @@ set_frozenxids(void) ...@@ -552,6 +570,14 @@ set_frozenxids(void)
/* only heap, materialized view, and TOAST are vacuumed */ /* only heap, materialized view, and TOAST are vacuumed */
"WHERE relkind IN ('r', 'm', 't')", "WHERE relkind IN ('r', 'm', 't')",
old_cluster.controldata.chkpnt_nxtxid)); old_cluster.controldata.chkpnt_nxtxid));
/* set pg_class.relminmxid */
PQclear(executeQueryOrDie(conn,
"UPDATE pg_catalog.pg_class "
"SET relminmxid = '%u' "
/* only heap, materialized view, and TOAST are vacuumed */
"WHERE relkind IN ('r', 'm', 't')",
old_cluster.controldata.chkpnt_nxtmulti));
PQfinish(conn); PQfinish(conn);
/* Reset datallowconn flag */ /* Reset datallowconn flag */
......
...@@ -203,10 +203,11 @@ start_postmaster(ClusterInfo *cluster, bool throw_error) ...@@ -203,10 +203,11 @@ start_postmaster(ClusterInfo *cluster, bool throw_error)
/* /*
* Using autovacuum=off disables cleanup vacuum and analyze, but freeze * Using autovacuum=off disables cleanup vacuum and analyze, but freeze
* vacuums can still happen, so we set autovacuum_freeze_max_age to its * vacuums can still happen, so we set autovacuum_freeze_max_age and
* maximum. We assume all datfrozenxid and relfrozen values are less than * autovacuum_multixact_freeze_max_age to their maximums. We assume all
* a gap of 2000000000 from the current xid counter, so autovacuum will * datfrozenxid, relfrozenxid, and relminmxid values are less than a gap
* not touch them. * of 2000000000 from the current xid counter, so autovacuum will not
* touch them.
* *
* Turn off durability requirements to improve object creation speed, and * 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 * 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) ...@@ -214,11 +215,13 @@ start_postmaster(ClusterInfo *cluster, bool throw_error)
* win on ext4. * win on ext4.
*/ */
snprintf(cmd, sizeof(cmd), 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->bindir, SERVER_LOG_FILE, cluster->pgconfig, cluster->port,
(cluster->controldata.cat_ver >= (cluster->controldata.cat_ver >=
BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? " -b" : BINARY_UPGRADE_SERVER_FLAG_CAT_VER) ? " -b" :
" -c autovacuum=off -c autovacuum_freeze_max_age=2000000000", " -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) ? (cluster == &new_cluster) ?
" -c synchronous_commit=off -c fsync=off -c full_page_writes=off" : "", " -c synchronous_commit=off -c fsync=off -c full_page_writes=off" : "",
cluster->pgopts ? cluster->pgopts : "", socket_string); cluster->pgopts ? cluster->pgopts : "", socket_string);
......
This diff is collapsed.
...@@ -247,8 +247,10 @@ typedef struct _tableInfo ...@@ -247,8 +247,10 @@ typedef struct _tableInfo
bool hastriggers; /* does it have any triggers? */ bool hastriggers; /* does it have any triggers? */
bool hasoids; /* does it have OIDs? */ bool hasoids; /* does it have OIDs? */
uint32 frozenxid; /* for restore frozen xid */ uint32 frozenxid; /* for restore frozen xid */
uint32 minmxid; /* for restore min multi xid */
Oid toast_oid; /* for restore toast frozen xid */ Oid toast_oid; /* for restore toast frozen xid */
uint32 toast_frozenxid; /* 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 */ int ncheck; /* # of CHECK expressions */
char *reloftype; /* underlying type for typed table */ char *reloftype; /* underlying type for typed table */
/* these two are set only if table is a sequence owned by a column: */ /* these two are set only if table is a sequence owned by a column: */
......
...@@ -1241,12 +1241,22 @@ dumpCreateDB(PGconn *conn) ...@@ -1241,12 +1241,22 @@ dumpCreateDB(PGconn *conn)
PQclear(res); PQclear(res);
/* Now collect all the information about databases to dump */ /* 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, res = executeQuery(conn,
"SELECT datname, " "SELECT datname, "
"coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), " "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
"pg_encoding_to_char(d.encoding), " "pg_encoding_to_char(d.encoding), "
"datcollate, datctype, datfrozenxid, " "datcollate, datctype, datfrozenxid, 0 AS datminmxid, "
"datistemplate, datacl, datconnlimit, " "datistemplate, datacl, datconnlimit, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace " "(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) " "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
...@@ -1256,7 +1266,7 @@ dumpCreateDB(PGconn *conn) ...@@ -1256,7 +1266,7 @@ dumpCreateDB(PGconn *conn)
"SELECT datname, " "SELECT datname, "
"coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), " "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
"pg_encoding_to_char(d.encoding), " "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, " "datistemplate, datacl, datconnlimit, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace " "(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) " "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
...@@ -1266,7 +1276,7 @@ dumpCreateDB(PGconn *conn) ...@@ -1266,7 +1276,7 @@ dumpCreateDB(PGconn *conn)
"SELECT datname, " "SELECT datname, "
"coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
"pg_encoding_to_char(d.encoding), " "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, " "datistemplate, datacl, -1 as datconnlimit, "
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace " "(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) " "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
...@@ -1276,7 +1286,7 @@ dumpCreateDB(PGconn *conn) ...@@ -1276,7 +1286,7 @@ dumpCreateDB(PGconn *conn)
"SELECT datname, " "SELECT datname, "
"coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
"pg_encoding_to_char(d.encoding), " "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, " "datistemplate, datacl, -1 as datconnlimit, "
"'pg_default' AS dattablespace " "'pg_default' AS dattablespace "
"FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) " "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
...@@ -1288,7 +1298,7 @@ dumpCreateDB(PGconn *conn) ...@@ -1288,7 +1298,7 @@ dumpCreateDB(PGconn *conn)
"(select usename from pg_shadow where usesysid=datdba), " "(select usename from pg_shadow where usesysid=datdba), "
"(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " "(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
"pg_encoding_to_char(d.encoding), " "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, " "datistemplate, '' as datacl, -1 as datconnlimit, "
"'pg_default' AS dattablespace " "'pg_default' AS dattablespace "
"FROM pg_database d " "FROM pg_database d "
...@@ -1303,7 +1313,7 @@ dumpCreateDB(PGconn *conn) ...@@ -1303,7 +1313,7 @@ dumpCreateDB(PGconn *conn)
"SELECT datname, " "SELECT datname, "
"(select usename from pg_shadow where usesysid=datdba), " "(select usename from pg_shadow where usesysid=datdba), "
"pg_encoding_to_char(d.encoding), " "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, " "'f' as datistemplate, "
"'' as datacl, -1 as datconnlimit, " "'' as datacl, -1 as datconnlimit, "
"'pg_default' AS dattablespace " "'pg_default' AS dattablespace "
...@@ -1319,10 +1329,11 @@ dumpCreateDB(PGconn *conn) ...@@ -1319,10 +1329,11 @@ dumpCreateDB(PGconn *conn)
char *dbcollate = PQgetvalue(res, i, 3); char *dbcollate = PQgetvalue(res, i, 3);
char *dbctype = PQgetvalue(res, i, 4); char *dbctype = PQgetvalue(res, i, 4);
uint32 dbfrozenxid = atooid(PQgetvalue(res, i, 5)); uint32 dbfrozenxid = atooid(PQgetvalue(res, i, 5));
char *dbistemplate = PQgetvalue(res, i, 6); uint32 dbminmxid = atooid(PQgetvalue(res, i, 6));
char *dbacl = PQgetvalue(res, i, 7); char *dbistemplate = PQgetvalue(res, i, 7);
char *dbconnlimit = PQgetvalue(res, i, 8); char *dbacl = PQgetvalue(res, i, 8);
char *dbtablespace = PQgetvalue(res, i, 9); char *dbconnlimit = PQgetvalue(res, i, 9);
char *dbtablespace = PQgetvalue(res, i, 10);
char *fdbname; char *fdbname;
fdbname = pg_strdup(fmtId(dbname)); fdbname = pg_strdup(fmtId(dbname));
...@@ -1385,11 +1396,11 @@ dumpCreateDB(PGconn *conn) ...@@ -1385,11 +1396,11 @@ dumpCreateDB(PGconn *conn)
if (binary_upgrade) 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 " appendPQExpBuffer(buf, "UPDATE pg_catalog.pg_database "
"SET datfrozenxid = '%u' " "SET datfrozenxid = '%u', datminmxid = '%u' "
"WHERE datname = ", "WHERE datname = ",
dbfrozenxid); dbfrozenxid, dbminmxid);
appendStringLiteralConn(buf, dbname, conn); appendStringLiteralConn(buf, dbname, conn);
appendPQExpBufferStr(buf, ";\n"); appendPQExpBufferStr(buf, ";\n");
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment