Reset hot standby xmin on master after restart

Hot_standby_feedback could be reset by reload and worked correctly, but if
the server was restarted rather than reloaded the xmin was not reset.
Force reset always if hot_standby_feedback is enabled at startup.

Ants Aasma, Craig Ringer

Reported-by: Ants Aasma
This commit is contained in:
Simon Riggs 2017-01-26 18:14:02 +00:00
parent 9d4ca01314
commit ec4b975016
2 changed files with 34 additions and 8 deletions

View File

@ -1167,7 +1167,10 @@ XLogWalRcvSendReply(bool force, bool requestReply)
* in case they don't have a watch. * in case they don't have a watch.
* *
* If the user disables feedback, send one final message to tell sender * If the user disables feedback, send one final message to tell sender
* to forget about the xmin on this standby. * to forget about the xmin on this standby. We also send this message
* on first connect because a previous connection might have set xmin
* on a replication slot. (If we're not using a slot it's harmless to
* send a feedback message explicitly setting InvalidTransactionId).
*/ */
static void static void
XLogWalRcvSendHSFeedback(bool immed) XLogWalRcvSendHSFeedback(bool immed)
@ -1177,7 +1180,8 @@ XLogWalRcvSendHSFeedback(bool immed)
uint32 nextEpoch; uint32 nextEpoch;
TransactionId xmin; TransactionId xmin;
static TimestampTz sendTime = 0; static TimestampTz sendTime = 0;
static bool master_has_standby_xmin = false; /* initially true so we always send at least one feedback message */
static bool master_has_standby_xmin = true;
/* /*
* If the user doesn't want status to be reported to the master, be sure * If the user doesn't want status to be reported to the master, be sure
@ -1202,14 +1206,17 @@ XLogWalRcvSendHSFeedback(bool immed)
} }
/* /*
* If Hot Standby is not yet active there is nothing to send. Check this * If Hot Standby is not yet accepting connections there is nothing to
* after the interval has expired to reduce number of calls. * send. Check this after the interval has expired to reduce number of
* calls.
*
* Bailing out here also ensures that we don't send feedback until we've
* read our own replication slot state, so we don't tell the master to
* discard needed xmin or catalog_xmin from any slots that may exist
* on this replica.
*/ */
if (!HotStandbyActive()) if (!HotStandbyActive())
{
Assert(!master_has_standby_xmin);
return; return;
}
/* /*
* Make the expensive call to get the oldest xmin once we are certain * Make the expensive call to get the oldest xmin once we are certain

View File

@ -3,7 +3,7 @@ use strict;
use warnings; use warnings;
use PostgresNode; use PostgresNode;
use TestLib; use TestLib;
use Test::More tests => 22; use Test::More tests => 24;
# Initialize master node # Initialize master node
my $node_master = get_new_node('master'); my $node_master = get_new_node('master');
@ -161,3 +161,22 @@ is($catalog_xmin, '', 'non-cascaded slot xmin still null with hs_feedback reset'
($xmin, $catalog_xmin) = get_slot_xmins($node_standby_1, $slotname_2); ($xmin, $catalog_xmin) = get_slot_xmins($node_standby_1, $slotname_2);
is($xmin, '', 'cascaded slot xmin null with hs feedback reset'); is($xmin, '', 'cascaded slot xmin null with hs feedback reset');
is($catalog_xmin, '', 'cascaded slot xmin still null with hs_feedback reset'); is($catalog_xmin, '', 'cascaded slot xmin still null with hs_feedback reset');
diag "re-enabling hot_standby_feedback and disabling while stopped";
$node_standby_2->safe_psql('postgres', 'ALTER SYSTEM SET hot_standby_feedback = on;');
$node_standby_2->reload;
$node_master->safe_psql('postgres', qq[INSERT INTO tab_int VALUES (11000);]);
replay_check();
$node_standby_2->safe_psql('postgres', 'ALTER SYSTEM SET hot_standby_feedback = off;');
$node_standby_2->stop;
($xmin, $catalog_xmin) = get_slot_xmins($node_standby_1, $slotname_2);
isnt($xmin, '', 'cascaded slot xmin non-null with postgres shut down');
# Xmin from a previous run should be cleared on startup.
$node_standby_2->start;
($xmin, $catalog_xmin) = get_slot_xmins($node_standby_1, $slotname_2);
is($xmin, '', 'cascaded slot xmin reset after startup with hs feedback reset');