| From: | Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> |
|---|---|
| To: | Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com> |
| Cc: | Srinath Reddy Sadipiralla <srinath2133(at)gmail(dot)com>, pgsql-hackers <pgsql-hackers(at)postgresql(dot)org> |
| Subject: | Re: Fix "unexpected logical decoding status change" error; from concurrent logical decoding activation |
| Date: | 2026-07-24 07:20:08 |
| Message-ID: | CAA4eK1JVkc2o6Ph60yW55N6jO01a-hM5Ay0OsDA8DhfL52gH2w@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
On Wed, Jul 22, 2026 at 7:08 PM Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:
>
> *
> - * CheckLogicalDecodingRequirements() must have already errored out if
> - * logical decoding is not enabled since we cannot enable the logical
> - * decoding status during recovery.
> + * The caller has already checked that logical decoding is enabled via
> + * CheckLogicalDecodingRequirements(), but the status could have been
> + * disabled concurrently before our slot being created: either by
> + * replaying an XLOG_LOGICAL_DECODING_STATUS_CHANGE record, or by
> + * UpdateLogicalDecodingStatusEndOfRecovery() upon promotion. We
> + * cannot enable logical decoding during recovery, so raise an error.
> */
> - Assert(IsLogicalDecodingEnabled());
> + if (!IsLogicalDecodingEnabled())
> + ereport(ERROR,
> + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
> + errmsg("logical decoding on standby requires \"effective_wal_level\"
> >= \"logical\" on the primary"),
> + errdetail("Logical decoding was concurrently disabled during the
> logical replication slot creation.")));
>
> It is not clear after reading the comment above this check what kind
> of interlocking would save us from concurrent deactivation by two ways
> mentioned by you immediately after this check?
>
I checked that before reaching here, we would have marked the slot as
in_use, so the invalidation will invalidate such a slot.
The other observation I had while looking at this patch was: On a
standby, InvalidateObsoleteReplicationSlots() can disable logical
decoding whenever it invalidates the last valid logical slot via
following check:
if (invalidated_logical && !found_valid_logicalslot)
RequestDisableLogicalDecoding();
RequestDisableLogicalDecoding() isn't guarded against recovery, so a
purely local invalidation (RS_INVAL_HORIZON/WAL_REMOVED/IDLE_TIMEOUT)
makes the standby disable decoding even though the primary still has
it enabled. The standby's status is supposed to follow the primary via
XLOG_LOGICAL_DECODING_STATUS_CHANGE replay, and there's no
self-healing since the primary never sends an "enable". So, won't that
be a problem because after that no new slots will be allowed to be
created on standby and slotsync also won't be able perform sync. Am, I
missing something? If not then probable the above check needs
additional check: "!RecoveryInProgress()".
--
With Regards,
Amit Kapila.
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Jakub Wartak | 2026-07-24 07:31:43 | Re: [WIP] Pipelined Recovery |
| Previous Message | Rui Zhao | 2026-07-24 07:18:26 | Re: [PATCH] Add pg_get_table_ddl() to reconstruct CREATE TABLE statements |