mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-26 08:36:30 +00:00
"standby follow": simplify check when follow target has higher timeline
No need for a CHECKPOINT here, which simplifies things considerably.
This commit is contained in:
@@ -22,6 +22,17 @@
|
|||||||
default location; no additional arguments are required.
|
default location; no additional arguments are required.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
By default &repmgr; will attempt to attach the standby to the current primary.
|
||||||
|
If <option>--upstream-node-id</option> is provided, &repmgr; will attempt
|
||||||
|
to attach the standby to the specified node, which can be another standby.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
This command will force a restart of the standby server, which must be
|
||||||
|
running.
|
||||||
|
</para>
|
||||||
|
|
||||||
<tip>
|
<tip>
|
||||||
<para>
|
<para>
|
||||||
To re-add an inactive node to the replication cluster, use
|
To re-add an inactive node to the replication cluster, use
|
||||||
@@ -29,29 +40,25 @@
|
|||||||
</para>
|
</para>
|
||||||
</tip>
|
</tip>
|
||||||
|
|
||||||
<para>
|
|
||||||
This command will force a restart of the standby server, which must be
|
|
||||||
running. Additionally, in order to be able to verify whether the standby
|
|
||||||
can attach to the upstream node, a <command>CHECKPOINT</command> will
|
|
||||||
be executed - this requires superuser privileges, and will be executed
|
|
||||||
even with the <option>--dry-run</option> option.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<important>
|
|
||||||
<para>
|
|
||||||
If the &repmgr; database user is not a superuser, it will not be possible
|
|
||||||
to execute <command>CHECKPOINT</command>, meaning &repmgr; may not be
|
|
||||||
able to determine whether the upstream node can be followed.
|
|
||||||
</para>
|
|
||||||
</important>
|
|
||||||
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<command>repmgr standby follow</command> will wait up to
|
<command>repmgr standby follow</command> will wait up to
|
||||||
<varname>standby_follow_timeout</varname> seconds (default: <literal>30</literal>)
|
<varname>standby_follow_timeout</varname> seconds (default: <literal>30</literal>)
|
||||||
to verify the standby has actually connected to the new primary.
|
to verify the standby has actually connected to the new upstream node.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
If <option>recovery_min_apply_delay</option> is set for the standby, it
|
||||||
|
will not attach to the new upstream node until it has replayed available
|
||||||
|
WAL.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Conversely, if the standby is attached follows another standby
|
||||||
|
with <option>recovery_min_apply_delay</option> set, that standby's replay
|
||||||
|
state may actually be behind that of its new downstream node.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
|||||||
@@ -2633,8 +2633,6 @@ do_standby_follow(void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
XLogRecPtr local_xlogpos = get_current_lsn(local_conn);
|
XLogRecPtr local_xlogpos = get_current_lsn(local_conn);
|
||||||
bool can_follow = true;
|
|
||||||
XLogRecPtr local_min_recovery_location = InvalidXLogRecPtr;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* upstream has higher timeline - check where it forked off from this node's timeline
|
* upstream has higher timeline - check where it forked off from this node's timeline
|
||||||
@@ -2650,8 +2648,6 @@ do_standby_follow(void)
|
|||||||
exit(ERR_FOLLOW_FAIL);
|
exit(ERR_FOLLOW_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
local_min_recovery_location = get_min_recovery_location(config_file_options.data_directory);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local node has proceeded beyond the follow target's fork, so we
|
* Local node has proceeded beyond the follow target's fork, so we
|
||||||
* definitely can't attach.
|
* definitely can't attach.
|
||||||
@@ -2660,59 +2656,31 @@ do_standby_follow(void)
|
|||||||
* not contain all changes which are being replayed to this standby.
|
* not contain all changes which are being replayed to this standby.
|
||||||
*/
|
*/
|
||||||
if (local_xlogpos > follow_target_history->end)
|
if (local_xlogpos > follow_target_history->end)
|
||||||
{
|
|
||||||
can_follow = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* XXX can we establish what the window is where we *need* to execute
|
|
||||||
* a CHECKPOINT?
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Execute CHECKPOINT on the local node - we'll need this to update
|
|
||||||
* the pg_control file so we can compare positions with the new upstream.
|
|
||||||
* There is no way of avoiding this for --dry-run.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (is_superuser_connection(local_conn, NULL) == true)
|
|
||||||
{
|
|
||||||
log_notice(_("executing CHECKPOINT"));
|
|
||||||
checkpoint(local_conn);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_warning(_("connection is not a superuser, unable to execute CHECKPOINT"));
|
|
||||||
log_detail(_("a CHECKPOINT is required in order to compare local and follow target states"));
|
|
||||||
}
|
|
||||||
|
|
||||||
log_debug("upstream tli: %i; branch LSN: %X/%X",
|
|
||||||
follow_target_history->tli, format_lsn(follow_target_history->end));
|
|
||||||
|
|
||||||
if (follow_target_history->end < local_min_recovery_location)
|
|
||||||
can_follow = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (can_follow == false)
|
|
||||||
{
|
{
|
||||||
log_error(_("this node cannot attach to follow target node %i"),
|
log_error(_("this node cannot attach to follow target node %i"),
|
||||||
follow_target_node_id);
|
follow_target_node_id);
|
||||||
log_detail(_("follow target server's timeline %i forked off current database system timeline %i before current recovery point %X/%X\n"),
|
log_detail(_("follow target server's timeline %i forked off current database system timeline %i before current recovery point %X/%X\n"),
|
||||||
local_identification.timeline + 1,
|
local_identification.timeline + 1,
|
||||||
local_identification.timeline,
|
local_identification.timeline,
|
||||||
format_lsn(local_min_recovery_location));
|
format_lsn(local_xlogpos));
|
||||||
|
|
||||||
PQfinish(follow_target_conn);
|
PQfinish(follow_target_conn);
|
||||||
PQfinish(follow_target_repl_conn);
|
|
||||||
PQfinish(local_conn);
|
PQfinish(local_conn);
|
||||||
exit(ERR_FOLLOW_FAIL);
|
exit(ERR_FOLLOW_FAIL);
|
||||||
}
|
}
|
||||||
|
if (runtime_options.dry_run == true)
|
||||||
|
{
|
||||||
|
log_info(_("local node %i can follow target node %i"),
|
||||||
|
config_file_options.node_id,
|
||||||
|
follow_target_node_id);
|
||||||
|
log_detail(_("local node's recovery point: %X/%X; follow target node's fork point: %X/%X"),
|
||||||
|
format_lsn(local_xlogpos),
|
||||||
|
format_lsn(follow_target_history->end));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PQfinish(local_conn);
|
PQfinish(local_conn);
|
||||||
|
|
||||||
PQfinish(follow_target_repl_conn);
|
PQfinish(follow_target_repl_conn);
|
||||||
|
|
||||||
if (runtime_options.dry_run == true)
|
if (runtime_options.dry_run == true)
|
||||||
|
|||||||
Reference in New Issue
Block a user