summaryrefslogtreecommitdiff
path: root/src/include/access/transam.h
diff options
context:
space:
mode:
authorNoah Misch <noah@leadboat.com>2025-01-25 11:28:14 -0800
committerNoah Misch <noah@leadboat.com>2025-01-25 11:28:14 -0800
commit81772a495ec98d36eabf5cc294e7031a9545c5c1 (patch)
tree52447ccedb7b25ebbe9372e0c94df8f4b14cf0de /src/include/access/transam.h
parent4f6ec3831d3e6a237eb6197451472e70282654db (diff)
Merge copies of converting an XID to a FullTransactionId.
Assume twophase.c is the performance-sensitive caller, and preserve its choice of unlikely() branch hint. Add some retrospective rationale for that choice. Back-patch to v17, for the next commit to use it. Reviewed (in earlier versions) by Michael Paquier. Discussion: https://postgr.es/m/17821-dd8c334263399284@postgresql.org Discussion: https://postgr.es/m/20250116010051.f3.nmisch@google.com
Diffstat (limited to 'src/include/access/transam.h')
-rw-r--r--src/include/access/transam.h43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/include/access/transam.h b/src/include/access/transam.h
index 0cab8653f1b..7d82cd2eb56 100644
--- a/src/include/access/transam.h
+++ b/src/include/access/transam.h
@@ -370,6 +370,49 @@ FullTransactionIdNewer(FullTransactionId a, FullTransactionId b)
return b;
}
+/*
+ * Compute FullTransactionId for the given TransactionId, assuming xid was
+ * between [oldestXid, nextXid] at the time when TransamVariables->nextXid was
+ * nextFullXid. When adding calls, evaluate what prevents xid from preceding
+ * oldestXid if SetTransactionIdLimit() runs between the collection of xid and
+ * the collection of nextFullXid.
+ */
+static inline FullTransactionId
+FullTransactionIdFromAllowableAt(FullTransactionId nextFullXid,
+ TransactionId xid)
+{
+ uint32 epoch;
+
+ /* Special transaction ID. */
+ if (!TransactionIdIsNormal(xid))
+ return FullTransactionIdFromEpochAndXid(0, xid);
+
+ Assert(TransactionIdPrecedesOrEquals(xid,
+ XidFromFullTransactionId(nextFullXid)));
+
+ /*
+ * The 64 bit result must be <= nextFullXid, since nextFullXid hadn't been
+ * issued yet when xid was in the past. The xid must therefore be from
+ * the epoch of nextFullXid or the epoch before. We know this because we
+ * must remove (by freezing) an XID before assigning the XID half an epoch
+ * ahead of it.
+ *
+ * The unlikely() branch hint is dubious. It's perfect for the first 2^32
+ * XIDs of a cluster's life. Right at 2^32 XIDs, misprediction shoots to
+ * 100%, then improves until perfection returns 2^31 XIDs later. Since
+ * current callers pass relatively-recent XIDs, expect >90% prediction
+ * accuracy overall. This favors average latency over tail latency.
+ */
+ epoch = EpochFromFullTransactionId(nextFullXid);
+ if (unlikely(xid > XidFromFullTransactionId(nextFullXid)))
+ {
+ Assert(epoch != 0);
+ epoch--;
+ }
+
+ return FullTransactionIdFromEpochAndXid(epoch, xid);
+}
+
#endif /* FRONTEND */
#endif /* TRANSAM_H */