Skip to content

Commit 2dde11a

Browse files
Reset master xmin when hot_standby_feedback disabled.
If walsender has xmin of standby then ensure we reset the value to 0 when we change from hot_standby_feedback=on to hot_standby_feedback=off.
1 parent f18858d commit 2dde11a

File tree

3 files changed

+42
-13
lines changed

3 files changed

+42
-13
lines changed

doc/src/sgml/protocol.sgml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1617,7 +1617,10 @@ The commands accepted in walsender mode are:
16171617
</term>
16181618
<listitem>
16191619
<para>
1620-
The standby's current xmin.
1620+
The standby's current xmin. This may be 0, if the standby is
1621+
sending notification that Hot Standby feedback will no
1622+
longer be sent on this connection. Later non-zero messages may
1623+
reinitiate the feedback mechanism.
16211624
</para>
16221625
</listitem>
16231626
</varlistentry>

src/backend/replication/walreceiver.c

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <signal.h>
3939
#include <unistd.h>
4040

41+
#include "access/transam.h"
4142
#include "access/xlog_internal.h"
4243
#include "libpq/pqsignal.h"
4344
#include "miscadmin.h"
@@ -123,7 +124,7 @@ static void XLogWalRcvProcessMsg(unsigned char type, char *buf, Size len);
123124
static void XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr);
124125
static void XLogWalRcvFlush(bool dying);
125126
static void XLogWalRcvSendReply(void);
126-
static void XLogWalRcvSendHSFeedback(void);
127+
static void XLogWalRcvSendHSFeedback(bool immed);
127128
static void ProcessWalSndrMessage(XLogRecPtr walEnd, TimestampTz sendTime);
128129

129130
/* Signal handlers */
@@ -312,6 +313,7 @@ WalReceiverMain(void)
312313
{
313314
got_SIGHUP = false;
314315
ProcessConfigFile(PGC_SIGHUP);
316+
XLogWalRcvSendHSFeedback(true);
315317
}
316318

317319
/* Wait a while for data to arrive */
@@ -340,7 +342,7 @@ WalReceiverMain(void)
340342
* master anyway, to report any progress in applying WAL.
341343
*/
342344
XLogWalRcvSendReply();
343-
XLogWalRcvSendHSFeedback();
345+
XLogWalRcvSendHSFeedback(false);
344346
}
345347
}
346348
}
@@ -621,7 +623,7 @@ XLogWalRcvFlush(bool dying)
621623
if (!dying)
622624
{
623625
XLogWalRcvSendReply();
624-
XLogWalRcvSendHSFeedback();
626+
XLogWalRcvSendHSFeedback(false);
625627
}
626628
}
627629
}
@@ -681,45 +683,62 @@ XLogWalRcvSendReply(void)
681683
/*
682684
* Send hot standby feedback message to primary, plus the current time,
683685
* in case they don't have a watch.
686+
*
687+
* If the user disables feedback, send one final message to tell sender
688+
* to forget about the xmin on this standby.
684689
*/
685690
static void
686-
XLogWalRcvSendHSFeedback(void)
691+
XLogWalRcvSendHSFeedback(bool immed)
687692
{
688693
char buf[sizeof(StandbyHSFeedbackMessage) + 1];
689694
TimestampTz now;
690695
TransactionId nextXid;
691696
uint32 nextEpoch;
692697
TransactionId xmin;
698+
static TimestampTz sendTime = 0;
699+
static bool master_has_standby_xmin = false;
693700

694701
/*
695702
* If the user doesn't want status to be reported to the master, be sure
696703
* to exit before doing anything at all.
697704
*/
698-
if (wal_receiver_status_interval <= 0 || !hot_standby_feedback)
705+
if ((wal_receiver_status_interval <= 0 || !hot_standby_feedback) &&
706+
!master_has_standby_xmin)
699707
return;
700708

701709
/* Get current timestamp. */
702710
now = GetCurrentTimestamp();
703711

704-
/*
705-
* Send feedback at most once per wal_receiver_status_interval.
706-
*/
707-
if (!TimestampDifferenceExceeds(feedback_message.sendTime, now,
712+
if (!immed)
713+
{
714+
/*
715+
* Send feedback at most once per wal_receiver_status_interval.
716+
*/
717+
if (!TimestampDifferenceExceeds(sendTime, now,
708718
wal_receiver_status_interval * 1000))
709-
return;
719+
return;
720+
}
721+
722+
sendTime = now;
710723

711724
/*
712725
* If Hot Standby is not yet active there is nothing to send. Check this
713726
* after the interval has expired to reduce number of calls.
714727
*/
715728
if (!HotStandbyActive())
729+
{
730+
Assert(!master_has_standby_xmin);
716731
return;
732+
}
717733

718734
/*
719735
* Make the expensive call to get the oldest xmin once we are certain
720736
* everything else has been checked.
721737
*/
722-
xmin = GetOldestXmin(true, false);
738+
if (hot_standby_feedback)
739+
xmin = GetOldestXmin(true, false);
740+
else
741+
xmin = InvalidTransactionId;
723742

724743
/*
725744
* Get epoch and adjust if nextXid and oldestXmin are different sides of
@@ -744,6 +763,10 @@ XLogWalRcvSendHSFeedback(void)
744763
buf[0] = 'h';
745764
memcpy(&buf[1], &feedback_message, sizeof(StandbyHSFeedbackMessage));
746765
walrcv_send(buf, sizeof(StandbyHSFeedbackMessage) + 1);
766+
if (TransactionIdIsValid(xmin))
767+
master_has_standby_xmin = true;
768+
else
769+
master_has_standby_xmin = false;
747770
}
748771

749772
/*

src/backend/replication/walsender.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,9 +656,12 @@ ProcessStandbyHSFeedbackMessage(void)
656656
reply.xmin,
657657
reply.epoch);
658658

659-
/* Ignore invalid xmin (can't actually happen with current walreceiver) */
659+
/* Unset WalSender's xmin if the feedback message value is invalid */
660660
if (!TransactionIdIsNormal(reply.xmin))
661+
{
662+
MyPgXact->xmin = InvalidTransactionId;
661663
return;
664+
}
662665

663666
/*
664667
* Check that the provided xmin/epoch are sane, that is, not in the future

0 commit comments

Comments
 (0)