From 56fdf28a10d531984b1765f3bd6ae3fbee8c0006 Mon Sep 17 00:00:00 2001
From: Matthias van de Meent <boekewurm+postgres@gmail.com>
Date: Wed, 25 Jan 2023 15:40:30 +0100
Subject: [PATCH v2 5/6] Stop the logging of XIDs in records where the XID is
 unused.

Many WAL record types do not need to contain an XID. This change
prepares for the removal of the xid from the main xlog record header,
by requiring the user of the XLog insertion API to explicitly request
the inclusion of the current xid in the log record - in all other
cases we'll log, assume and track InvalidXid instead.
---
 src/backend/access/heap/heapam.c          | 16 +++++++++-------
 src/backend/access/heap/pruneheap.c       |  1 +
 src/backend/access/heap/rewriteheap.c     |  1 +
 src/backend/access/transam/generic_xlog.c |  3 +++
 src/backend/access/transam/multixact.c    |  1 +
 src/backend/access/transam/xact.c         |  4 ++--
 src/backend/access/transam/xloginsert.c   | 12 ++++++++++--
 src/backend/commands/tablecmds.c          |  2 +-
 src/backend/replication/logical/message.c |  2 +-
 src/backend/utils/cache/inval.c           |  1 +
 src/include/access/xlog.h                 |  1 +
 11 files changed, 31 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 1512f22c76..30b7b05f54 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1969,7 +1969,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
 							heaptup->t_len - SizeofHeapTupleHeader);
 
 		/* filtering by origin on a row level is much more efficient */
-		XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
+		XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN | XLOG_INCLUDE_XID);
 
 		recptr = XLogInsert(RM_HEAP_ID, info);
 
@@ -2365,7 +2365,7 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples,
 			XLogRegisterBufData(0, tupledata, totaldatalen);
 
 			/* filtering by origin on a row level is much more efficient */
-			XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
+			XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN | XLOG_INCLUDE_XID);
 
 			recptr = XLogInsert(RM_HEAP2_ID, info);
 
@@ -2865,7 +2865,7 @@ l1:
 		}
 
 		/* filtering by origin on a row level is much more efficient */
-		XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
+		XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN | XLOG_INCLUDE_XID);
 
 		recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_DELETE);
 
@@ -5535,6 +5535,7 @@ l4:
 				cleared_all_frozen ? XLH_LOCK_ALL_FROZEN_CLEARED : 0;
 
 			XLogRegisterData((char *) &xlrec, SizeOfHeapLockUpdated);
+			XLogSetRecordFlags(XLOG_INCLUDE_XID);
 
 			recptr = XLogInsert(RM_HEAP2_ID, XLOG_HEAP2_LOCK_UPDATED);
 
@@ -5685,7 +5686,7 @@ heap_finish_speculative(Relation relation, ItemPointer tid)
 		XLogBeginInsert();
 
 		/* We want the same filtering on this as on a plain insert */
-		XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
+		XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN | XLOG_INCLUDE_XID);
 
 		XLogRegisterData((char *) &xlrec, SizeOfHeapConfirm);
 		XLogRegisterBuffer(0, buffer, REGBUF_STANDARD);
@@ -5831,7 +5832,8 @@ heap_abort_speculative(Relation relation, ItemPointer tid)
 		XLogRegisterData((char *) &xlrec, SizeOfHeapDelete);
 		XLogRegisterBuffer(0, buffer, REGBUF_STANDARD);
 
-		/* No replica identity & replication origin logged */
+		/* No replica identity & replication origin logged, but XID is required */
+		XLogSetRecordFlags(XLOG_INCLUDE_XID);
 
 		recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_DELETE);
 
@@ -8563,7 +8565,7 @@ log_heap_update(Relation reln, Buffer oldbuf,
 	}
 
 	/* filtering by origin on a row level is much more efficient */
-	XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
+	XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN | XLOG_INCLUDE_XID);
 
 	recptr = XLogInsert(RM_HEAP_ID, info);
 
@@ -8638,7 +8640,7 @@ log_heap_new_cid(Relation relation, HeapTuple tup)
 	XLogRegisterData((char *) &xlrec, SizeOfHeapNewCid);
 
 	/* will be looked at irrespective of origin */
-
+	XLogSetRecordFlags(XLOG_INCLUDE_XID);
 	recptr = XLogInsert(RM_HEAP2_ID, XLOG_HEAP2_NEW_CID);
 
 	return recptr;
diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c
index 47b9e20915..24e1bbe1ad 100644
--- a/src/backend/access/heap/pruneheap.c
+++ b/src/backend/access/heap/pruneheap.c
@@ -445,6 +445,7 @@ heap_page_prune(Relation relation, Buffer buffer,
 				XLogRegisterBufData(0, (char *) prstate.nowunused,
 									prstate.nunused * sizeof(OffsetNumber));
 
+			XLogSetRecordFlags(XLOG_INCLUDE_XID);
 			recptr = XLogInsert(RM_HEAP2_ID, XLOG_HEAP2_PRUNE);
 
 			PageSetLSN(BufferGetPage(buffer), recptr);
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index 424958912c..9f77537335 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -921,6 +921,7 @@ logical_heap_rewrite_flush_mappings(RewriteState state)
 		src->off += len;
 
 		XLogBeginInsert();
+		XLogSetRecordFlags(XLOG_INCLUDE_XID);
 		XLogRegisterData((char *) (&xlrec), sizeof(xlrec));
 		XLogRegisterData(waldata_start, len);
 
diff --git a/src/backend/access/transam/generic_xlog.c b/src/backend/access/transam/generic_xlog.c
index 6c68191ca6..c8983b40ad 100644
--- a/src/backend/access/transam/generic_xlog.c
+++ b/src/backend/access/transam/generic_xlog.c
@@ -399,6 +399,9 @@ GenericXLogFinish(GenericXLogState *state)
 			}
 		}
 
+		/* Assume XID is required */
+		XLogSetRecordFlags(XLOG_INCLUDE_XID);
+
 		/* Insert xlog record */
 		lsn = XLogInsert(RM_GENERIC_ID, 0);
 
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index c70b6b7358..883da6a33b 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -834,6 +834,7 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
 	 * Not clear that it's worth the trouble though.
 	 */
 	XLogBeginInsert();
+	XLogSetRecordFlags(XLOG_INCLUDE_XID);
 	XLogRegisterData((char *) (&xlrec), SizeOfMultiXactCreate);
 	XLogRegisterData((char *) members, nmembers * sizeof(MultiXactMember));
 
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index da0ac6c8d3..57504594b0 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -5793,7 +5793,7 @@ XactLogCommitRecord(TimestampTz commit_time,
 		XLogRegisterData((char *) (&xl_origin), sizeof(xl_xact_origin));
 
 	/* we allow filtering by xacts */
-	XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
+	XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN | XLOG_INCLUDE_XID);
 
 	return XLogInsertExtended(RM_XACT_ID, info, rmgr_info);
 }
@@ -5940,7 +5940,7 @@ XactLogAbortRecord(TimestampTz abort_time,
 		XLogRegisterData((char *) (&xl_origin), sizeof(xl_xact_origin));
 
 	/* Include the replication origin */
-	XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
+	XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN | XLOG_INCLUDE_XID);
 
 	return XLogInsertExtended(RM_XACT_ID, info, rmgr_info);
 }
diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c
index 9a3eb4fb4b..4816c5284b 100644
--- a/src/backend/access/transam/xloginsert.c
+++ b/src/backend/access/transam/xloginsert.c
@@ -456,6 +456,10 @@ XLogSetRecordFlags(uint8 flags)
  * (LSN is the XLOG point up to which the XLOG must be flushed to disk
  * before the data page can be written out.  This implements the basic
  * WAL rule "write the log before the data".)
+ *
+ * Note: To include the current backend's TransactionID in the record,
+ * you have to set the XLOG_INCLUDE_XID flag using XLogRecordSetFlags
+ * before calling XLogInsert.
  */
 XLogRecPtr
 XLogInsert(RmgrId rmid, uint8 rmgr_info)
@@ -847,7 +851,7 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, uint8 rmgr_info, XLogRecPtr RedoRecP
 	}
 
 	/* followed by toplevel XID, if not already included in previous record */
-	if (IsSubxactTopXidLogPending())
+	if (curinsert_flags & XLOG_INCLUDE_XID && IsSubxactTopXidLogPending())
 	{
 		TransactionId xid = GetTopTransactionIdIfAny();
 
@@ -924,7 +928,11 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, uint8 rmgr_info, XLogRecPtr RedoRecP
 	 * once we know where in the WAL the record will be inserted. The CRC does
 	 * not include the record header yet.
 	 */
-	rechdr->xl_xid = GetCurrentTransactionIdIfAny();
+	if (curinsert_flags & XLOG_INCLUDE_XID)
+		rechdr->xl_xid = GetCurrentTransactionIdIfAny();
+	else
+		rechdr->xl_xid = InvalidTransactionId;
+
 	rechdr->xl_tot_len = (uint32) total_len;
 	rechdr->xl_info = info;
 	rechdr->xl_rmid = rmid;
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index d985278ac6..264a0399b4 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -2132,7 +2132,7 @@ ExecuteTruncateGuts(List *explicit_rels,
 		XLogRegisterData((char *) &xlrec, SizeOfHeapTruncate);
 		XLogRegisterData((char *) logrelids, list_length(relids_logged) * sizeof(Oid));
 
-		XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
+		XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN | XLOG_INCLUDE_XID);
 
 		(void) XLogInsert(RM_HEAP_ID, XLOG_HEAP_TRUNCATE);
 	}
diff --git a/src/backend/replication/logical/message.c b/src/backend/replication/logical/message.c
index c31dc1203f..af86d18457 100644
--- a/src/backend/replication/logical/message.c
+++ b/src/backend/replication/logical/message.c
@@ -69,7 +69,7 @@ LogLogicalMessage(const char *prefix, const char *message, size_t size,
 	XLogRegisterData(unconstify(char *, message), size);
 
 	/* allow origin filtering */
-	XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
+	XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN | XLOG_INCLUDE_XID);
 
 	return XLogInsert(RM_LOGICALMSG_ID, XLOG_LOGICAL_MESSAGE);
 }
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index 0008826f67..b0afdd6f90 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -1632,6 +1632,7 @@ LogLogicalInvalidations(void)
 		ProcessMessageSubGroupMulti(group, RelCacheMsgs,
 									XLogRegisterData((char *) msgs,
 													 n * sizeof(SharedInvalidationMessage)));
+		XLogSetRecordFlags(XLOG_INCLUDE_XID);
 		XLogInsert(RM_XACT_ID, XLOG_XACT_INVALIDATIONS);
 	}
 }
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 9007f559f3..f4dfaeda29 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -150,6 +150,7 @@ extern PGDLLIMPORT bool XLOG_DEBUG;
  */
 #define XLOG_INCLUDE_ORIGIN		0x01	/* include the replication origin */
 #define XLOG_MARK_UNIMPORTANT	0x02	/* record not important for durability */
+#define XLOG_INCLUDE_XID		0x04	/* include the transaction ID */
 
 
 /* Checkpoint statistics */
-- 
2.40.1

