mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-26 16:46:28 +00:00
Support "pg_promote()" function (PostgreSQL 12 and later)
This is an experimental feature.
This commit is contained in:
45
dbutils.c
45
dbutils.c
@@ -1928,6 +1928,51 @@ vacuum_table(PGconn *primary_conn, const char *table)
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For use in PostgreSQL 12 and later
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
promote_standby(PGconn *conn, bool wait, int wait_seconds)
|
||||||
|
{
|
||||||
|
PQExpBufferData query;
|
||||||
|
bool success = true;
|
||||||
|
PGresult *res = NULL;
|
||||||
|
|
||||||
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
|
appendPQExpBuffer(&query,
|
||||||
|
"SELECT pg_catalog.pg_promote(wait := %s",
|
||||||
|
wait ? "TRUE" : "FALSE");
|
||||||
|
|
||||||
|
if (wait_seconds > 0)
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&query,
|
||||||
|
", wait_seconds := %i",
|
||||||
|
wait_seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
appendPQExpBufferStr(&query, ")");
|
||||||
|
|
||||||
|
res = PQexec(conn, query.data);
|
||||||
|
|
||||||
|
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
|
{
|
||||||
|
log_db_error(conn, query.data, _("unable to execute pg_promote()"));
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* NOTE: if "wait" is false, pg_promote() will always return true */
|
||||||
|
success = atobool(PQgetvalue(res, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
termPQExpBuffer(&query);
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ===================== */
|
/* ===================== */
|
||||||
/* Node record functions */
|
/* Node record functions */
|
||||||
/* ===================== */
|
/* ===================== */
|
||||||
|
|||||||
@@ -424,7 +424,7 @@ ExtensionStatus get_repmgr_extension_status(PGconn *conn);
|
|||||||
/* node management functions */
|
/* node management functions */
|
||||||
void checkpoint(PGconn *conn);
|
void checkpoint(PGconn *conn);
|
||||||
bool vacuum_table(PGconn *conn, const char *table);
|
bool vacuum_table(PGconn *conn, const char *table);
|
||||||
|
bool promote_standby(PGconn *conn, bool wait, int wait_seconds);
|
||||||
|
|
||||||
/* node record functions */
|
/* node record functions */
|
||||||
t_server_type parse_node_type(const char *type);
|
t_server_type parse_node_type(const char *type);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ static char local_repmgr_tmp_directory[MAXPGPATH];
|
|||||||
static char datadir_list_filename[MAXLEN];
|
static char datadir_list_filename[MAXLEN];
|
||||||
static char barman_command_buf[MAXLEN] = "";
|
static char barman_command_buf[MAXLEN] = "";
|
||||||
|
|
||||||
static void _do_standby_promote_internal(PGconn *conn);
|
static void _do_standby_promote_internal(PGconn *conn, int server_version_num);
|
||||||
static void _do_create_recovery_conf(void);
|
static void _do_create_recovery_conf(void);
|
||||||
|
|
||||||
static void check_barman_config(void);
|
static void check_barman_config(void);
|
||||||
@@ -1956,13 +1956,14 @@ do_standby_promote(void)
|
|||||||
RecoveryType recovery_type = RECTYPE_UNKNOWN;
|
RecoveryType recovery_type = RECTYPE_UNKNOWN;
|
||||||
|
|
||||||
int existing_primary_id = UNKNOWN_NODE_ID;
|
int existing_primary_id = UNKNOWN_NODE_ID;
|
||||||
|
int server_version_num = UNKNOWN_SERVER_VERSION_NUM;
|
||||||
|
|
||||||
conn = establish_db_connection(config_file_options.conninfo, true);
|
conn = establish_db_connection(config_file_options.conninfo, true);
|
||||||
|
|
||||||
log_verbose(LOG_INFO, _("connected to standby, checking its state"));
|
log_verbose(LOG_INFO, _("connected to standby, checking its state"));
|
||||||
|
|
||||||
/* Verify that standby is a supported server version */
|
/* Verify that standby is a supported server version */
|
||||||
check_server_version(conn, "standby", true, NULL);
|
server_version_num = check_server_version(conn, "standby", true, NULL);
|
||||||
|
|
||||||
/* Check we are in a standby node */
|
/* Check we are in a standby node */
|
||||||
recovery_type = get_recovery_type(conn);
|
recovery_type = get_recovery_type(conn);
|
||||||
@@ -2008,16 +2009,14 @@ do_standby_promote(void)
|
|||||||
|
|
||||||
PQfinish(current_primary_conn);
|
PQfinish(current_primary_conn);
|
||||||
|
|
||||||
_do_standby_promote_internal(conn);
|
_do_standby_promote_internal(conn, server_version_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_do_standby_promote_internal(PGconn *conn)
|
_do_standby_promote_internal(PGconn *conn, int server_version_num)
|
||||||
{
|
{
|
||||||
char script[MAXLEN];
|
int i;
|
||||||
int r,
|
|
||||||
i;
|
|
||||||
bool promote_success = false;
|
bool promote_success = false;
|
||||||
PQExpBufferData details;
|
PQExpBufferData details;
|
||||||
|
|
||||||
@@ -2049,24 +2048,51 @@ _do_standby_promote_internal(PGconn *conn)
|
|||||||
* `pg_ctl promote` returns immediately and (prior to 10.0) has no -w
|
* `pg_ctl promote` returns immediately and (prior to 10.0) has no -w
|
||||||
* option so we can't be sure when or if the promotion completes. For now
|
* option so we can't be sure when or if the promotion completes. For now
|
||||||
* we'll poll the server until the default timeout (60 seconds)
|
* we'll poll the server until the default timeout (60 seconds)
|
||||||
|
*
|
||||||
|
* For PostgreSQL 12+, use the pg_promote() function - note this is
|
||||||
|
* experimental
|
||||||
*/
|
*/
|
||||||
|
|
||||||
get_server_action(ACTION_PROMOTE, script, (char *) data_dir);
|
|
||||||
|
|
||||||
log_notice(_("promoting standby to primary"));
|
log_notice(_("promoting standby to primary"));
|
||||||
log_detail(_("promoting server \"%s\" (ID: %i) using \"%s\""),
|
|
||||||
local_node_record.node_name,
|
|
||||||
local_node_record.node_id,
|
|
||||||
script);
|
|
||||||
log_detail(_("waiting up to %i seconds (parameter \"promote_check_timeout\") for promotion to complete"),
|
|
||||||
config_file_options.promote_check_timeout);
|
|
||||||
|
|
||||||
r = system(script);
|
if (server_version_num >= 120000)
|
||||||
if (r != 0)
|
|
||||||
{
|
{
|
||||||
log_error(_("unable to promote server from standby to primary"));
|
log_detail(_("promoting server \"%s\" (ID: %i) using pg_promote()"),
|
||||||
exit(ERR_PROMOTION_FAIL);
|
local_node_record.node_name,
|
||||||
|
local_node_record.node_id);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We'll check for promotion success ourselves, but will abort
|
||||||
|
* if some unrecoverable error prevented the function from being
|
||||||
|
* executed.
|
||||||
|
*/
|
||||||
|
if (!promote_standby(conn, false, 0))
|
||||||
|
{
|
||||||
|
log_error(_("unable to promote server from standby to primary"));
|
||||||
|
exit(ERR_PROMOTION_FAIL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char script[MAXLEN];
|
||||||
|
int r;
|
||||||
|
|
||||||
|
get_server_action(ACTION_PROMOTE, script, (char *) data_dir);
|
||||||
|
|
||||||
|
log_detail(_("promoting server \"%s\" (ID: %i) using \"%s\""),
|
||||||
|
local_node_record.node_name,
|
||||||
|
local_node_record.node_id,
|
||||||
|
script);
|
||||||
|
|
||||||
|
r = system(script);
|
||||||
|
if (r != 0)
|
||||||
|
{
|
||||||
|
log_error(_("unable to promote server from standby to primary"));
|
||||||
|
exit(ERR_PROMOTION_FAIL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_notice(_("waiting up to %i seconds (parameter \"promote_check_timeout\") for promotion to complete"),
|
||||||
|
config_file_options.promote_check_timeout);
|
||||||
|
|
||||||
for (i = 0; i < config_file_options.promote_check_timeout; i += config_file_options.promote_check_interval)
|
for (i = 0; i < config_file_options.promote_check_timeout; i += config_file_options.promote_check_interval)
|
||||||
{
|
{
|
||||||
@@ -2807,6 +2833,7 @@ do_standby_switchover(void)
|
|||||||
PGconn *local_conn = NULL;
|
PGconn *local_conn = NULL;
|
||||||
PGconn *remote_conn = NULL;
|
PGconn *remote_conn = NULL;
|
||||||
|
|
||||||
|
int server_version_num = UNKNOWN_SERVER_VERSION_NUM;
|
||||||
t_node_info local_node_record = T_NODE_INFO_INITIALIZER;
|
t_node_info local_node_record = T_NODE_INFO_INITIALIZER;
|
||||||
|
|
||||||
/* the remote server is the primary to be demoted */
|
/* the remote server is the primary to be demoted */
|
||||||
@@ -2866,6 +2893,9 @@ do_standby_switchover(void)
|
|||||||
|
|
||||||
local_conn = establish_db_connection(config_file_options.conninfo, true);
|
local_conn = establish_db_connection(config_file_options.conninfo, true);
|
||||||
|
|
||||||
|
/* Verify that standby is a supported server version */
|
||||||
|
server_version_num = check_server_version(local_conn, "standby", true, NULL);
|
||||||
|
|
||||||
record_status = get_node_record(local_conn, config_file_options.node_id, &local_node_record);
|
record_status = get_node_record(local_conn, config_file_options.node_id, &local_node_record);
|
||||||
if (record_status != RECORD_FOUND)
|
if (record_status != RECORD_FOUND)
|
||||||
{
|
{
|
||||||
@@ -3944,7 +3974,7 @@ do_standby_switchover(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* promote standby (local node) */
|
/* promote standby (local node) */
|
||||||
_do_standby_promote_internal(local_conn);
|
_do_standby_promote_internal(local_conn, server_version_num);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user