/* *Iftheserverispromoted,thereisnowaytousethecurrentsetup *again.Warntheuserthatanewreplicationsetupshouldbedonebefore *tryingagain.
*/ if (recovery_ended)
{
pg_log_warning("failed after the end of recovery");
pg_log_warning_hint("The target server cannot be used as a physical replica anymore. " "You must recreate the physical replica before continuing.");
}
for (int i = 0; i < num_dbs; i++)
{ struct LogicalRepInfo *dbinfo = &dbinfos.dbinfo[i];
if (dbinfo->made_publication || dbinfo->made_replslot)
{
PGconn *conn;
conn = connect_database(dbinfo->pubconninfo, false); if (conn != NULL)
{ if (dbinfo->made_publication)
drop_publication(conn, dbinfo->pubname, dbinfo->dbname,
&dbinfo->made_publication); if (dbinfo->made_replslot)
drop_replication_slot(conn, dbinfo, dbinfo->replslotname);
disconnect_database(conn, false);
} else
{ /* *Ifaconnectioncouldnotbeestablished,informtheuser *thatsomeobjectswereleftonprimaryandshouldbe *removedbeforetryingagain.
*/ if (dbinfo->made_publication)
{
pg_log_warning("publication \"%s\" created in database \"%s\" on primary was left behind",
dbinfo->pubname,
dbinfo->dbname);
pg_log_warning_hint("Drop this publication before trying again.");
} if (dbinfo->made_replslot)
{
pg_log_warning("replication slot \"%s\" created in database \"%s\" on primary was left behind",
dbinfo->replslotname,
dbinfo->dbname);
pg_log_warning_hint("Drop this replication slot soon to avoid retention of WAL files.");
}
}
}
}
if (standby_running)
stop_standby_server(subscriber_dir);
}
staticvoid
usage(void)
{
printf(_("%s creates a new logical replica from a standby server.\n\n"),
progname);
printf(_("Usage:\n"));
printf(_(" %s [OPTION]...\n"), progname);
printf(_("\nOptions:\n"));
printf(_(" -a, --all create subscriptions for all databases except template\n" " databases and databases that don't allow connections\n"));
printf(_(" -d, --database=DBNAME database in which to create a subscription\n"));
printf(_(" -D, --pgdata=DATADIR location for the subscriber data directory\n"));
printf(_(" -n, --dry-run dry run, just show what would be done\n"));
printf(_(" -p, --subscriber-port=PORT subscriber port number (default %s)\n"), DEFAULT_SUB_PORT);
printf(_(" -P, --publisher-server=CONNSTR publisher connection string\n"));
printf(_(" -s, --socketdir=DIR socket directory to use (default current dir.)\n"));
printf(_(" -t, --recovery-timeout=SECS seconds to wait for recovery to end\n"));
printf(_(" -T, --enable-two-phase enable two-phase commit for all subscriptions\n"));
printf(_(" -U, --subscriber-username=NAME user name for subscriber connection\n"));
printf(_(" -v, --verbose output verbose messages\n"));
printf(_(" --clean=OBJECTTYPE drop all objects of the specified type from specified\n" " databases on the subscriber; accepts: \"%s\"\n"), "publications");
printf(_(" --config-file=FILENAME use specified main server configuration\n" " file when running target cluster\n"));
printf(_(" --publication=NAME publication name\n"));
printf(_(" --replication-slot=NAME replication slot name\n"));
printf(_(" --subscription=NAME subscription name\n"));
printf(_(" -V, --version output version information, then exit\n"));
printf(_(" -?, --help show this help, then exit\n"));
printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
}
if (find_my_exec(argv0, full_path) < 0)
strlcpy(full_path, progname, sizeof(full_path));
if (ret == -1)
pg_fatal("program \"%s\" is needed by %s but was not found in the same directory as \"%s\"",
progname, "pg_createsubscriber", full_path); else
pg_fatal("program \"%s\" was found by \"%s\" but was not the same version as %s",
progname, full_path, "pg_createsubscriber");
}
pg_log_debug("%s path is: %s", progname, exec_path);
pg_log_info("getting system identifier from publisher");
conn = connect_database(conninfo, true);
res = PQexec(conn, "SELECT system_identifier FROM pg_catalog.pg_control_system()"); if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
pg_log_error("could not get system identifier: %s",
PQresultErrorMessage(res));
disconnect_database(conn, true);
} if (PQntuples(res) != 1)
{
pg_log_error("could not get system identifier: got %d rows, expected %d row",
PQntuples(res), 1);
disconnect_database(conn, true);
}
if (dry_run)
pg_log_info("dry-run: would set system identifier to %" PRIu64 " on subscriber",
cf->system_identifier); else
{
update_controlfile(subscriber_dir, cf, true);
pg_log_info("system identifier is %" PRIu64 " on subscriber",
cf->system_identifier);
}
if (dry_run)
pg_log_info("dry-run: would run pg_resetwal on the subscriber"); else
pg_log_info("running pg_resetwal on the subscriber");
pg_log_debug("pg_resetwal command is: %s", cmd_str);
if (!dry_run)
{ int rc = system(cmd_str);
if (rc == 0)
pg_log_info("successfully reset WAL on the subscriber"); else
pg_fatal("could not reset WAL on subscriber: %s", wait_result_to_str(rc));
}
char *wal_level; int max_repslots; int cur_repslots; int max_walsenders; int cur_walsenders; int max_prepared_transactions; char *max_slot_wal_keep_size;
/* *Iftheprimaryserverisinrecovery(i.e.cascadingreplication), *objects(publication)cannotbecreatedbecauseitisreadonly.
*/ if (server_is_in_recovery(conn))
{
pg_log_error("primary server cannot be in recovery");
disconnect_database(conn, true);
}
/*------------------------------------------------------------------------ *Logicalreplicationrequiresafewparameterstobesetonpublisher. *Sincetheseparametersarenotarequirementforphysicalreplication, *weshouldcheckittomakesureitwon'tfail. * *-wal_level=logical *-max_replication_slots>=current+numberofdbstobeconverted *-max_wal_senders>=current+numberofdbstobeconverted *-max_slot_wal_keep_size=-1(topreventdeletionofrequiredWALfiles) *-----------------------------------------------------------------------
*/
res = PQexec(conn, "SELECT pg_catalog.current_setting('wal_level')," " pg_catalog.current_setting('max_replication_slots')," " (SELECT count(*) FROM pg_catalog.pg_replication_slots)," " pg_catalog.current_setting('max_wal_senders')," " (SELECT count(*) FROM pg_catalog.pg_stat_activity WHERE backend_type = 'walsender')," " pg_catalog.current_setting('max_prepared_transactions')," " pg_catalog.current_setting('max_slot_wal_keep_size')");
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
pg_log_error("could not obtain publisher settings: %s",
PQresultErrorMessage(res));
disconnect_database(conn, true);
}
if (max_repslots - cur_repslots < num_dbs)
{
pg_log_error("publisher requires %d replication slots, but only %d remain",
num_dbs, max_repslots - cur_repslots);
pg_log_error_hint("Increase the configuration parameter \"%s\" to at least %d.", "max_replication_slots", cur_repslots + num_dbs);
failed = true;
}
if (max_walsenders - cur_walsenders < num_dbs)
{
pg_log_error("publisher requires %d WAL sender processes, but only %d remain",
num_dbs, max_walsenders - cur_walsenders);
pg_log_error_hint("Increase the configuration parameter \"%s\" to at least %d.", "max_wal_senders", cur_walsenders + num_dbs);
failed = true;
}
if (max_prepared_transactions != 0 && !dbinfos.two_phase)
{
pg_log_warning("two_phase option will not be enabled for replication slots");
pg_log_warning_detail("Subscriptions will be created with the two_phase option disabled. " "Prepared transactions will be replicated at COMMIT PREPARED.");
pg_log_warning_hint("You can use the command-line option --enable-two-phase to enable two_phase.");
}
/* *Indry-runmode,validate'max_slot_wal_keep_size'.Ifthisparameter *issettoanon-defaultvalue,itmaycausereplicationfailuresdueto *requiredWALfilesbeingprematurelyremoved.
*/ if (dry_run && (strcmp(max_slot_wal_keep_size, "-1") != 0))
{
pg_log_warning("required WAL could be removed from the publisher");
pg_log_warning_hint("Set the configuration parameter \"%s\" to -1 to ensure that required WAL files are not prematurely removed.", "max_slot_wal_keep_size");
}
/* The target server must be a standby */ if (!server_is_in_recovery(conn))
{
pg_log_error("target server must be a standby");
disconnect_database(conn, true);
}
/*------------------------------------------------------------------------ *Logicalreplicationrequiresafewparameterstobesetonsubscriber. *Sincetheseparametersarenotarequirementforphysicalreplication, *weshouldcheckittomakesureitwon'tfail. * *-max_active_replication_origins>=numberofdbstobeconverted *-max_logical_replication_workers>=numberofdbstobeconverted *-max_worker_processes>=1+numberofdbstobeconverted *------------------------------------------------------------------------
*/
res = PQexec(conn, "SELECT setting FROM pg_catalog.pg_settings WHERE name IN (" "'max_logical_replication_workers', " "'max_active_replication_origins', " "'max_worker_processes', " "'primary_slot_name') " "ORDER BY name");
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
pg_log_error("could not obtain subscriber settings: %s",
PQresultErrorMessage(res));
disconnect_database(conn, true);
}
if (max_reporigins < num_dbs)
{
pg_log_error("subscriber requires %d active replication origins, but only %d remain",
num_dbs, max_reporigins);
pg_log_error_hint("Increase the configuration parameter \"%s\" to at least %d.", "max_active_replication_origins", num_dbs);
failed = true;
}
if (max_lrworkers < num_dbs)
{
pg_log_error("subscriber requires %d logical replication workers, but only %d remain",
num_dbs, max_lrworkers);
pg_log_error_hint("Increase the configuration parameter \"%s\" to at least %d.", "max_logical_replication_workers", num_dbs);
failed = true;
}
if (max_wprocs < num_dbs + 1)
{
pg_log_error("subscriber requires %d worker processes, but only %d remain",
num_dbs + 1, max_wprocs);
pg_log_error_hint("Increase the configuration parameter \"%s\" to at least %d.", "max_worker_processes", num_dbs + 1);
failed = true;
}
/* *Constructaquerystring.Thesecommandsareallowedtobeexecuted *withinatransaction.
*/
appendPQExpBuffer(query, "ALTER SUBSCRIPTION %s DISABLE;",
subname_esc);
appendPQExpBuffer(query, " ALTER SUBSCRIPTION %s SET (slot_name = NONE);",
subname_esc);
appendPQExpBuffer(query, " DROP SUBSCRIPTION %s;", subname_esc);
PQfreemem(subname_esc);
if (dry_run)
pg_log_info("dry-run: would drop subscription \"%s\" in database \"%s\"",
subname, dbname); else
{
pg_log_info("dropping subscription \"%s\" in database \"%s\"",
subname, dbname);
res = PQexec(conn, query->data);
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
pg_log_error("could not drop subscription \"%s\": %s",
subname, PQresultErrorMessage(res));
disconnect_database(conn, true);
}
appendPQExpBuffer(query, "SELECT s.subname FROM pg_catalog.pg_subscription s " "INNER JOIN pg_catalog.pg_database d ON (s.subdbid = d.oid) " "WHERE d.datname = %s",
dbname);
res = PQexec(conn, query->data);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
pg_log_error("could not obtain pre-existing subscriptions: %s",
PQresultErrorMessage(res));
disconnect_database(conn, true);
}
for (int i = 0; i < PQntuples(res); i++)
drop_existing_subscriptions(conn, PQgetvalue(res, i, 0),
dbinfo->dbname);
conn = connect_database(dbinfo[0].subconninfo, false); if (conn != NULL)
{ /* Get failover replication slot names */
res = PQexec(conn, "SELECT slot_name FROM pg_catalog.pg_replication_slots WHERE failover");
if (PQresultStatus(res) == PGRES_TUPLES_OK)
{ /* Remove failover replication slots from subscriber */ for (int i = 0; i < PQntuples(res); i++)
drop_replication_slot(conn, &dbinfo[0], PQgetvalue(res, i, 0));
} else
{
pg_log_warning("could not obtain failover replication slot information: %s",
PQresultErrorMessage(res));
pg_log_warning_hint("Drop the failover replication slots on subscriber soon to avoid retention of WAL files.");
}
PQclear(res);
disconnect_database(conn, false);
} else
{
pg_log_warning("could not drop failover replication slot");
pg_log_warning_hint("Drop the failover replication slots on subscriber soon to avoid retention of WAL files.");
}
}
if (dry_run)
pg_log_info("dry-run: would create the replication slot \"%s\" in database \"%s\" on publisher",
slot_name, dbinfo->dbname); else
pg_log_info("creating the replication slot \"%s\" in database \"%s\" on publisher",
slot_name, dbinfo->dbname);
if (dry_run)
pg_log_info("dry-run: would drop the replication slot \"%s\" in database \"%s\"",
slot_name, dbinfo->dbname); else
pg_log_info("dropping the replication slot \"%s\" in database \"%s\"",
slot_name, dbinfo->dbname);
if (!dry_run)
{
res = PQexec(conn, str->data); if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
pg_log_error("could not drop replication slot \"%s\" in database \"%s\": %s",
slot_name, dbinfo->dbname, PQresultErrorMessage(res));
dbinfo->made_replslot = false; /* don't try again. */
}
PQclear(res);
}
destroyPQExpBuffer(str);
}
/* *Reportsasuitablemessageifpg_ctlfails.
*/ staticvoid
pg_ctl_status(constchar *pg_ctl_cmd, int rc)
{ if (rc != 0)
{ if (WIFEXITED(rc))
{
pg_log_error("pg_ctl failed with exit code %d", WEXITSTATUS(rc));
} elseif (WIFSIGNALED(rc))
{ #ifdefined(WIN32)
pg_log_error("pg_ctl was terminated by exception 0x%X",
WTERMSIG(rc));
pg_log_error_detail("See C include file \"ntstatus.h\" for a description of the hexadecimal value."); #else
pg_log_error("pg_ctl was terminated by signal %d: %s",
WTERMSIG(rc), pg_strsignal(WTERMSIG(rc))); #endif
} else
{
pg_log_error("pg_ctl exited with unrecognized status %d", rc);
}
/* *Returnsaftertheserverfinishestherecoveryprocess. * *Ifrecovery_timeoutoptionisset,terminateabnormallywithoutfinishing *therecoveryprocess.Bydefault,itwaitsforever. * *XXXIstherecoveryprocessstillinprogress?Whenrecoveryprocesshasa *betterprogressreportingmechanism,itshouldbeaddedhere.
*/ staticvoid
wait_for_end_recovery(constchar *conninfo, conststruct CreateSubscriberOptions *opt)
{
PGconn *conn; int status = POSTMASTER_STILL_STARTING; int timer = 0;
pg_log_info("waiting for the target server to reach the consistent state");
conn = connect_database(conninfo, true);
for (;;)
{ /* Did the recovery process finish? We're done if so. */ if (dry_run || !server_is_in_recovery(conn))
{
status = POSTMASTER_READY;
recovery_ended = true; break;
}
/* Bail out after recovery_timeout seconds if this option is set */ if (opt->recovery_timeout > 0 && timer >= opt->recovery_timeout)
{
stop_standby_server(subscriber_dir);
pg_log_error("recovery timed out");
disconnect_database(conn, true);
}
if (status == POSTMASTER_STILL_STARTING)
pg_fatal("server did not end recovery");
pg_log_info("target server reached the consistent state");
pg_log_info_hint("If pg_createsubscriber fails after this point, you must recreate the physical replica before continuing.");
}
if (dry_run)
pg_log_info("dry-run: would drop publication \"%s\" in database \"%s\"",
pubname, dbname); else
pg_log_info("dropping publication \"%s\" in database \"%s\"",
pubname, dbname);
if (drop_all_pubs)
{
pg_log_info("dropping all existing publications in database \"%s\"",
dbinfo->dbname);
/* Fetch all publication names */
res = PQexec(conn, "SELECT pubname FROM pg_catalog.pg_publication;"); if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
pg_log_error("could not obtain publication information: %s",
PQresultErrorMessage(res));
PQclear(res);
disconnect_database(conn, true);
}
/* Drop each publication */ for (int i = 0; i < PQntuples(res); i++)
drop_publication(conn, PQgetvalue(res, i, 0), dbinfo->dbname,
&dbinfo->made_publication);
if (dry_run)
pg_log_info("dry-run: would set the replication progress (node name \"%s\", LSN %s) in database \"%s\"",
originname, lsnstr, dbinfo->dbname); else
pg_log_info("setting the replication progress (node name \"%s\", LSN %s) in database \"%s\"",
originname, lsnstr, dbinfo->dbname);
if (!dry_run)
{
res = PQexec(conn, str->data); if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
pg_log_error("could not set replication progress for subscription \"%s\": %s",
dbinfo->subname, PQresultErrorMessage(res));
disconnect_database(conn, true);
}
PQclear(res);
}
/* If a database name was specified, just connect to it. */ if (dbnamespecified)
conn = connect_database(opt->pub_conninfo_str, true); else
{ /* Otherwise, try postgres first and then template1. */ char *conninfo;
res = PQexec(conn, "SELECT datname FROM pg_database WHERE datistemplate = false AND datallowconn AND datconnlimit <> -2 ORDER BY 1"); if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
pg_log_error("could not obtain a list of databases: %s", PQresultErrorMessage(res));
PQclear(res);
disconnect_database(conn, true);
}
for (int i = 0; i < PQntuples(res); i++)
{ constchar *dbname = PQgetvalue(res, i, 0);
/* *Don'tallowittoberunasroot.Itusespg_ctlwhichdoesnotallow *iteither.
*/ #ifndef WIN32 if (geteuid() == 0)
{
pg_log_error("cannot be executed by \"root\"");
pg_log_error_hint("You must run %s as the PostgreSQL superuser.",
progname); exit(1);
} #endif
get_restricted_token();
while ((c = getopt_long(argc, argv, "ad:D:np:P:s:t:TU:v",
long_options, &option_index)) != -1)
{ switch (c)
{ case'a':
opt.all_dbs = true; break; case'd': if (!simple_string_list_member(&opt.database_names, optarg))
{
simple_string_list_append(&opt.database_names, optarg);
num_dbs++;
} else
pg_fatal("database \"%s\" specified more than once for -d/--database", optarg); break; case'D':
subscriber_dir = pg_strdup(optarg);
canonicalize_path(subscriber_dir); break; case'n':
dry_run = true; break; case'p':
opt.sub_port = pg_strdup(optarg); break; case'P':
opt.pub_conninfo_str = pg_strdup(optarg); break; case's':
opt.socket_dir = pg_strdup(optarg);
canonicalize_path(opt.socket_dir); break; case't':
opt.recovery_timeout = atoi(optarg); break; case'T':
opt.two_phase = true; break; case'U':
opt.sub_username = pg_strdup(optarg); break; case'v':
pg_logging_increase_verbosity(); break; case1:
opt.config_file = pg_strdup(optarg); break; case2: if (!simple_string_list_member(&opt.pub_names, optarg))
{
simple_string_list_append(&opt.pub_names, optarg);
num_pubs++;
} else
pg_fatal("publication \"%s\" specified more than once for --publication", optarg); break; case3: if (!simple_string_list_member(&opt.replslot_names, optarg))
{
simple_string_list_append(&opt.replslot_names, optarg);
num_replslots++;
} else
pg_fatal("replication slot \"%s\" specified more than once for --replication-slot", optarg); break; case4: if (!simple_string_list_member(&opt.sub_names, optarg))
{
simple_string_list_append(&opt.sub_names, optarg);
num_subs++;
} else
pg_fatal("subscription \"%s\" specified more than once for --subscription", optarg); break; case5: if (!simple_string_list_member(&opt.objecttypes_to_clean, optarg))
simple_string_list_append(&opt.objecttypes_to_clean, optarg); else
pg_fatal("object type \"%s\" specified more than once for --clean", optarg); break; default: /* getopt_long already emitted a complaint */
pg_log_error_hint("Try \"%s --help\" for more information.", progname); exit(1);
}
}
/* Validate that --all is not used with incompatible options */ if (opt.all_dbs)
{ char *bad_switch = NULL;
if (bad_switch)
{
pg_log_error("options %s and %s cannot be used together",
bad_switch, "-a/--all");
pg_log_error_hint("Try \"%s --help\" for more information.", progname); exit(1);
}
}
/* Any non-option arguments? */ if (optind < argc)
{
pg_log_error("too many command-line arguments (first is \"%s\")",
argv[optind]);
pg_log_error_hint("Try \"%s --help\" for more information.", progname); exit(1);
}
/* Required arguments */ if (subscriber_dir == NULL)
{
pg_log_error("no subscriber data directory specified");
pg_log_error_hint("Try \"%s --help\" for more information.", progname); exit(1);
}
/* If socket directory is not provided, use the current directory */ if (opt.socket_dir == NULL)
{ char cwd[MAXPGPATH];
if (!getcwd(cwd, MAXPGPATH))
pg_fatal("could not determine current directory");
opt.socket_dir = pg_strdup(cwd);
canonicalize_path(opt.socket_dir);
}
if (opt.database_names.head == NULL)
{
pg_log_info("no database was specified");
/* *Trytoobtainthedbnamefromthepublisherconninfo.Ifdbname *parameterisnotavailable,errorout.
*/ if (dbname_conninfo)
{
simple_string_list_append(&opt.database_names, dbname_conninfo);
num_dbs++;
pg_log_info("database name \"%s\" was extracted from the publisher connection string",
dbname_conninfo);
} else
{
pg_log_error("no database name specified");
pg_log_error_hint("Try \"%s --help\" for more information.",
progname); exit(1);
}
}
/* Number of object names must match number of databases */ if (num_pubs > 0 && num_pubs != num_dbs)
{
pg_log_error("wrong number of publication names specified");
pg_log_error_detail("The number of specified publication names (%d) must match the number of specified database names (%d).",
num_pubs, num_dbs); exit(1);
} if (num_subs > 0 && num_subs != num_dbs)
{
pg_log_error("wrong number of subscription names specified");
pg_log_error_detail("The number of specified subscription names (%d) must match the number of specified database names (%d).",
num_subs, num_dbs); exit(1);
} if (num_replslots > 0 && num_replslots != num_dbs)
{
pg_log_error("wrong number of replication slot names specified");
pg_log_error_detail("The number of specified replication slot names (%d) must match the number of specified database names (%d).",
num_replslots, num_dbs); exit(1);
}
/* Verify the object types specified for removal from the subscriber */ for (SimpleStringListCell *cell = opt.objecttypes_to_clean.head; cell; cell = cell->next)
{ if (pg_strcasecmp(cell->val, "publications") == 0)
dbinfos.objecttypes_to_clean |= OBJECTTYPE_PUBLICATIONS; else
{
pg_log_error("invalid object type \"%s\" specified for %s",
cell->val, "--clean");
pg_log_error_hint("The valid value is: \"%s\"", "publications"); exit(1);
}
}
/* Get the absolute path of pg_ctl and pg_resetwal on the subscriber */
pg_ctl_path = get_exec_path(argv[0], "pg_ctl");
pg_resetwal_path = get_exec_path(argv[0], "pg_resetwal");
/* Rudimentary check for a data directory */
check_data_directory(subscriber_dir);
/* Register a function to clean up objects in case of failure */
atexit(cleanup_objects_atexit);
/* *Checkifthesubscriberdatadirectoryhasthesamesystemidentifier *thanthepublisherdatadirectory.
*/
pub_sysid = get_primary_sysid(dbinfos.dbinfo[0].pubconninfo);
sub_sysid = get_standby_sysid(subscriber_dir); if (pub_sysid != sub_sysid)
pg_fatal("subscriber data directory is not a copy of the source database cluster");
/* *Thestandbyservermustnotberunning.Iftheserverisstartedunder *servicemanagerandpg_createsubscriberstopsit,theservicemanager *mightreacttothisactionandstarttheserveragain.Therefore, *refusetoproceediftheserverisrunningtoavoidpossiblefailures.
*/ if (stat(pidfile, &statbuf) == 0)
{
pg_log_error("standby server is running");
pg_log_error_hint("Stop the standby server and try again."); exit(1);
}
/* *Startashort-livedstandbyserverwithtemporaryparameters(provided *bycommand-lineoptions).Thegoalistoavoidconnectionsduringthe *transformationsteps.
*/
pg_log_info("starting the standby server with command-line options");
start_standby_server(&opt, true, false);
/* Check if the standby server is ready for logical replication */
check_subscriber(dbinfos.dbinfo);
/* Check if the primary server is ready for logical replication */
check_publisher(dbinfos.dbinfo);
/* Remove primary_slot_name if it exists on primary */
drop_primary_replication_slot(dbinfos.dbinfo, primary_slot_name);
/* Remove failover replication slots if they exist on subscriber */
drop_failover_replication_slots(dbinfos.dbinfo);
/* Stop the subscriber */
pg_log_info("stopping the subscriber");
stop_standby_server(subscriber_dir);
/* Change system identifier from subscriber */
modify_subscriber_sysid(&opt);
success = true;
pg_log_info("Done!");
return0;
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.71Bemerkung:
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Angebot
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.