Re: Recovery conflict resolution misses backends that import snapshots

From: Scott Ray <scott(at)scottray(dot)io>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Michael Paquier <michael(at)paquier(dot)xyz>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, Kuroda, Hayato/黒田 隼人 <kuroda(dot)hayato(at)fujitsu(dot)com>, Bertrand Drouvot <bertranddrouvot(dot)pg(at)gmail(dot)com>
Subject: Re: Recovery conflict resolution misses backends that import snapshots
Date: 2026-08-01 22:22:54
Message-ID: BHhAG3NY-VN-rhDMxrr4COSdUJWGBS8OOnJv7H6pCe5te-hqo20T-5zPc1WnXt4I5X8YQC3fv_6Rcddbix0t9k3I4qEb68JcDpNc_2VQYEo=@scottray.io
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Monday, July 27th, 2026 at 9:57 PM, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> wrote:

> I think we should at least have CFI in this loop so that it responds
> to promotion, shutdown, etc.

If the goal is to make the standby responsive to shutdown, we should
add ProcessStartupProcInterrupts(), which is already called elsewhere
during redo: xlog_redo() -> CheckRequiredParameterValues() ->
RecoveryRequiresIntParameter() -> ProcessStartupProcInterrupts()
in a loop. CHECK_FOR_INTERRUPTS() doesn't handle shutdown.

If the target is promotion, then we could use CheckForStandbyTrigger().
Conflict resolution occurs while the standby is processing a record,
and from what I can tell, responding to promotion after beginning to
apply the record but before finishing is unprecedented and would force
the standby to decide what to do with the partially-applied record.

The attached v2 calls ProcessStartupProcInterrupts(), and I confirmed
that the standby shuts down promptly when signaled.

On Mon, Jul 27, 2026 at 5:19 AM Michael Paquier
<michael(at)paquier(dot)xyz> wrote:
>
> Adding a code pattern that could potentially cause this code path to
> loop infinitely is not what I would call a principled approach, I
> would call it a risky one.

I tried to cause an infinite loop using a standby with
max_standby_streaming_delay = 5s, max_connections = 400, and a pool of
clients that relays one old snapshot forward as fast as it can:

t= 1.1s 212 conflicting VXIDs
t= 5.5s 363 population stops growing, no connection slots left
t= 6.6s 277 cutoff has passed, cancellation begins
t= 7.7s 190
t= 8.8s 105
t= 9.9s 16
t=11.0s 0 replay resumes

The standby begins killing VXIDs and kills them too fast for a
sustained relay - at least on my machine with this setup. The standby
calls pg_usleep(5000) after each signal, which is why the
population remains above 0 for several seconds after the cutoff.

--
Scott Ray

Attachment Content-Type Size
v2-0001-Add-TAP-test-for-recovery-conflicts-from-imported.patch application/octet-stream 6.9 KB
v2-0002-Fix-recovery-conflict-resolution-to-account-for-i.patch application/octet-stream 4.9 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Mihail Nikalayeu 2026-08-01 22:57:00 Re: RI fast path gets cross-type foreign keys wrong
Previous Message Alexander Lakhin 2026-08-01 18:00:00 Re: Improving tracking/processing of buildfarm test failures