repmgr: improve standby clone when synchronous replication in use

Fixes GitHub #277
This commit is contained in:
Ian Barwick
2017-03-16 16:40:54 +09:00
parent 478407fd86
commit 0ef532dcff
4 changed files with 55 additions and 26 deletions

View File

@@ -6,6 +6,7 @@
repmgr: if replication slots in use, where possible delete slot on old repmgr: if replication slots in use, where possible delete slot on old
upstream node after following new upstream (Ian) upstream node after following new upstream (Ian)
repmgr: improve logging of rsync actions (Ian) repmgr: improve logging of rsync actions (Ian)
repmgr: improve `standby clone` when synchronous replication in use (Ian)
3.3 2016-12-27 3.3 2016-12-27
repmgr: always log to STDERR even if log facility defined (Ian) repmgr: always log to STDERR even if log facility defined (Ian)

View File

@@ -33,6 +33,7 @@ char repmgr_schema[MAXLEN] = "";
char repmgr_schema_quoted[MAXLEN] = ""; char repmgr_schema_quoted[MAXLEN] = "";
static int _get_node_record(PGconn *conn, char *cluster, char *sqlquery, t_node_info *node_info); static int _get_node_record(PGconn *conn, char *cluster, char *sqlquery, t_node_info *node_info);
static bool _set_config(PGconn *conn, const char *config_param, const char *sqlquery);
PGconn * PGconn *
_establish_db_connection(const char *conninfo, const bool exit_on_error, const bool log_notice, const bool verbose_only) _establish_db_connection(const char *conninfo, const bool exit_on_error, const bool log_notice, const bool verbose_only)
@@ -1150,19 +1151,12 @@ stop_backup(PGconn *conn, char *last_wal_segment)
} }
bool bool
set_config_bool(PGconn *conn, const char *config_param, bool state) _set_config(PGconn *conn, const char *config_param, const char *sqlquery)
{ {
char sqlquery[QUERY_STR_LEN];
PGresult *res; PGresult *res;
sqlquery_snprintf(sqlquery,
"SET %s TO %s",
config_param,
state ? "TRUE" : "FALSE");
log_verbose(LOG_DEBUG, "set_config_bool():\n%s\n", sqlquery);
res = PQexec(conn, sqlquery); res = PQexec(conn, sqlquery);
if (PQresultStatus(res) != PGRES_COMMAND_OK) if (PQresultStatus(res) != PGRES_COMMAND_OK)
@@ -1177,6 +1171,36 @@ set_config_bool(PGconn *conn, const char *config_param, bool state)
return true; return true;
} }
bool
set_config(PGconn *conn, const char *config_param, const char *config_value)
{
char sqlquery[QUERY_STR_LEN];
sqlquery_snprintf(sqlquery,
"SET %s TO '%s'",
config_param,
config_value);
log_verbose(LOG_DEBUG, "set_config():\n%s\n", sqlquery);
return _set_config(conn, config_param, sqlquery);
}
bool
set_config_bool(PGconn *conn, const char *config_param, bool state)
{
char sqlquery[QUERY_STR_LEN];
sqlquery_snprintf(sqlquery,
"SET %s TO %s",
config_param,
state ? "TRUE" : "FALSE");
log_verbose(LOG_DEBUG, "set_config_bool():\n%s\n", sqlquery);
return _set_config(conn, config_param, sqlquery);
}
/* /*
* witness_copy_node_records() * witness_copy_node_records()

View File

@@ -124,6 +124,7 @@ int get_slot_record(PGconn *conn, char *slot_name, t_replication_slot *record)
bool drop_replication_slot(PGconn *conn, char *slot_name); bool drop_replication_slot(PGconn *conn, char *slot_name);
bool start_backup(PGconn *conn, char *first_wal_segment, bool fast_checkpoint); bool start_backup(PGconn *conn, char *first_wal_segment, bool fast_checkpoint);
bool stop_backup(PGconn *conn, char *last_wal_segment); bool stop_backup(PGconn *conn, char *last_wal_segment);
bool set_config(PGconn *conn, const char *config_param, const char *config_value);
bool set_config_bool(PGconn *conn, const char *config_param, bool state); bool set_config_bool(PGconn *conn, const char *config_param, bool state);
bool witness_copy_node_records(PGconn *masterconn, PGconn *witnessconn, char *cluster_name); bool witness_copy_node_records(PGconn *masterconn, PGconn *witnessconn, char *cluster_name);
bool create_node_record(PGconn *conn, char *action, int node, char *type, int upstream_node, char *cluster_name, char *node_name, char *conninfo, int priority, char *slot_name, bool active); bool create_node_record(PGconn *conn, char *action, int node, char *type, int upstream_node, char *cluster_name, char *node_name, char *conninfo, int priority, char *slot_name, bool active);

View File

@@ -758,7 +758,7 @@ main(int argc, char **argv)
{ {
if (optind < argc) if (optind < argc)
{ {
if (runtime_options.host_param_provided == true) if (runtime_options.host[0])
{ {
PQExpBufferData additional_host_arg; PQExpBufferData additional_host_arg;
initPQExpBuffer(&additional_host_arg); initPQExpBuffer(&additional_host_arg);
@@ -2954,6 +2954,8 @@ do_standby_clone(void)
primary_conn = source_conn; primary_conn = source_conn;
} }
/* /*
* Sanity-check that the master node has a repmgr schema - if not * Sanity-check that the master node has a repmgr schema - if not
* present, fail with an error (unless -F/--force is used) * present, fail with an error (unless -F/--force is used)
@@ -2973,6 +2975,7 @@ do_standby_clone(void)
log_warning(_("expected repmgr schema '%s' not found on master server\n"), get_repmgr_schema()); log_warning(_("expected repmgr schema '%s' not found on master server\n"), get_repmgr_schema());
} }
/* Fetch the source's data directory */ /* Fetch the source's data directory */
if (get_pg_setting(source_conn, "data_directory", master_data_directory) == false) if (get_pg_setting(source_conn, "data_directory", master_data_directory) == false)
{ {
@@ -2994,6 +2997,8 @@ do_standby_clone(void)
log_hint(_("use -D/--data-dir to explicitly specify a data directory\n")); log_hint(_("use -D/--data-dir to explicitly specify a data directory\n"));
} }
/* /*
* Copy the source connection so that we have some default values, * Copy the source connection so that we have some default values,
* particularly stuff like passwords extracted from PGPASSFILE; * particularly stuff like passwords extracted from PGPASSFILE;
@@ -3017,6 +3022,18 @@ do_standby_clone(void)
strncpy(recovery_conninfo_str, upstream_node_record.conninfo_str, MAXLEN); strncpy(recovery_conninfo_str, upstream_node_record.conninfo_str, MAXLEN);
} }
} }
/* Finally, set `synchronous_commit` to `local` to avoid problems
* if synchronous commit is in use.
*/
if (primary_conn != NULL && PQstatus(primary_conn) == CONNECTION_OK)
{
if (set_config(primary_conn, "synchronous_commit", "local") == false)
{
exit(ERR_DB_QUERY);
}
}
} }
if (mode == barman && PQstatus(source_conn) != CONNECTION_OK) if (mode == barman && PQstatus(source_conn) != CONNECTION_OK)
@@ -3578,9 +3595,6 @@ do_standby_clone(void)
/* /*
* We must create some PGDATA subdirectories because they are * We must create some PGDATA subdirectories because they are
* not included in the Barman backup. * not included in the Barman backup.
*
* See class RsyncBackupExecutor in the Barman source (barman/backup_executor.py)
* for a definitive list of excluded directories.
*/ */
{ {
const char* const dirs[] = { const char* const dirs[] = {
@@ -3591,14 +3605,14 @@ do_standby_clone(void)
/* Only from 9.4 */ /* Only from 9.4 */
"pg_dynshmem", "pg_logical", "pg_logical/snapshots", "pg_logical/mappings", "pg_replslot", "pg_dynshmem", "pg_logical", "pg_logical/snapshots", "pg_logical/mappings", "pg_replslot",
/* Already in 9.3 */ /* Already in 9.3 */
"pg_notify", "pg_serial", "pg_snapshots", "pg_stat", "pg_stat_tmp", "pg_tblspc", "pg_serial", "pg_snapshots", "pg_stat", "pg_stat_tmp", "pg_tblspc",
"pg_twophase", "pg_xlog", 0 "pg_twophase", "pg_xlog", 0
}; };
const int vers[] = { const int vers[] = {
100000, 100000,
90500, 90500,
90400, 90400, 90400, 90400, 90400, 90400, 90400, 90400, 90400, 90400,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, -100000, 0 0, -100000, 0
}; };
for (i = 0; dirs[i]; i++) for (i = 0; dirs[i]; i++)
@@ -3628,17 +3642,6 @@ do_standby_clone(void)
initPQExpBuffer(&tablespace_map); initPQExpBuffer(&tablespace_map);
} }
/*
* From 9.1 default is to wait for a sync standby to ack, avoid that by
* turning off sync rep for this session
*/
if (set_config_bool(source_conn, "synchronous_commit", false) == false)
{
r = ERR_BAD_CONFIG;
retval = ERR_BAD_CONFIG;
goto stop_backup;
}
if (start_backup(source_conn, first_wal_segment, runtime_options.fast_checkpoint) == false) if (start_backup(source_conn, first_wal_segment, runtime_options.fast_checkpoint) == false)
{ {
r = ERR_BAD_BASEBACKUP; r = ERR_BAD_BASEBACKUP;