Hi,
I spent some time digging deeper into the KnownAssignedXids logic in
procarray.c and made a few refinements. Below are some observations
and questions I’d like to discuss.
1) Present usage (AFAICS)
It appears that logical decoding is the only place that waits for an
XID on a standby. The single call-site is SnapBuildWaitSnapshot(),
which waits in a simple loop:
for (off = 0; off < running->xcnt; off++)
{
TransactionId xid = running->xids[off];
if (TransactionIdIsCurrentTransactionId(xid))
elog(ERROR, "waiting for ourselves");
if (TransactionIdFollows(xid, cutoff))
continue;
XactLockTableWait(xid, NULL, NULL, XLTW_None);
}
So each backend seems to block on one XID at a time.
2) Picking the waiter data structure
Given that behaviour, the total number of concurrent waits can’t exceed
MaxBackends. If logical-slot creation stays the primary consumer for
now and for future, I’m wondering
whether a simple fixed-size array (or even a single global
ConditionVariable) might be sufficient.
In the patch I currently size the hash table the same as
KnownAssignedXids (TOTAL_MAX_CACHED_SUBXIDS), but that may well be
conservative.
3) Some trims
I’ve removed WakeAllXidWaiters() and call WakeXidWaiters() at each
point where an XID is deleted from KnownAssignedXids.
Feedback would be much appreciated.
Best,
Xuneng