Skip to content

Commit 12ee6ec

Browse files
committed
In pg_upgrade, dump each database separately and use
--single-transaction to restore each database schema. This yields performance improvements for databases with many tables. Also, remove split_old_dump() as it is no longer needed.
1 parent bd9c8e7 commit 12ee6ec

File tree

8 files changed

+85
-106
lines changed

8 files changed

+85
-106
lines changed

contrib/pg_upgrade/check.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ output_check_banner(bool *live_check)
7272

7373

7474
void
75-
check_old_cluster(bool live_check, char **sequence_script_file_name)
75+
check_and_dump_old_cluster(bool live_check, char **sequence_script_file_name)
7676
{
7777
/* -- OLD -- */
7878

@@ -131,10 +131,7 @@ check_old_cluster(bool live_check, char **sequence_script_file_name)
131131
* the old server is running.
132132
*/
133133
if (!user_opts.check)
134-
{
135134
generate_old_dump();
136-
split_old_dump();
137-
}
138135

139136
if (!live_check)
140137
stop_postmaster(false);

contrib/pg_upgrade/dump.c

Lines changed: 20 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -16,95 +16,34 @@
1616
void
1717
generate_old_dump(void)
1818
{
19-
/* run new pg_dumpall binary */
20-
prep_status("Creating catalog dump");
19+
int dbnum;
2120

22-
/*
23-
* --binary-upgrade records the width of dropped columns in pg_class, and
24-
* restores the frozenid's for databases and relations.
25-
*/
21+
prep_status("Creating catalog dump\n");
22+
23+
pg_log(PG_REPORT, OVERWRITE_MESSAGE, "global objects");
24+
25+
/* run new pg_dumpall binary for globals */
2626
exec_prog(UTILITY_LOG_FILE, NULL, true,
27-
"\"%s/pg_dumpall\" %s --schema-only --binary-upgrade %s -f %s",
27+
"\"%s/pg_dumpall\" %s --schema-only --globals-only --binary-upgrade %s -f %s",
2828
new_cluster.bindir, cluster_conn_opts(&old_cluster),
2929
log_opts.verbose ? "--verbose" : "",
30-
ALL_DUMP_FILE);
31-
check_ok();
32-
}
33-
34-
35-
/*
36-
* split_old_dump
37-
*
38-
* This function splits pg_dumpall output into global values and
39-
* database creation, and per-db schemas. This allows us to create
40-
* the support functions between restoring these two parts of the
41-
* dump. We split on the first "\connect " after a CREATE ROLE
42-
* username match; this is where the per-db restore starts.
43-
*
44-
* We suppress recreation of our own username so we don't generate
45-
* an error during restore
46-
*/
47-
void
48-
split_old_dump(void)
49-
{
50-
FILE *all_dump,
51-
*globals_dump,
52-
*db_dump;
53-
FILE *current_output;
54-
char line[LINE_ALLOC];
55-
bool start_of_line = true;
56-
char create_role_str[MAX_STRING];
57-
char create_role_str_quote[MAX_STRING];
58-
char filename[MAXPGPATH];
59-
bool suppressed_username = false;
60-
61-
62-
/*
63-
* Open all files in binary mode to avoid line end translation on Windows,
64-
* both for input and output.
65-
*/
30+
GLOBALS_DUMP_FILE);
6631

67-
snprintf(filename, sizeof(filename), "%s", ALL_DUMP_FILE);
68-
if ((all_dump = fopen(filename, PG_BINARY_R)) == NULL)
69-
pg_log(PG_FATAL, "Could not open dump file \"%s\": %s\n", filename, getErrorText(errno));
70-
snprintf(filename, sizeof(filename), "%s", GLOBALS_DUMP_FILE);
71-
if ((globals_dump = fopen_priv(filename, PG_BINARY_W)) == NULL)
72-
pg_log(PG_FATAL, "Could not write to dump file \"%s\": %s\n", filename, getErrorText(errno));
73-
snprintf(filename, sizeof(filename), "%s", DB_DUMP_FILE);
74-
if ((db_dump = fopen_priv(filename, PG_BINARY_W)) == NULL)
75-
pg_log(PG_FATAL, "Could not write to dump file \"%s\": %s\n", filename, getErrorText(errno));
76-
77-
current_output = globals_dump;
78-
79-
/* patterns used to prevent our own username from being recreated */
80-
snprintf(create_role_str, sizeof(create_role_str),
81-
"CREATE ROLE %s;", os_info.user);
82-
snprintf(create_role_str_quote, sizeof(create_role_str_quote),
83-
"CREATE ROLE %s;", quote_identifier(os_info.user));
84-
85-
while (fgets(line, sizeof(line), all_dump) != NULL)
32+
/* create per-db dump files */
33+
for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
8634
{
87-
/* switch to db_dump file output? */
88-
if (current_output == globals_dump && start_of_line &&
89-
suppressed_username &&
90-
strncmp(line, "\\connect ", strlen("\\connect ")) == 0)
91-
current_output = db_dump;
35+
char file_name[MAXPGPATH];
36+
DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum];
9237

93-
/* output unless we are recreating our own username */
94-
if (current_output != globals_dump || !start_of_line ||
95-
(strncmp(line, create_role_str, strlen(create_role_str)) != 0 &&
96-
strncmp(line, create_role_str_quote, strlen(create_role_str_quote)) != 0))
97-
fputs(line, current_output);
98-
else
99-
suppressed_username = true;
38+
pg_log(PG_REPORT, OVERWRITE_MESSAGE, old_db->db_name);
39+
snprintf(file_name, sizeof(file_name), DB_DUMP_FILE_MASK, old_db->db_oid);
10040

101-
if (strlen(line) > 0 && line[strlen(line) - 1] == '\n')
102-
start_of_line = true;
103-
else
104-
start_of_line = false;
41+
exec_prog(RESTORE_LOG_FILE, NULL, true,
42+
"\"%s/pg_dump\" %s --schema-only --binary-upgrade --format=custom %s --file=\"%s\" \"%s\"",
43+
new_cluster.bindir, cluster_conn_opts(&old_cluster),
44+
log_opts.verbose ? "--verbose" : "", file_name, old_db->db_name);
10545
}
10646

107-
fclose(all_dump);
108-
fclose(globals_dump);
109-
fclose(db_dump);
47+
end_progress_output();
48+
check_ok();
11049
}

contrib/pg_upgrade/exec.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,10 @@ exec_prog(const char *log_file, const char *opt_log_file,
104104

105105
if (result != 0)
106106
{
107-
report_status(PG_REPORT, "*failure*");
107+
/* we might be in on a progress status line, so go to the next line */
108+
report_status(PG_REPORT, "\n*failure*");
108109
fflush(stdout);
110+
109111
pg_log(PG_VERBOSE, "There were problems executing \"%s\"\n", cmd);
110112
if (opt_log_file)
111113
pg_log(throw_error ? PG_FATAL : PG_REPORT,

contrib/pg_upgrade/pg_upgrade.c

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ main(int argc, char **argv)
9292

9393
check_cluster_compatibility(live_check);
9494

95-
check_old_cluster(live_check, &sequence_script_file_name);
95+
check_and_dump_old_cluster(live_check, &sequence_script_file_name);
9696

9797

9898
/* -- NEW -- */
@@ -282,6 +282,11 @@ create_new_objects(void)
282282

283283
prep_status("Adding support functions to new cluster");
284284

285+
/*
286+
* Technically, we only need to install these support functions in new
287+
* databases that also exist in the old cluster, but for completeness
288+
* we process all new databases.
289+
*/
285290
for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
286291
{
287292
DbInfo *new_db = &new_cluster.dbarr.dbs[dbnum];
@@ -292,11 +297,27 @@ create_new_objects(void)
292297
}
293298
check_ok();
294299

295-
prep_status("Restoring database schema to new cluster");
296-
exec_prog(RESTORE_LOG_FILE, NULL, true,
297-
"\"%s/psql\" " EXEC_PSQL_ARGS " %s -f \"%s\"",
298-
new_cluster.bindir, cluster_conn_opts(&new_cluster),
299-
DB_DUMP_FILE);
300+
prep_status("Restoring database schema to new cluster\n");
301+
302+
for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
303+
{
304+
char file_name[MAXPGPATH];
305+
DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum];
306+
307+
pg_log(PG_REPORT, OVERWRITE_MESSAGE, old_db->db_name);
308+
snprintf(file_name, sizeof(file_name), DB_DUMP_FILE_MASK, old_db->db_oid);
309+
310+
/*
311+
* Using pg_restore --single-transaction is faster than other
312+
* methods, like --jobs. pg_dump only produces its output at the
313+
* end, so there is little parallelism using the pipe.
314+
*/
315+
exec_prog(RESTORE_LOG_FILE, NULL, true,
316+
"\"%s/pg_restore\" %s --exit-on-error --single-transaction --verbose --dbname \"%s\" \"%s\"",
317+
new_cluster.bindir, cluster_conn_opts(&new_cluster),
318+
old_db->db_name, file_name);
319+
}
320+
end_progress_output();
300321
check_ok();
301322

302323
/* regenerate now that we have objects in the databases */
@@ -455,14 +476,23 @@ cleanup(void)
455476
/* Remove dump and log files? */
456477
if (!log_opts.retain)
457478
{
479+
int dbnum;
458480
char **filename;
459481

460482
for (filename = output_files; *filename != NULL; filename++)
461483
unlink(*filename);
462484

463-
/* remove SQL files */
464-
unlink(ALL_DUMP_FILE);
485+
/* remove dump files */
465486
unlink(GLOBALS_DUMP_FILE);
466-
unlink(DB_DUMP_FILE);
487+
488+
if (old_cluster.dbarr.dbs)
489+
for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
490+
{
491+
char file_name[MAXPGPATH];
492+
DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum];
493+
494+
snprintf(file_name, sizeof(file_name), DB_DUMP_FILE_MASK, old_db->db_oid);
495+
unlink(file_name);
496+
}
467497
}
468498
}

contrib/pg_upgrade/pg_upgrade.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,9 @@
2929
#define OVERWRITE_MESSAGE " %-" MESSAGE_WIDTH "." MESSAGE_WIDTH "s\r"
3030
#define GET_MAJOR_VERSION(v) ((v) / 100)
3131

32-
#define ALL_DUMP_FILE "pg_upgrade_dump_all.sql"
3332
/* contains both global db information and CREATE DATABASE commands */
3433
#define GLOBALS_DUMP_FILE "pg_upgrade_dump_globals.sql"
35-
#define DB_DUMP_FILE "pg_upgrade_dump_db.sql"
34+
#define DB_DUMP_FILE_MASK "pg_upgrade_dump_%u.custom"
3635

3736
#define SERVER_LOG_FILE "pg_upgrade_server.log"
3837
#define RESTORE_LOG_FILE "pg_upgrade_restore.log"
@@ -296,12 +295,12 @@ extern OSInfo os_info;
296295
/* check.c */
297296

298297
void output_check_banner(bool *live_check);
299-
void check_old_cluster(bool live_check,
298+
void check_and_dump_old_cluster(bool live_check,
300299
char **sequence_script_file_name);
301300
void check_new_cluster(void);
302301
void report_clusters_compatible(void);
303302
void issue_warnings(char *sequence_script_file_name);
304-
void output_completion_banner(char *analyze_script_file_name,
303+
void output_completion_banner(char *analyze_script_file_name,
305304
char *deletion_script_file_name);
306305
void check_cluster_versions(void);
307306
void check_cluster_compatibility(bool live_check);
@@ -319,7 +318,6 @@ void disable_old_cluster(void);
319318
/* dump.c */
320319

321320
void generate_old_dump(void);
322-
void split_old_dump(void);
323321

324322

325323
/* exec.c */
@@ -433,6 +431,7 @@ __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
433431
void
434432
pg_log(eLogType type, char *fmt,...)
435433
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
434+
void end_progress_output(void);
436435
void
437436
prep_status(const char *fmt,...)
438437
__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));

contrib/pg_upgrade/relfilenode.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,7 @@ transfer_all_new_dbs(DbInfoArr *old_db_arr,
8282
}
8383
}
8484

85-
prep_status(" "); /* in case nothing printed; pass a space so
86-
* gcc doesn't complain about empty format
87-
* string */
85+
end_progress_output();
8886
check_ok();
8987

9088
return msg;

contrib/pg_upgrade/util.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,18 @@ report_status(eLogType type, const char *fmt,...)
3535
}
3636

3737

38+
/* force blank output for progress display */
39+
void
40+
end_progress_output(void)
41+
{
42+
/*
43+
* In case nothing printed; pass a space so gcc doesn't complain about
44+
* empty format string.
45+
*/
46+
prep_status(" ");
47+
}
48+
49+
3850
/*
3951
* prep_status
4052
*

src/bin/pg_dump/pg_dumpall.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ main(int argc, char *argv[])
502502
}
503503

504504
/* Dump CREATE DATABASE commands */
505-
if (!globals_only && !roles_only && !tablespaces_only)
505+
if (binary_upgrade || (!globals_only && !roles_only && !tablespaces_only))
506506
dumpCreateDB(conn);
507507

508508
/* Dump role/database settings */
@@ -745,9 +745,11 @@ dumpRoles(PGconn *conn)
745745
* will acquire the right properties even if it already exists (ie, it
746746
* won't hurt for the CREATE to fail). This is particularly important
747747
* for the role we are connected as, since even with --clean we will
748-
* have failed to drop it.
748+
* have failed to drop it. binary_upgrade cannot generate any errors,
749+
* so we assume the role is already created.
749750
*/
750-
appendPQExpBuffer(buf, "CREATE ROLE %s;\n", fmtId(rolename));
751+
if (!binary_upgrade)
752+
appendPQExpBuffer(buf, "CREATE ROLE %s;\n", fmtId(rolename));
751753
appendPQExpBuffer(buf, "ALTER ROLE %s WITH", fmtId(rolename));
752754

753755
if (strcmp(PQgetvalue(res, i, i_rolsuper), "t") == 0)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy