]> granicus.if.org Git - postgresql/blob - contrib/pg_upgrade/pg_upgrade.c
Fix pg_upgrade, broken by the xlogid/segno -> 64-bit int refactoring.
[postgresql] / contrib / pg_upgrade / pg_upgrade.c
1 /*
2  *      pg_upgrade.c
3  *
4  *      main source file
5  *
6  *      Copyright (c) 2010-2012, PostgreSQL Global Development Group
7  *      contrib/pg_upgrade/pg_upgrade.c
8  */
9
10 /*
11  *      To simplify the upgrade process, we force certain system values to be
12  *      identical between old and new clusters:
13  *
14  *      We control all assignments of pg_class.oid (and relfilenode) so toast
15  *      oids are the same between old and new clusters.  This is important
16  *      because toast oids are stored as toast pointers in user tables.
17  *
18  *      FYI, while pg_class.oid and pg_class.relfilenode are initially the same
19  *      in a cluster, but they can diverge due to CLUSTER, REINDEX, or VACUUM
20  *      FULL.  The new cluster will have matching pg_class.oid and
21  *      pg_class.relfilenode values and be based on the old oid value.  This can
22  *      cause the old and new pg_class.relfilenode values to differ.  In summary,
23  *      old and new pg_class.oid and new pg_class.relfilenode will have the
24  *      same value, and old pg_class.relfilenode might differ.
25  *
26  *      We control all assignments of pg_type.oid because these oids are stored
27  *      in user composite type values.
28  *
29  *      We control all assignments of pg_enum.oid because these oids are stored
30  *      in user tables as enum values.
31  *
32  *      We control all assignments of pg_authid.oid because these oids are stored
33  *      in pg_largeobject_metadata.
34  */
35
36
37
38 #include "postgres.h"
39
40 #include "pg_upgrade.h"
41
42 #ifdef HAVE_LANGINFO_H
43 #include <langinfo.h>
44 #endif
45
46 static void prepare_new_cluster(void);
47 static void prepare_new_databases(void);
48 static void create_new_objects(void);
49 static void copy_clog_xlog_xid(void);
50 static void set_frozenxids(void);
51 static void setup(char *argv0, bool live_check);
52 static void cleanup(void);
53
54 ClusterInfo old_cluster,
55                         new_cluster;
56 OSInfo          os_info;
57
58 char       *output_files[] = {
59         SERVER_LOG_FILE,
60 #ifdef WIN32
61         /* unique file for pg_ctl start */
62         SERVER_START_LOG_FILE,
63 #endif
64         RESTORE_LOG_FILE,
65         UTILITY_LOG_FILE,
66         INTERNAL_LOG_FILE,
67         NULL
68 };
69
70
71 int
72 main(int argc, char **argv)
73 {
74         char       *sequence_script_file_name = NULL;
75         char       *analyze_script_file_name = NULL;
76         char       *deletion_script_file_name = NULL;
77         bool            live_check = false;
78
79         parseCommandLine(argc, argv);
80
81         adjust_data_dir(&old_cluster);
82         adjust_data_dir(&new_cluster);
83
84         output_check_banner(&live_check);
85
86         setup(argv[0], live_check);
87
88         check_cluster_versions();
89         check_cluster_compatibility(live_check);
90
91         check_old_cluster(live_check, &sequence_script_file_name);
92
93
94         /* -- NEW -- */
95         start_postmaster(&new_cluster);
96
97         check_new_cluster();
98         report_clusters_compatible();
99
100         pg_log(PG_REPORT, "\nPerforming Upgrade\n");
101         pg_log(PG_REPORT, "------------------\n");
102
103         prepare_new_cluster();
104
105         stop_postmaster(false);
106
107         /*
108          * Destructive Changes to New Cluster
109          */
110
111         copy_clog_xlog_xid();
112
113         /* New now using xids of the old system */
114
115         /* -- NEW -- */
116         start_postmaster(&new_cluster);
117
118         prepare_new_databases();
119
120         create_new_objects();
121
122         stop_postmaster(false);
123
124         /*
125          * Most failures happen in create_new_objects(), which has completed at
126          * this point.  We do this here because it is just before linking, which
127          * will link the old and new cluster data files, preventing the old
128          * cluster from being safely started once the new cluster is started.
129          */
130         if (user_opts.transfer_mode == TRANSFER_MODE_LINK)
131                 disable_old_cluster();
132
133         transfer_all_new_dbs(&old_cluster.dbarr, &new_cluster.dbarr,
134                                                  old_cluster.pgdata, new_cluster.pgdata);
135
136         /*
137          * Assuming OIDs are only used in system tables, there is no need to
138          * restore the OID counter because we have not transferred any OIDs from
139          * the old system, but we do it anyway just in case.  We do it late here
140          * because there is no need to have the schema load use new oids.
141          */
142         prep_status("Setting next OID for new cluster");
143         exec_prog(true, true, UTILITY_LOG_FILE,
144                           SYSTEMQUOTE "\"%s/pg_resetxlog\" -o %u \"%s\" >> \"%s\" 2>&1"
145                           SYSTEMQUOTE,
146                           new_cluster.bindir, old_cluster.controldata.chkpnt_nxtoid,
147                           new_cluster.pgdata, UTILITY_LOG_FILE);
148         check_ok();
149
150         create_script_for_cluster_analyze(&analyze_script_file_name);
151         create_script_for_old_cluster_deletion(&deletion_script_file_name);
152
153         issue_warnings(sequence_script_file_name);
154
155         pg_log(PG_REPORT, "\nUpgrade Complete\n");
156         pg_log(PG_REPORT, "----------------\n");
157
158         output_completion_banner(analyze_script_file_name,
159                                                          deletion_script_file_name);
160
161         pg_free(analyze_script_file_name);
162         pg_free(deletion_script_file_name);
163         pg_free(sequence_script_file_name);
164
165         cleanup();
166
167         return 0;
168 }
169
170
171 static void
172 setup(char *argv0, bool live_check)
173 {
174         char            exec_path[MAXPGPATH];   /* full path to my executable */
175
176         /*
177          * make sure the user has a clean environment, otherwise, we may confuse
178          * libpq when we connect to one (or both) of the servers.
179          */
180         check_pghost_envvar();
181
182         verify_directories();
183
184         /* no postmasters should be running */
185         if (!live_check && is_server_running(old_cluster.pgdata))
186                 pg_log(PG_FATAL, "There seems to be a postmaster servicing the old cluster.\n"
187                            "Please shutdown that postmaster and try again.\n");
188
189         /* same goes for the new postmaster */
190         if (is_server_running(new_cluster.pgdata))
191                 pg_log(PG_FATAL, "There seems to be a postmaster servicing the new cluster.\n"
192                            "Please shutdown that postmaster and try again.\n");
193
194         /* get path to pg_upgrade executable */
195         if (find_my_exec(argv0, exec_path) < 0)
196                 pg_log(PG_FATAL, "Could not get path name to pg_upgrade: %s\n", getErrorText(errno));
197
198         /* Trim off program name and keep just path */
199         *last_dir_separator(exec_path) = '\0';
200         canonicalize_path(exec_path);
201         os_info.exec_path = pg_strdup(exec_path);
202 }
203
204
205 static void
206 prepare_new_cluster(void)
207 {
208         /*
209          * It would make more sense to freeze after loading the schema, but that
210          * would cause us to lose the frozenids restored by the load. We use
211          * --analyze so autovacuum doesn't update statistics later
212          */
213         prep_status("Analyzing all rows in the new cluster");
214         exec_prog(true, true, UTILITY_LOG_FILE,
215                           SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
216                           "--all --analyze %s >> \"%s\" 2>&1" SYSTEMQUOTE,
217                           new_cluster.bindir, new_cluster.port, os_info.user,
218                           log_opts.verbose ? "--verbose" : "", UTILITY_LOG_FILE);
219         check_ok();
220
221         /*
222          * We do freeze after analyze so pg_statistic is also frozen. template0 is
223          * not frozen here, but data rows were frozen by initdb, and we set its
224          * datfrozenxid and relfrozenxids later to match the new xid counter
225          * later.
226          */
227         prep_status("Freezing all rows on the new cluster");
228         exec_prog(true, true, UTILITY_LOG_FILE,
229                           SYSTEMQUOTE "\"%s/vacuumdb\" --port %d --username \"%s\" "
230                           "--all --freeze %s >> \"%s\" 2>&1" SYSTEMQUOTE,
231                           new_cluster.bindir, new_cluster.port, os_info.user,
232                           log_opts.verbose ? "--verbose" : "", UTILITY_LOG_FILE);
233         check_ok();
234
235         get_pg_database_relfilenode(&new_cluster);
236 }
237
238
239 static void
240 prepare_new_databases(void)
241 {
242         /*
243          * We set autovacuum_freeze_max_age to its maximum value so autovacuum
244          * does not launch here and delete clog files, before the frozen xids are
245          * set.
246          */
247
248         set_frozenxids();
249
250         prep_status("Creating databases in the new cluster");
251
252         /*
253          * Install support functions in the global-object restore database to
254          * preserve pg_authid.oid.      pg_dumpall uses 'template0' as its template
255          * database so objects we add into 'template1' are not propogated.      They
256          * are removed on pg_upgrade exit.
257          */
258         install_support_functions_in_new_db("template1");
259
260         /*
261          * We have to create the databases first so we can install support
262          * functions in all the other databases.  Ideally we could create the
263          * support functions in template1 but pg_dumpall creates database using
264          * the template0 template.
265          */
266         exec_prog(true, true, RESTORE_LOG_FILE,
267                           SYSTEMQUOTE "\"%s/psql\" --echo-queries "
268                           "--set ON_ERROR_STOP=on "
269         /* --no-psqlrc prevents AUTOCOMMIT=off */
270                           "--no-psqlrc --port %d --username \"%s\" "
271                           "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
272                           new_cluster.bindir, new_cluster.port, os_info.user,
273                           GLOBALS_DUMP_FILE, RESTORE_LOG_FILE);
274         check_ok();
275
276         /* we load this to get a current list of databases */
277         get_db_and_rel_infos(&new_cluster);
278 }
279
280
281 static void
282 create_new_objects(void)
283 {
284         int                     dbnum;
285
286         prep_status("Adding support functions to new cluster");
287
288         for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
289         {
290                 DbInfo     *new_db = &new_cluster.dbarr.dbs[dbnum];
291
292                 /* skip db we already installed */
293                 if (strcmp(new_db->db_name, "template1") != 0)
294                         install_support_functions_in_new_db(new_db->db_name);
295         }
296         check_ok();
297
298         prep_status("Restoring database schema to new cluster");
299         exec_prog(true, true, RESTORE_LOG_FILE,
300                           SYSTEMQUOTE "\"%s/psql\" --echo-queries "
301                           "--set ON_ERROR_STOP=on "
302                           "--no-psqlrc --port %d --username \"%s\" "
303                           "-f \"%s\" --dbname template1 >> \"%s\" 2>&1" SYSTEMQUOTE,
304                           new_cluster.bindir, new_cluster.port, os_info.user,
305                           DB_DUMP_FILE, RESTORE_LOG_FILE);
306         check_ok();
307
308         /* regenerate now that we have objects in the databases */
309         get_db_and_rel_infos(&new_cluster);
310
311         uninstall_support_functions_from_new_cluster();
312 }
313
314
315 static void
316 copy_clog_xlog_xid(void)
317 {
318         char            old_clog_path[MAXPGPATH];
319         char            new_clog_path[MAXPGPATH];
320
321         /* copy old commit logs to new data dir */
322         prep_status("Deleting new commit clogs");
323
324         snprintf(old_clog_path, sizeof(old_clog_path), "%s/pg_clog", old_cluster.pgdata);
325         snprintf(new_clog_path, sizeof(new_clog_path), "%s/pg_clog", new_cluster.pgdata);
326         if (!rmtree(new_clog_path, true))
327                 pg_log(PG_FATAL, "could not delete directory \"%s\"\n", new_clog_path);
328         check_ok();
329
330         prep_status("Copying old commit clogs to new server");
331         exec_prog(true, false, UTILITY_LOG_FILE,
332 #ifndef WIN32
333                           SYSTEMQUOTE "%s \"%s\" \"%s\" >> \"%s\" 2>&1" SYSTEMQUOTE,
334                           "cp -Rf",
335 #else
336         /* flags: everything, no confirm, quiet, overwrite read-only */
337                           SYSTEMQUOTE "%s \"%s\" \"%s\\\" >> \"%s\" 2>&1" SYSTEMQUOTE,
338                           "xcopy /e /y /q /r",
339 #endif
340                           old_clog_path, new_clog_path, UTILITY_LOG_FILE);
341         check_ok();
342
343         /* set the next transaction id of the new cluster */
344         prep_status("Setting next transaction ID for new cluster");
345         exec_prog(true, true, UTILITY_LOG_FILE,
346                           SYSTEMQUOTE
347                           "\"%s/pg_resetxlog\" -f -x %u \"%s\" >> \"%s\" 2>&1"
348                           SYSTEMQUOTE, new_cluster.bindir,
349                           old_cluster.controldata.chkpnt_nxtxid,
350                           new_cluster.pgdata, UTILITY_LOG_FILE);
351         check_ok();
352
353         /* now reset the wal archives in the new cluster */
354         prep_status("Resetting WAL archives");
355         exec_prog(true, true, UTILITY_LOG_FILE,
356                           SYSTEMQUOTE
357                           "\"%s/pg_resetxlog\" -l %s \"%s\" >> \"%s\" 2>&1"
358                           SYSTEMQUOTE, new_cluster.bindir,
359                           old_cluster.controldata.nextxlogfile,
360                           new_cluster.pgdata, UTILITY_LOG_FILE);
361         check_ok();
362 }
363
364
365 /*
366  *      set_frozenxids()
367  *
368  *      We have frozen all xids, so set relfrozenxid and datfrozenxid
369  *      to be the old cluster's xid counter, which we just set in the new
370  *      cluster.  User-table frozenxid values will be set by pg_dumpall
371  *      --binary-upgrade, but objects not set by the pg_dump must have
372  *      proper frozen counters.
373  */
374 static
375 void
376 set_frozenxids(void)
377 {
378         int                     dbnum;
379         PGconn     *conn,
380                            *conn_template1;
381         PGresult   *dbres;
382         int                     ntups;
383         int                     i_datname;
384         int                     i_datallowconn;
385
386         prep_status("Setting frozenxid counters in new cluster");
387
388         conn_template1 = connectToServer(&new_cluster, "template1");
389
390         /* set pg_database.datfrozenxid */
391         PQclear(executeQueryOrDie(conn_template1,
392                                                           "UPDATE pg_catalog.pg_database "
393                                                           "SET  datfrozenxid = '%u'",
394                                                           old_cluster.controldata.chkpnt_nxtxid));
395
396         /* get database names */
397         dbres = executeQueryOrDie(conn_template1,
398                                                           "SELECT       datname, datallowconn "
399                                                           "FROM pg_catalog.pg_database");
400
401         i_datname = PQfnumber(dbres, "datname");
402         i_datallowconn = PQfnumber(dbres, "datallowconn");
403
404         ntups = PQntuples(dbres);
405         for (dbnum = 0; dbnum < ntups; dbnum++)
406         {
407                 char       *datname = PQgetvalue(dbres, dbnum, i_datname);
408                 char       *datallowconn = PQgetvalue(dbres, dbnum, i_datallowconn);
409
410                 /*
411                  * We must update databases where datallowconn = false, e.g.
412                  * template0, because autovacuum increments their datfrozenxids and
413                  * relfrozenxids even if autovacuum is turned off, and even though all
414                  * the data rows are already frozen  To enable this, we temporarily
415                  * change datallowconn.
416                  */
417                 if (strcmp(datallowconn, "f") == 0)
418                         PQclear(executeQueryOrDie(conn_template1,
419                                                                           "UPDATE pg_catalog.pg_database "
420                                                                           "SET  datallowconn = true "
421                                                                           "WHERE datname = '%s'", datname));
422
423                 conn = connectToServer(&new_cluster, datname);
424
425                 /* set pg_class.relfrozenxid */
426                 PQclear(executeQueryOrDie(conn,
427                                                                   "UPDATE       pg_catalog.pg_class "
428                                                                   "SET  relfrozenxid = '%u' "
429                 /* only heap and TOAST are vacuumed */
430                                                                   "WHERE        relkind IN ('r', 't')",
431                                                                   old_cluster.controldata.chkpnt_nxtxid));
432                 PQfinish(conn);
433
434                 /* Reset datallowconn flag */
435                 if (strcmp(datallowconn, "f") == 0)
436                         PQclear(executeQueryOrDie(conn_template1,
437                                                                           "UPDATE pg_catalog.pg_database "
438                                                                           "SET  datallowconn = false "
439                                                                           "WHERE datname = '%s'", datname));
440         }
441
442         PQclear(dbres);
443
444         PQfinish(conn_template1);
445
446         check_ok();
447 }
448
449
450 static void
451 cleanup(void)
452 {
453
454         fclose(log_opts.internal);
455
456         /* Remove dump and log files? */
457         if (!log_opts.retain)
458         {
459                 char      **filename;
460
461                 for (filename = output_files; *filename != NULL; filename++)
462                         unlink(*filename);
463
464                 /* remove SQL files */
465                 unlink(ALL_DUMP_FILE);
466                 unlink(GLOBALS_DUMP_FILE);
467                 unlink(DB_DUMP_FILE);
468         }
469 }