mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
Avoid unnecessary end-of-recovery barrier waits
Commit 67c20979ce made end-of-recovery processing emit a process signal
barrier and wait for all processes to refresh their cached logical WAL
logging state. This can hold up promotion indefinitely if a backend
cannot process the barrier, for example while blocked sending data to
a client that has stopped reading.
At wal_level=logical, logical WAL logging is enabled regardless of the
cached state, so no cache synchronization is needed. Skip emitting and
waiting for the barrier in this case.
When logical decoding will be disabled after recovery, stale caches
can only cause extra logical information to be written to WAL, which is
safe. Still emit the barrier so processes update their caches
asynchronously, but no longer wait for it to complete.
These changes allow promotion to finish without waiting for unresponsive
backends to process this barrier in either case. Retain the wait in
other cases, even if the shared state has not changed, to prevent
processes with stale caches from omitting required logical information
after recovery.
Reported-by: shihao zhong <zhong950419@gmail.com>
Author: Fujii Masao <masao.fujii@gmail.com>
Author: Manuel Reyes Bravo <manuelreyesbravo@gmail.com>
Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com>
Discussion: https://postgr.es/m/CAGRkXqToBk9c2sPAgha-kCgxJhVwn90j1sCyUXrvydq51LKAqA@mail.gmail.com
Backpatch-through: 19
This commit is contained in:
@@ -664,9 +664,9 @@ DisableLogicalDecoding(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates the logical decoding status at end of recovery, and ensures that
|
||||
* all running processes have the updated XLogLogicalInfo status. This
|
||||
* function must be called before accepting writes.
|
||||
* Update the logical decoding status at end of recovery, synchronizing
|
||||
* process-local WAL logging state when necessary. This function must
|
||||
* be called before accepting writes.
|
||||
*/
|
||||
void
|
||||
UpdateLogicalDecodingStatusEndOfRecovery(void)
|
||||
@@ -746,16 +746,25 @@ UpdateLogicalDecodingStatusEndOfRecovery(void)
|
||||
LWLockRelease(LogicalDecodingControlLock);
|
||||
|
||||
/*
|
||||
* Ensure all running processes have the updated status. We don't need to
|
||||
* wait for running transactions to finish as we don't accept any writes
|
||||
* yet. On the other hand, we need to wait for synchronizing
|
||||
* XLogLogicalInfo even if we've not updated the status above as the
|
||||
* status have been turned on and off during recovery, having running
|
||||
* processes have different status on their local caches.
|
||||
* With wal_level = logical, XLogLogicalInfoActive() is always true, so no
|
||||
* barrier is needed.
|
||||
*
|
||||
* Otherwise, notify all processes to refresh XLogLogicalInfo. Wait only
|
||||
* if new_status is true, even if the shared status is unchanged, since
|
||||
* recovery may have left stale caches. Writes are not yet allowed, so we
|
||||
* need not wait for running transactions to finish.
|
||||
*
|
||||
* If new_status is false, stale caches only cause extra logical
|
||||
* information in WAL, which is safe (see DisableLogicalDecoding()).
|
||||
*/
|
||||
if (IsUnderPostmaster)
|
||||
WaitForProcSignalBarrier(
|
||||
EmitProcSignalBarrier(PROCSIGNAL_BARRIER_UPDATE_XLOG_LOGICAL_INFO));
|
||||
if (IsUnderPostmaster && wal_level != WAL_LEVEL_LOGICAL)
|
||||
{
|
||||
uint64 generation;
|
||||
|
||||
generation = EmitProcSignalBarrier(PROCSIGNAL_BARRIER_UPDATE_XLOG_LOGICAL_INFO);
|
||||
if (new_status)
|
||||
WaitForProcSignalBarrier(generation);
|
||||
}
|
||||
|
||||
INJECTION_POINT("startup-logical-decoding-status-change-end-of-recovery", NULL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user