Re: Separate catalog_xmin from xmin in walsender hot standby feedback

From: Rui Zhao <zhaorui126(at)gmail(dot)com>
To: pgsql-hackers(at)lists(dot)postgresql(dot)org
Cc: andres(at)anarazel(dot)de, amit(dot)kapila16(at)gmail(dot)com
Subject: Re: Separate catalog_xmin from xmin in walsender hot standby feedback
Date: 2026-06-08 07:57:25
Message-ID: 273DD115-F20F-4521-880C-FC08A7DE99D3@gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

Attaching v2, rebased on top of current master (v1 no longer applied
cleanly per cfbot). Two improvements were also made since v1:

1. Test stability
The TAP test (053_hs_feedback_catalog_xmin.pl) replaced a sleep(2)
with a poll on pg_stat_replication.reply_time, so it deterministically
waits for a fresh hot standby feedback round to reach the primary
instead of relying on wall-clock time. This removes the most obvious
source of flakiness on slower CI runners.

2. Performance impact (pgbench)
I was concerned about adding a UINT32_ACCESS_ONCE(proc->catalog_xmin)
read and an extra TransactionIdOlder() call per PGPROC iteration in
ComputeXidHorizons(), which is on a hot path. Measured on a 104-core
box, scale=30, 64 clients / 32 jobs / 60s, -M prepared, optimized
build (CFLAGS=-O2, no --enable-cassert):

workload baseline median patched median delta
---------------------- --------------- -------------- -----
pgbench -S (read-only) 1,596,196 1,617,083 +1.3%
pgbench (read-write) 129,550 132,024 +1.9%

Numbers are medians of 3 warm runs after a 30s warmup, after I
discarded the cold-start runs which were dominated by cache priming.
The patched build comes out marginally above baseline, which is of
course noise -- adding code does not make things faster -- but it
confirms the change is below the measurement floor on this hardware.
Happy to rerun on different shapes (more clients, smaller scale,
different machine) if anyone wants to see specific numbers.

Summary of the change (unchanged in substance from v1):

- proc.h: add catalog_xmin field to PGPROC (4 bytes)
- proc.c: initialize it in InitProcess / InitAuxiliaryProcess
- procarray.c: accumulate proc_catalog_xmin in ComputeXidHorizons()
and apply it only to catalog_oldest_nonremovable and
shared_oldest_nonremovable; include it in GetReplicationHorizons()
so the catalog_xmin propagates correctly in cascading setups
- walsender.c: in the no-slot path of ProcessStandbyHSFeedbackMessage(),
set MyProc->xmin and MyProc->catalog_xmin separately instead of
folding them together

Registered in the 2026-07 commitfest:
https://commitfest.postgresql.org/patch/6861/

Adding Andres (who wrote much of the ProcArray horizon code) and Amit
Kapila (logical replication / slots), in case you have any thoughts on
the approach here -- in particular whether tracking catalog_xmin in
PGPROC is preferable to generalizing the ephemeral-slot idea hinted at
by the existing XXX comment in ProcessStandbyHSFeedbackMessage().

Regards,
Rui Zhao

Attachment Content-Type Size
v2-0001-Separate-catalog_xmin-from-xmin-in-walsender-hot-.patch application/octet-stream 19.4 KB
unknown_filename text/plain 4.7 KB
v1-0001-Separate-catalog_xmin-from-xmin-in-walsender-hs-feedback.patch application/octet-stream 18.2 KB
unknown_filename text/plain 7 bytes

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Ewan Young 2026-06-08 07:59:59 Re: [PATCH] Fix for bug #19474: LIKE fails to match literal backslashes with nondeterministic collations
Previous Message Andrei Lepikhov 2026-06-08 07:45:23 Re: Subquery pull-up increases jointree search space