repmgrd: during failover, check if other nodes have seen the primary

In a situation where only some standbys are cut off from the primary,
a failover would result in a split brain/split cluster situation,
as it's likely one of the cut-off standbys will promote itself, and
other cut-off standbys (but not all standbys) will follow it.

To prevent this happening, interrogate the other sibiling nodes to
check whether they've seen the primary within a reasonably short interval;
if this is the case, do not take any failover action.

This feature is experimental.
This commit is contained in:
Ian Barwick
2019-02-23 12:59:08 +09:00
parent 07097575b1
commit b72c894db4
3 changed files with 50 additions and 6 deletions

View File

@@ -4781,6 +4781,7 @@ init_replication_info(ReplInfo *replication_info)
replication_info->replication_lag_time = 0;
replication_info->receiving_streamed_wal = true;
replication_info->wal_replay_paused = false;
replication_info->primary_last_seen = -1;
}
@@ -4807,7 +4808,8 @@ get_replication_info(PGconn *conn, ReplInfo *replication_info)
" END "
" END AS replication_lag_time, "
" last_wal_receive_lsn >= last_wal_replay_lsn AS receiving_streamed_wal, "
" wal_replay_paused "
" wal_replay_paused, "
" primary_last_seen "
" FROM ( "
" SELECT CURRENT_TIMESTAMP AS ts, "
" pg_catalog.pg_last_xact_replay_timestamp() AS last_xact_replay_timestamp, ");
@@ -4821,7 +4823,7 @@ get_replication_info(PGconn *conn, ReplInfo *replication_info)
" CASE WHEN pg_catalog.pg_is_in_recovery() IS FALSE "
" THEN FALSE "
" ELSE pg_catalog.pg_is_wal_replay_paused() "
" END AS wal_replay_paused ");
" END AS wal_replay_paused, ");
}
else
{
@@ -4843,10 +4845,14 @@ get_replication_info(PGconn *conn, ReplInfo *replication_info)
" CASE WHEN pg_catalog.pg_is_in_recovery() IS FALSE "
" THEN FALSE "
" ELSE pg_catalog.pg_is_xlog_replay_paused() "
" END AS wal_replay_paused ");
" END AS wal_replay_paused, ");
}
appendPQExpBufferStr(&query,
" CASE WHEN pg_catalog.pg_is_in_recovery() IS FALSE "
" THEN -1 "
" ELSE repmgr.get_primary_last_seen() "
" END AS primary_last_seen "
" ) q ");
log_verbose(LOG_DEBUG, "get_replication_info():\n%s", query.data);
@@ -4868,6 +4874,7 @@ get_replication_info(PGconn *conn, ReplInfo *replication_info)
replication_info->replication_lag_time = atoi(PQgetvalue(res, 0, 4));
replication_info->receiving_streamed_wal = atobool(PQgetvalue(res, 0, 5));
replication_info->wal_replay_paused = atobool(PQgetvalue(res, 0, 6));
replication_info->primary_last_seen = atoi(PQgetvalue(res, 0, 7));
}
termPQExpBuffer(&query);