For pg_upgrade, update template0's datfrozenxid and its relfrozenxids to
authorBruce Momjian <bruce@momjian.us>
Wed, 19 May 2010 18:27:43 +0000 (18:27 +0000)
committerBruce Momjian <bruce@momjian.us>
Wed, 19 May 2010 18:27:43 +0000 (18:27 +0000)
match the behavior of autovacuum, which does this as the xid advances
even if autovacuum is turned off.

contrib/pg_upgrade/pg_upgrade.c

index fc692fc96a1eece54406508c053255dbbdfbcbc5..7d7abe6c23cb11ca78647f5dd4020abfa2ea30dc 100644 (file)
@@ -164,7 +164,10 @@ prepare_new_cluster(migratorContext *ctx)
    check_ok(ctx);
 
    /*
-    * We do freeze after analyze so pg_statistic is also frozen
+    * 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.
     */
    prep_status(ctx, "Freezing all rows on the new cluster");
    exec_prog(ctx, true,
@@ -292,48 +295,72 @@ void
 set_frozenxids(migratorContext *ctx)
 {
    int         dbnum;
-   PGconn     *conn;
+   PGconn     *conn, *conn_template1;
    PGresult   *dbres;
    int         ntups;
+   int         i_datname;
+   int         i_datallowconn;
 
    prep_status(ctx, "Setting frozenxid counters in new cluster");
 
-   conn = connectToServer(ctx, "template1", CLUSTER_NEW);
+   conn_template1 = connectToServer(ctx, "template1", CLUSTER_NEW);
 
    /* set pg_database.datfrozenxid */
-   PQclear(executeQueryOrDie(ctx, conn,
+   PQclear(executeQueryOrDie(ctx, conn_template1,
                              "UPDATE pg_catalog.pg_database "
-                             "SET  datfrozenxid = '%u' "
-                             "WHERE datallowconn = true",
+                             "SET  datfrozenxid = '%u'",
                              ctx->old.controldata.chkpnt_nxtxid));
 
    /* get database names */
-   dbres = executeQueryOrDie(ctx, conn,
-                             "SELECT   datname "
-                             "FROM pg_catalog.pg_database "
-                             "WHERE datallowconn = true");
+   dbres = executeQueryOrDie(ctx, conn_template1,
+                             "SELECT   datname, datallowconn "
+                             "FROM pg_catalog.pg_database");
 
-   /* free dbres below */
-   PQfinish(conn);
+   i_datname = PQfnumber(dbres, "datname");
+   i_datallowconn = PQfnumber(dbres, "datallowconn");
 
    ntups = PQntuples(dbres);
    for (dbnum = 0; dbnum < ntups; dbnum++)
    {
-       conn = connectToServer(ctx, PQgetvalue(dbres, dbnum, 0), CLUSTER_NEW);
+       char *datname = PQgetvalue(dbres, dbnum, i_datname);
+       char *datallowconn= PQgetvalue(dbres, dbnum, i_datallowconn);
+
+       /*
+        *  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.
+        */
+       if (strcmp(datallowconn, "f") == 0)
+           PQclear(executeQueryOrDie(ctx, conn_template1,
+                                 "UPDATE pg_catalog.pg_database "
+                                 "SET  datallowconn = true "
+                                 "WHERE datname = '%s'", datname));
+
+       conn = connectToServer(ctx, datname, CLUSTER_NEW);
 
        /* set pg_class.relfrozenxid */
        PQclear(executeQueryOrDie(ctx, conn,
                                  "UPDATE   pg_catalog.pg_class "
                                  "SET  relfrozenxid = '%u' "
        /* only heap and TOAST are vacuumed */
-                                 "WHERE    relkind = 'r' OR "
-                                 "     relkind = 't'",
+                                 "WHERE    relkind IN ('r', 't')",
                                  ctx->old.controldata.chkpnt_nxtxid));
        PQfinish(conn);
+
+       /* Reset datallowconn flag */
+       if (strcmp(datallowconn, "f") == 0)
+           PQclear(executeQueryOrDie(ctx, conn_template1,
+                                 "UPDATE pg_catalog.pg_database "
+                                 "SET  datallowconn = false "
+                                 "WHERE datname = '%s'", datname));
    }
 
    PQclear(dbres);
 
+   PQfinish(conn_template1);
+
    check_ok(ctx);
 }