From b06679e01244d33304b71a6a44c7cc86173617b3 Mon Sep 17 00:00:00 2001
From: Simon Riggs <simon@2ndQuadrant.com>
Date: Fri, 11 May 2012 14:36:24 +0100
Subject: [PATCH] Ensure age() returns a stable value rather than the latest
 value

---
 src/backend/access/transam/xact.c | 22 ++++++++++++++++++++++
 src/backend/utils/adt/xid.c       |  8 +++-----
 src/include/access/xact.h         |  1 +
 3 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 7f412b10d75..1654a0e5c73 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -391,6 +391,28 @@ GetCurrentTransactionIdIfAny(void)
 }
 
 
+/*
+ *	GetStableLatestTransactionIdIfAny
+ *
+ * Get the latest XID once and then return same value for rest of transaction.
+ * Acts as a useful reference point for maintenance tasks.
+ */
+TransactionId
+GetStableLatestTransactionId(void)
+{
+	static LocalTransactionId lxid = InvalidLocalTransactionId;
+	static TransactionId stablexid = InvalidTransactionId;
+
+	if (lxid != MyProc->lxid ||
+		!TransactionIdIsValid(stablexid))
+	{
+		lxid = MyProc->lxid;
+		stablexid = ReadNewTransactionId();
+	}
+
+	return stablexid;
+}
+
 /*
  * AssignTransactionId
  *
diff --git a/src/backend/utils/adt/xid.c b/src/backend/utils/adt/xid.c
index eeda081ad18..da9da8a29b9 100644
--- a/src/backend/utils/adt/xid.c
+++ b/src/backend/utils/adt/xid.c
@@ -19,6 +19,7 @@
 #include "access/transam.h"
 #include "access/xact.h"
 #include "libpq/pqformat.h"
+#include "storage/proc.h"
 #include "utils/builtins.h"
 
 #define PG_GETARG_TRANSACTIONID(n)	DatumGetTransactionId(PG_GETARG_DATUM(n))
@@ -87,16 +88,13 @@ xideq(PG_FUNCTION_ARGS)
 }
 
 /*
- *		xid_age			- compute age of an XID (relative to current xact)
+ *		xid_age			- compute age of an XID (relative to latest stable xid)
  */
 Datum
 xid_age(PG_FUNCTION_ARGS)
 {
 	TransactionId xid = PG_GETARG_TRANSACTIONID(0);
-	TransactionId now = GetTopTransactionIdIfAny();
-
-	if (!TransactionIdIsValid(now))
-		now = ReadNewTransactionId();
+	TransactionId now = GetStableLatestTransactionId();
 
 	/* Permanent XIDs are always infinitely old */
 	if (!TransactionIdIsNormal(xid))
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
index 20e344e5b73..50f181307ff 100644
--- a/src/include/access/xact.h
+++ b/src/include/access/xact.h
@@ -209,6 +209,7 @@ extern TransactionId GetTopTransactionId(void);
 extern TransactionId GetTopTransactionIdIfAny(void);
 extern TransactionId GetCurrentTransactionId(void);
 extern TransactionId GetCurrentTransactionIdIfAny(void);
+extern TransactionId GetStableLatestTransactionId(void);
 extern SubTransactionId GetCurrentSubTransactionId(void);
 extern CommandId GetCurrentCommandId(bool used);
 extern TimestampTz GetCurrentTransactionStartTimestamp(void);
-- 
GitLab