Implement mxid_age() to compute multi-xid age
authorBruce Momjian <bruce@momjian.us>
Wed, 10 Sep 2014 21:13:04 +0000 (17:13 -0400)
committerBruce Momjian <bruce@momjian.us>
Wed, 10 Sep 2014 21:13:04 +0000 (17:13 -0400)
Report by Josh Berkus

doc/src/sgml/maintenance.sgml
src/backend/utils/adt/xid.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/utils/builtins.h

index cf174f071576faba23af85356b2b1a0c754b5117..d692308cf494f61266bbf95d69db8c2fd33f3b76 100644 (file)
@@ -640,7 +640,12 @@ HINT:  Stop the postmaster and vacuum that database in single-user mode.
      possible multixact ID still appearing in any tuple of that table.
      If this value is older than
      <xref linkend="guc-vacuum-multixact-freeze-table-age">, a whole-table
-     scan is forced.  Whole-table <command>VACUUM</> scans, regardless of
+     scan is forced.  <function>mxid_age()</> can be used on
+     <structname>pg_class</>.<structfield>relminmxid</> to find its age.
+    </para>
+
+    <para>
+     Whole-table <command>VACUUM</> scans, regardless of
      what causes them, enable advancing the value for that table.
      Eventually, as all tables in all databases are scanned and their
      oldest multixact values are advanced, on-disk storage for older
index 602a9e5d6f4838d5a5d9ebe38194329873874d61..ecb3cf55dd1789c978435dc2a1c5223be988a8dc 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <limits.h>
 
+#include "access/multixact.h"
 #include "access/transam.h"
 #include "access/xact.h"
 #include "libpq/pqformat.h"
@@ -102,6 +103,21 @@ xid_age(PG_FUNCTION_ARGS)
    PG_RETURN_INT32((int32) (now - xid));
 }
 
+/*
+ *     mxid_age            - compute age of a multi XID (relative to latest stable mxid)
+ */
+Datum
+mxid_age(PG_FUNCTION_ARGS)
+{
+   TransactionId xid = PG_GETARG_TRANSACTIONID(0);
+   MultiXactId now = ReadNextMultiXactId();
+
+   if (!MultiXactIdIsValid(xid))
+       PG_RETURN_INT32(INT_MAX);
+
+   PG_RETURN_INT32((int32) (now - xid));
+}
+
 /*
  * xidComparator
  *     qsort comparison function for XIDs
index 5dc0455477ae44a09aa7f1ace75ae26fb29d5b67..74582e9bbb8393a1fd8306419bb981598883085c 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 201409091
+#define CATALOG_VERSION_NO 201409101
 
 #endif
index bd1b41723c01143b2deb4048ec9f277a910cc582..a56a6359ca861c86208c4bdc184f305f6eb6fb63 100644 (file)
@@ -1279,6 +1279,8 @@ DATA(insert OID = 1180 (  abstime        PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 7
 DESCR("convert timestamp with time zone to abstime");
 DATA(insert OID = 1181 (  age             PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 23 "28" _null_ _null_ _null_ _null_ xid_age _null_ _null_ _null_ ));
 DESCR("age of a transaction ID, in transactions before current transaction");
+DATA(insert OID = 3939 (  mxid_age        PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 23 "28" _null_ _null_ _null_ _null_ mxid_age _null_ _null_ _null_ ));
+DESCR("age of a multi-transaction ID, in multi-transactions before current multi-transaction");
 
 DATA(insert OID = 1188 (  timestamptz_mi   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1186 "1184 1184" _null_ _null_ _null_ _null_ timestamp_mi _null_ _null_ _null_ ));
 DATA(insert OID = 1189 (  timestamptz_pl_interval PGNSP PGUID 12 1 0 0 0 f f f f t f s 2 0 1184 "1184 1186" _null_ _null_ _null_ _null_ timestamptz_pl_interval _null_ _null_ _null_ ));
index 78cc0a0bea38160c1c626ae638acf7cc750926a8..d88e7a3b265821566adf08c7ca69176dfc1ddbe2 100644 (file)
@@ -845,6 +845,7 @@ extern Datum xidrecv(PG_FUNCTION_ARGS);
 extern Datum xidsend(PG_FUNCTION_ARGS);
 extern Datum xideq(PG_FUNCTION_ARGS);
 extern Datum xid_age(PG_FUNCTION_ARGS);
+extern Datum mxid_age(PG_FUNCTION_ARGS);
 extern int xidComparator(const void *arg1, const void *arg2);
 extern Datum cidin(PG_FUNCTION_ARGS);
 extern Datum cidout(PG_FUNCTION_ARGS);