Re: Introduce XID age based replication slot invalidation

From: Bertrand Drouvot <bertranddrouvot(dot)pg(at)gmail(dot)com>
To: Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>
Cc: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, Srinath Reddy Sadipiralla <srinath2133(at)gmail(dot)com>, SATYANARAYANA NARLAPURAM <satyanarlapuram(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, John H <johnhyvr(at)gmail(dot)com>, PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: Introduce XID age based replication slot invalidation
Date: 2026-10-30 14:29:35
Message-ID: auSpz4wdC7PM9aWs@bdtpg
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

On Wed, Oct 21, 2026 at 01:15:00PM -0700, Bharath Rupireddy wrote:
> Hi,
>
> On Tue, Sep 22, 2026 at 2:19 AM Bertrand Drouvot
> <bertranddrouvot(dot)pg(at)gmail(dot)com> wrote:
> >
> > On Fri, Sep 18, 2026 at 10:40:00AM -0700, Bharath Rupireddy wrote:
> > >
> > > One approach is to never invalidate the slot, and to honour
> > > max_slot_xid_age by stopping conflict info retention for whoever is
> > > holding the slot's xmin back. On the worker side, the existing
> > > should_stop_conflict_info_retention() stops retention when the
> > > worker's oldest xid has aged past the age limit, whether or not a
> > > retention duration is set. On the launcher side, once per cycle, right
> > > after it tries to advance the xmin as usual, if the xmin has aged past
> > > the age limit it stops retention by setting subretentionactive to
> > > false in pg_subscription
> >
> > How do you see the launcher updating pg_subscription here? Are you thinking of a
> > launcher specific update path?
> >
> > > I prefer the first approach,
> >
> > +1 on the first approach. It is what I had in mind when suggesting combining the
> > worker and launcher checks.
>
> Hm. I realized the launcher doesn’t connect to a specific database. It
> can read the pg_subscription shared catalog, but it can’t update it,

Yeah, that's the issue I had in mind when asking how the launcher would update
pg_subscription.

> So I’m thinking of this approach.

Overall, the proposed design looks reasonable to me, but I have a couple of
questions:

> The launcher checks the slot for XID
> age, and when the limit is hit it sets a flag in its existing
> per-subscription shmem (LauncherLastStartTimesEntry) for every
> subscription still retaining, and lets the apply worker update the
> catalog. The launcher creates an entry even for the subscriptions
> whose apply worker is not running, such as disabled ones. When the
> flag is set, a running apply worker stops through the existing path
> (stop_conflict_info_retention()), setting subretentionactive to false,
> and the launcher does not move the slot’s xmin past that worker’s xid
> until the stop is recorded. For the subscriptions whose apply worker
> is not running, the launcher stops honoring their retention
> immediately and their apply worker records the stop when it next
> starts.

Could this have the same kind of durability issue as [1]? For a subscription
without a running apply worker, the launcher stops honoring retention immediately,
but subretentionactive remains true until the worker next starts.

What happens if the cleared slot's xmin is persisted and the postmaster restarts
in between?

> Once the xmin is no longer aged, the launcher clears the flag
> for the subscriptions whose stop is recorded, and retention resumes
> through the existing path. Until then a worker whose stop is recorded
> does not resume. This way the slot is never invalidated.
>
> For example, with XID age = 100, sub1 enabled and sub2 disabled, both retaining:
>
> 1/ The slot's xmin stops advancing at 500, because sub2 has no apply worker.
>
> 2/ At XID 600 the xmin is aged, so the launcher flags both. sub1's
> worker stops retaining and records it. sub2 has no worker, so the
> launcher stops counting it right away.
>
> 3/ Nothing to count, so the launcher clears the slot's xmin and vacuum
> moves on. The slot stays valid.
>
> 4/ The xmin is no longer aged, so the launcher clears sub1's flag. Its
> worker resumes retaining and the slot's xmin restarts at 600.
>
> 5/ sub2 stays flagged. When enabled, its worker records the stop at
> startup and resumes once it has caught up.
>
> Thoughts?

Isn't this different from what we discussed upthread? IIUC, the idea was to
stop retention only for subscriptions whose oldest_nonremovable_xid is
keeping the slot's xmin aged, allowing the others to continue normally. For
example, if sub1's value has advanced beyond 500, couldn't the launcher stop
counting only sub2 and recompute the slot's xmin from sub1's value?

[1]: https://postgr.es/m/ao7u5I9OeIR72kGp%40bdtpg

Regards,

--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Sami Imseih 2026-10-30 14:41:12 Re: [PATCH] pgstat: Add helper to drop entries from a stats kind's hash
Previous Message Henson Choi 2026-10-30 14:01:26 Columns assigned by MERGE can be dropped from SQL-standard function bodies