Re: Snapshot export on a standby corrupts hint bits on subxact overflow

From: Peter Geoghegan <pg(at)bowt(dot)ie>
To: Bertrand Drouvot <bertranddrouvot(dot)pg(at)gmail(dot)com>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Andres Freund <andres(at)anarazel(dot)de>, scott(at)scottray(dot)io
Subject: Re: Snapshot export on a standby corrupts hint bits on subxact overflow
Date: 2026-08-24 23:07:07
Message-ID: CAH2-WznimsP_QS-bP3xMtRsmMGDud7GDdYAvUU4MYHQiVN_Q1Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Wed, Jul 29, 2026 at 5:36 AM Bertrand Drouvot
<bertranddrouvot(dot)pg(at)gmail(dot)com> wrote:
> > 1/ In ExportSnapshot(), do not include recovery subxip entries and committed
> > child XIDs at or above xmax when counting and serializing them, so unnecessary
> > entries do not consume the limited recovery subxip capacity.

That is a valid issue, but I wonder if it's worth including in a
back-patchable fix. Is the special case worth the added risk?

Attached v3 simplifies 0001, partly by leaving that part out entirely.
It also simplifies the logic by always writing "sof:%u" and "sxcnt:%d"
to the temp file -- the idea is to make ImportSnapshot import any
subxacts it finds in the file (while still sanitizing the inputs).

The nchildren-won't-fit issue is extremely narrow in practice. The
worst that can happen is that the user sees an "invalid snapshot data
in file..." error on import. But that can only happen when:

1. A snapshot is taken on a standby.
2. The xact holding that snapshot outlives promotion.
3. The xact then writes, acquiring an XID. It accumulates enough
committed subxacts that they, plus the snapshot's own subxip entries,
exceed GetMaxSnapshotSubxidCount().
4. It then calls pg_export_snapshot().

When someone goes to import the snapshot exported in step 4, they see
the error. In practice, GetMaxSnapshotSubxidCount will fit about 15k
XIDs with max_connections=200. So I think that this will just never
happen.

Note also that it need not be the original xact that acquired the
snapshot that holds onto it in step 2. You could export + import a
snapshot during recovery, and then have the importing xact continue
after promotion -- at which point the snapshot is exported + imported
a second time. That's probably manageable in practice, but it makes me
nervous. Especially because there is evidently plenty of potential for
somebody to get something wrong in this area (we learned of three bugs
here in the past 6 weeks or so).

Maybe we could improve the error message, but I want the committed
solution to be as simple as possible.

> > 2/ In pg_current_snapshot(), do not include source XIDs outside [xmin, xmax),
> > so that it enforces the rule regardless of how the source snapshot was produced.

I'm not treating this one as a priority, so I haven't worked on it.

I'm focused on committing 0001 in the next few days, since it's a bug
that has caused users real harm.

--
Peter Geoghegan

Attachment Content-Type Size
v3-0001-Export-subxip-for-snapshots-taken-during-recovery.patch application/octet-stream 14.4 KB

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Manuel Reyes Bravo 2026-08-24 23:30:38 Detecting plan drift: pg_plan_advice pins plans, nothing watches them
Previous Message David Rowley 2026-08-24 22:43:56 Re: Add bms_offset_members() function for bitshifting Bitmapsets