On Fri, Sep 4, 2026 at 7:42 AM Zhijie Hou (Fujitsu)
<[email protected]> wrote:
>
> Apart from above comments, I also addressed comments from Kuroda-San[1] and
> Nisha[2].
>

Thanks for the updated patch.

I was testing/reviewing the retention stop-resume path when two dbs
(say db1 and db2) are involved. I see a race condition between the
launcher and the worker that leads to the same assert.
When a sub resumes retention on db2, update_retention_status(true)
sets subretentionactive = true and calls ApplyLauncherWakeup() before
the worker restarts itself through apply_worker_exit().

Now if the launcher runs its next cycle while the old worker's entry
is still in_use(say we hold it just before apply_worker_exit), then in
that cycle, launcher will -
 - add the db2 to retained_dbids.
 - fire the reset because db2 is not yet in the set.
 - Finds w != NULL (still old worker), so
compute_min_nonremovable_xid() reads the "InvalidTransactionId" left
by the earlier stop and returns without contributing to the result.

Now the situation is that update_conflict_slot_xmin() advances the
slot to the horizon of db1 (which can be way ahead of db2's horizon).
When eventually a new worker starts for db2's subscription with a
valid oldest_xmin based on db2's horizon, in the next launcher cycle,
since db2 is already in the retained_dbids list, it will not fire the
reset again. The slot.xmin stays advanced, and when the db2 worker
reaches get_candidate_xid() with its old xmin, it hits the same
assertion.

TRAP: failed 
Assert("TransactionIdPrecedesOrEquals(MyLogicalRepWorker->oldest_nonremovable_xid,
oldest_running_xid)"), File: "worker.c", Line: 4536, PID: 60377
0   postgres                            0x0000000100ac5144
ExceptionalCondition + 216
1   postgres                            0x00000001007979c4
get_candidate_xid + 196
2   postgres                            0x00000001007978ac
process_rdt_phase_transition + 128
3   postgres                            0x00000001007973bc
maybe_advance_nonremovable_xid + 56
4   postgres                            0x0000000100791b6c
LogicalRepApplyLoop + 1456
5   postgres                            0x00000001007914f0 start_apply + 120
...

Attached is a TAP test that reproduces this issue using an injection
point. The patch applies on top of v2-0001.

--
Thanks,
Nisha

Attachment: v2-0002-Reproducer-TAP-test.patch
Description: Binary data

Reply via email to