mirror of
https://github.com/postgres/postgres.git
synced 2025-08-24 09:27:52 +03:00
For cascading replication, wake physical and logical walsenders separately
Physical walsenders can't send data until it's been flushed; logical walsenders can't decode and send data until it's been applied. On the standby, the WAL is flushed first, which will only wake up physical walsenders; and then applied, which will only wake up logical walsenders. Previously, all walsenders were awakened when the WAL was flushed. That was fine for logical walsenders on the primary; but on the standby the flushed WAL would have been not applied yet, so logical walsenders were awakened too early. Per idea from Jeff Davis and Amit Kapila. Author: "Drouvot, Bertrand" <bertranddrouvot.pg@gmail.com> Reviewed-By: Jeff Davis <pgsql@j-davis.com> Reviewed-By: Robert Haas <robertmhaas@gmail.com> Reviewed-by: Amit Kapila <amit.kapila16@gmail.com> Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com> Discussion: https://postgr.es/m/CAA4eK1+zO5LUeisabX10c81LU-fWMKO4M9Wyg1cdkbW7Hqh6vQ@mail.gmail.com
This commit is contained in:
@@ -1935,6 +1935,31 @@ ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *repl
|
||||
XLogRecoveryCtl->lastReplayedTLI = *replayTLI;
|
||||
SpinLockRelease(&XLogRecoveryCtl->info_lck);
|
||||
|
||||
/* ------
|
||||
* Wakeup walsenders:
|
||||
*
|
||||
* On the standby, the WAL is flushed first (which will only wake up
|
||||
* physical walsenders) and then applied, which will only wake up logical
|
||||
* walsenders.
|
||||
*
|
||||
* Indeed, logical walsenders on standby can't decode and send data until
|
||||
* it's been applied.
|
||||
*
|
||||
* Physical walsenders don't need to be woken up during replay unless
|
||||
* cascading replication is allowed and time line change occurred (so that
|
||||
* they can notice that they are on a new time line).
|
||||
*
|
||||
* That's why the wake up conditions are for:
|
||||
*
|
||||
* - physical walsenders in case of new time line and cascade
|
||||
* replication is allowed
|
||||
* - logical walsenders in case cascade replication is allowed (could not
|
||||
* be created otherwise)
|
||||
* ------
|
||||
*/
|
||||
if (AllowCascadeReplication())
|
||||
WalSndWakeup(switchedTLI, true);
|
||||
|
||||
/*
|
||||
* If rm_redo called XLogRequestWalReceiverReply, then we wake up the
|
||||
* receiver so that it notices the updated lastReplayedEndRecPtr and sends
|
||||
@@ -1958,12 +1983,6 @@ ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *repl
|
||||
*/
|
||||
RemoveNonParentXlogFiles(xlogreader->EndRecPtr, *replayTLI);
|
||||
|
||||
/*
|
||||
* Wake up any walsenders to notice that we are on a new timeline.
|
||||
*/
|
||||
if (AllowCascadeReplication())
|
||||
WalSndWakeup();
|
||||
|
||||
/* Reset the prefetcher. */
|
||||
XLogPrefetchReconfigure();
|
||||
}
|
||||
@@ -3050,9 +3069,9 @@ ReadRecord(XLogPrefetcher *xlogprefetcher, int emode,
|
||||
{
|
||||
/*
|
||||
* When we find that WAL ends in an incomplete record, keep track
|
||||
* of that record. After recovery is done, we'll write a record to
|
||||
* indicate to downstream WAL readers that that portion is to be
|
||||
* ignored.
|
||||
* of that record. After recovery is done, we'll write a record
|
||||
* to indicate to downstream WAL readers that that portion is to
|
||||
* be ignored.
|
||||
*
|
||||
* However, when ArchiveRecoveryRequested = true, we're going to
|
||||
* switch to a new timeline at the end of recovery. We will only
|
||||
|
Reference in New Issue
Block a user