commit 02513d121ce0b96be5619edfd0317b46b70a44da Author: Sachin Kumar Date: Tue Jan 2 16:57:42 2024 +0000 Pass pg_upgrade --jobs parameter to pg_restore This patch changes pg_upgrade --jobs behaviour for data, post_data part of restore. Instead for restoring N databases in parallel, they are restored in sequential order but with pg_restore --jobs = {original pg_upgrade --jobs value} diff --git a/src/bin/pg_upgrade/pg_upgrade.c b/src/bin/pg_upgrade/pg_upgrade.c index 5cfd2282e1..73ffdafd19 100644 --- a/src/bin/pg_upgrade/pg_upgrade.c +++ b/src/bin/pg_upgrade/pg_upgrade.c @@ -54,6 +54,7 @@ static void set_locale_and_encoding(void); static void prepare_new_cluster(void); static void prepare_new_globals(void); +static void parallel_pg_restore_dbs(bool); static void create_new_objects(void); static void copy_xact_xlog_xid(void); static void set_frozenxids(bool minmxid_only); @@ -508,6 +509,96 @@ prepare_new_globals(void) check_ok(); } +/* + * This function will use parallel pg_restore to restore + * {data}, {post_data} section of the dump. + * Since {pre_data} section cant be parallelized , instead we will + * restore {pg_upgrade --jobs} dbs in parallel. + */ +static void +parallel_pg_restore_dbs(bool pre_data) +{ + int dbnum; + int jobs = user_opts.jobs ? user_opts.jobs : 1; + /* + * Restore @section of the dump with parallel pg_restore + */ + for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++) + { + char sql_file_name[MAXPGPATH], + log_file_name[MAXPGPATH]; + DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum]; + const char *create_opts; + + /* Skip template1 in this pass */ + if (strcmp(old_db->db_name, "template1") == 0) + continue; + + pg_log(PG_STATUS, "%s", old_db->db_name); + snprintf(sql_file_name, sizeof(sql_file_name), DB_DUMP_FILE_MASK, old_db->db_oid); + snprintf(log_file_name, sizeof(log_file_name), DB_DUMP_LOG_FILE_MASK, old_db->db_oid); + + /* + * postgres database will already exist in the target installation, so + * tell pg_restore to drop and recreate it; otherwise we would fail to + * propagate its database-level properties. + */ + if (pre_data) + { + if (strcmp(old_db->db_name, "postgres") == 0) + create_opts = "--clean --create"; + else if (pre_data) + create_opts = "--create"; + } + else + create_opts = ""; + + /* + * Restore pre-data section of the dump in parallel with single pg_restore job + * This section of dump cant be parallelized with parallel pg_restore + */ + if (pre_data) + { + parallel_exec_prog(log_file_name, + NULL, + "\"%s/pg_restore\" %s %s --exit-on-error --verbose " + " --section=pre-data " + "--dbname template1 \"%s/%s\"", + new_cluster.bindir, + cluster_conn_opts(&new_cluster), + create_opts, + log_opts.dumpdir, + sql_file_name); + + } + else + { + exec_prog(log_file_name, + NULL, + true, + true, + "\"%s/pg_restore\" %s %s --exit-on-error --verbose " + "--transaction-size=1000 --jobs %d --section=data --section=post-data " + "--dbname template1 \"%s/%s\"", + new_cluster.bindir, + cluster_conn_opts(&new_cluster), + create_opts, + jobs, + log_opts.dumpdir, + sql_file_name); + } + } + /* + * Wait for child process for pre-data section + */ + if (pre_data) + { + /* reap all children */ + while (reap_child(true) == true) + ; + } + +} static void create_new_objects(void) @@ -559,46 +650,10 @@ create_new_objects(void) break; /* done once we've processed template1 */ } - for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++) - { - char sql_file_name[MAXPGPATH], - log_file_name[MAXPGPATH]; - DbInfo *old_db = &old_cluster.dbarr.dbs[dbnum]; - const char *create_opts; - - /* Skip template1 in this pass */ - if (strcmp(old_db->db_name, "template1") == 0) - continue; - - pg_log(PG_STATUS, "%s", old_db->db_name); - snprintf(sql_file_name, sizeof(sql_file_name), DB_DUMP_FILE_MASK, old_db->db_oid); - snprintf(log_file_name, sizeof(log_file_name), DB_DUMP_LOG_FILE_MASK, old_db->db_oid); - - /* - * postgres database will already exist in the target installation, so - * tell pg_restore to drop and recreate it; otherwise we would fail to - * propagate its database-level properties. - */ - if (strcmp(old_db->db_name, "postgres") == 0) - create_opts = "--clean --create"; - else - create_opts = "--create"; - - parallel_exec_prog(log_file_name, - NULL, - "\"%s/pg_restore\" %s %s --exit-on-error --verbose " - "--transaction-size=1000 " - "--dbname template1 \"%s/%s\"", - new_cluster.bindir, - cluster_conn_opts(&new_cluster), - create_opts, - log_opts.dumpdir, - sql_file_name); - } - - /* reap all children */ - while (reap_child(true) == true) - ; + /* Restore pre_data */ + parallel_pg_restore_dbs(true); + /* Restore data, post_data */ + parallel_pg_restore_dbs(false); end_progress_output(); check_ok();