postgres/src/backend
Michael Paquier 2e57790836 Fix race with synchronous_standby_names at startup
synchronous_standby_names cannot be reloaded safely by backends, and the
checkpointer is in charge of updating a state in shared memory if the
GUC is enabled in WalSndCtl, to let the backends know if they should
wait or not for a given LSN.  This provides a strict control on the
timing of the waiting queues if the GUC is enabled or disabled, then
reloaded.  The checkpointer is also in charge of waking up the backends
that could be waiting for a LSN when the GUC is disabled.

This logic had a race condition at startup, where it would be possible
for backends to not wait for a LSN even if synchronous_standby_names is
enabled.  This would cause visibility issues with transactions that we
should be waiting for but they were not.  The problem lasts until the
checkpointer does its initial update of the shared memory state when it
loads synchronous_standby_names.

In order to take care of this problem, the shared memory state in
WalSndCtl is extended to detect if it has been initialized by the
checkpointer, and not only check if synchronous_standby_names is
defined.  In WalSndCtlData, sync_standbys_defined is renamed to
sync_standbys_status, a bits8 able to know about two states:
- If the shared memory state has been initialized.  This flag is set by
the checkpointer at startup once, and never removed.
- If synchronous_standby_names is known as defined in the shared memory
state.  This is the same as the previous sync_standbys_defined in
WalSndCtl.

This method gives a way for backends to decide what they should do until
the shared memory area is initialized, and they now ultimately fall back
to a check on the GUC value in this case, which is the best thing that
can be done.

Fortunately, SyncRepUpdateSyncStandbysDefined() is called immediately by
the checkpointer when this process starts, so the window is very narrow.
It is possible to enlarge the problematic window by making the
checkpointer wait at the beginning of SyncRepUpdateSyncStandbysDefined()
with a hardcoded sleep for example, and doing so has showed that a 2PC
visibility test is indeed failing.  On machines slow enough, this bug
would cause spurious failures.

In 17~, we have looked at the possibility of adding an injection point
to have a reproducible test, but as the problematic window happens at
early startup, we would need to invent a way to make an injection point
optionally persistent across restarts when attached, something that
would be fine for this case as it would involve the checkpointer.  This
issue is quite old, and can be reproduced on all the stable branches.

Author: Melnikov Maksim <m.melnikov@postgrespro.ru>
Co-authored-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/163fcbec-900b-4b07-beaa-d2ead8634bec@postgrespro.ru
Backpatch-through: 13
2025-04-11 10:00:21 +09:00
..
access Allow NOT NULL constraints to be added as NOT VALID 2025-04-07 19:19:50 +02:00
archive
backup Use XLOG_CONTROL_FILE macro consistently for control file name. 2025-04-07 09:27:33 +09:00
bootstrap
catalog Add function to get memory context stats for processes 2025-04-08 11:06:56 +02:00
commands Improve various new-to-v18 appendStringInfo calls 2025-04-11 10:07:22 +12:00
executor Fix uninitialized index information access during apply. 2025-04-08 15:35:42 +05:30
foreign
jit Allow NOT NULL constraints to be added as NOT VALID 2025-04-07 19:19:50 +02:00
lib
libpq
main Use thread-safe strftime_l() instead of strftime(). 2025-03-28 07:13:43 +01:00
nodes Speedup child EquivalenceMember lookup in planner 2025-04-08 18:09:57 +12:00
optimizer Update wording in optimizer/README for EquivalenceClasses 2025-04-10 17:33:58 +12:00
parser Allow NOT NULL constraints to be added as NOT VALID 2025-04-07 19:19:50 +02:00
partitioning
po
port
postmaster Fix a few oversights in the longer cancel keys patch 2025-04-09 13:11:42 +03:00
regex
replication Fix race with synchronous_standby_names at startup 2025-04-11 10:00:21 +09:00
rewrite
snowball
statistics
storage Cleanup of pg_numa.c 2025-04-09 21:50:17 +02:00
tcop Add function to get memory context stats for processes 2025-04-08 11:06:56 +02:00
tsearch
utils Add code comment explaining ins_since_vacuum and aborted inserts 2025-04-11 11:36:21 +12:00
.gitignore
common.mk
Makefile
meson.build
nls.mk