xid-assignment-v13-fix.patch
text/plain
Filename: xid-assignment-v13-fix.patch
Type: text/plain
Part: 0
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,