| From: | Nisha Moond <nisha(dot)moond412(at)gmail(dot)com> |
|---|---|
| To: | "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com> |
| Cc: | shveta malik <shveta(dot)malik(at)gmail(dot)com>, pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com> |
| Subject: | Re: Follow-up review items for update_deleted |
| Date: | 2026-09-04 07:26:57 |
| Message-ID: | CABdArM4tH9TPfE92UgkAKv87bPZv3JicrcR4pmCOdzPjFTorAQ@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
On Fri, Sep 4, 2026 at 7:42 AM Zhijie Hou (Fujitsu)
<houzj(dot)fnst(at)fujitsu(dot)com> 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 | Content-Type | Size |
|---|---|---|
| v2-0002-Reproducer-TAP-test.patch | application/octet-stream | 8.9 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Ashutosh Bapat | 2026-09-04 07:34:01 | Re: Vertex/Edge label and view |
| Previous Message | solai v | 2026-09-04 07:15:19 | Re: Introducing find_all_inheritors_ordered() |