xid-assignment-v13-fix.patch

text/plain

Filename: xid-assignment-v13-fix.patch
Type: text/plain
Part: 0
Message: Re: PATCH: logical_work_mem and logical streaming of large in-progress transactions

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
Series: patch v13
File+
src/backend/access/transam/xlog.c 13 0
src/backend/storage/ipc/procarray.c 47 0
src/include/storage/procarray.h 1 0
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 1951103b26..b85c046b41 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7300,6 +7300,19 @@ StartupXLOG(void)
 					TransactionIdIsValid(record->xl_xid))
 					RecordKnownAssignedTransactionIds(record->xl_xid);
 
+				/*
+				* Assign subtransaction xids to the top level xid if the
+				* record has that information. This is required at most
+				* once per subtransactions.
+				*/
+				if (TransactionIdIsValid(xlogreader->toplevel_xid) &&
+					standbyState >= STANDBY_INITIALIZED)
+				{
+					Assert(XLogStandbyInfoActive());
+					ProcArrayCacheXidAssignment(xlogreader->toplevel_xid,
+												record->xl_xid);
+				}
+
 				/* Now apply the WAL record itself */
 				RmgrTable[record->xl_rmid].rm_redo(xlogreader);
 
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index cfb88db4a4..efddd0e1e6 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -958,6 +958,53 @@ ProcArrayApplyXidAssignment(TransactionId topxid,
 	LWLockRelease(ProcArrayLock);
 }
 
+static HTAB *xidAssignmentsHash = NULL;
+
+typedef struct XidAssignmentEntry
+{
+	/* the hash lookup key MUST BE FIRST */
+	TransactionId	topXid;
+
+	int				nsubxids;
+	TransactionId	subxids[PGPROC_MAX_CACHED_SUBXIDS];
+} XidAssignmentEntry;
+
+void
+ProcArrayCacheXidAssignment(TransactionId topXid, TransactionId subXid)
+{
+	XidAssignmentEntry *entry;
+	bool				found;
+
+	if (xidAssignmentsHash == NULL)
+	{
+		/* First time through: initialize the hash table */
+		HASHCTL		ctl;
+
+		MemSet(&ctl, 0, sizeof(ctl));
+		ctl.keysize = sizeof(TransactionId);
+		ctl.entrysize = sizeof(XidAssignmentEntry);
+		xidAssignmentsHash = hash_create("XID assignment cache", 256,
+										 &ctl, HASH_ELEM | HASH_BLOBS);
+	}
+
+	/* Look for an existing entry */
+	entry = (XidAssignmentEntry *) hash_search(xidAssignmentsHash,
+											 (void *) &topXid,
+											 HASH_ENTER, &found);
+
+	if (!found)
+		entry->nsubxids = 0;
+
+	entry->subxids[entry->nsubxids++] = subXid;
+
+	/* after reaching the limit, apply the assignments for this top XID */
+	if (entry->nsubxids == PGPROC_MAX_CACHED_SUBXIDS)
+	{
+		ProcArrayApplyXidAssignment(topXid, entry->nsubxids, entry->subxids);
+		entry->nsubxids = 0;
+	}
+}
+
 /*
  * TransactionIdIsInProgress -- is given transaction running in some backend
  *
diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
index a5c7d0c064..17d89bdd7e 100644
--- a/src/include/storage/procarray.h
+++ b/src/include/storage/procarray.h
@@ -67,6 +67,7 @@ extern void ProcArrayInitRecovery(TransactionId initializedUptoXID);
 extern void ProcArrayApplyRecoveryInfo(RunningTransactions running);
 extern void ProcArrayApplyXidAssignment(TransactionId topxid,
 										int nsubxids, TransactionId *subxids);
+extern void ProcArrayCacheXidAssignment(TransactionId topxid, TransactionId subxid);
 
 extern void RecordKnownAssignedTransactionIds(TransactionId xid);
 extern void ExpireTreeKnownAssignedTransactionIds(TransactionId xid,