v3-0002-Partition-2PCs-first-during-wait.patch

application/octet-stream

Filename: v3-0002-Partition-2PCs-first-during-wait.patch
Type: application/octet-stream
Part: 1
Message: Re: CREATE INDEX CONCURRENTLY does not index prepared xact's data

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: format-patch
Series: patch v3-0002
Subject: Partition 2PCs first during wait
File+
src/backend/access/transam/twophase.c 4 3
src/backend/storage/lmgr/lmgr.c 28 4
From a4db2c29cb07e0129af2734a31299bae9bdfe680 Mon Sep 17 00:00:00 2001
From: Andrey Borodin <amborodin@acm.org>
Date: Wed, 21 Jul 2021 00:24:13 +0500
Subject: [PATCH v3 2/2] Partition 2PCs first during wait

---
 src/backend/access/transam/twophase.c |  7 +++---
 src/backend/storage/lmgr/lmgr.c       | 32 +++++++++++++++++++++++----
 2 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index dba302d322..836c9339af 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -852,7 +852,7 @@ TwoPhaseGetGXact(TransactionId xid, bool lock_held)
 
 /*
  * TwoPhaseGetXidByVXid
- *		Try to lookup for vxid among prepared xacts
+ *		Try to lookup earliest xid for vxid among prepared xacts
  */
 TransactionId
 TwoPhaseGetXidByVXid(VirtualTransactionId vxid)
@@ -871,8 +871,9 @@ TwoPhaseGetXidByVXid(VirtualTransactionId vxid)
 		if (proc->backendId == vxid.backendId &&
 				proc->lxid == vxid.localTransactionId)
 		{
-			result = gxact->xid;
-			break;
+			if (result == InvalidTransactionId ||
+				TransactionIdPrecedes(gxact->xid, result))
+					result = gxact->xid;
 		}
 	}
 
diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c
index cdf2266d6d..d03ce465cc 100644
--- a/src/backend/storage/lmgr/lmgr.c
+++ b/src/backend/storage/lmgr/lmgr.c
@@ -912,20 +912,44 @@ WaitForLockersMultiple(List *locktags, LOCKMODE lockmode, bool progress)
 	foreach(lc, holders)
 	{
 		VirtualTransactionId *lockholders = lfirst(lc);
+		int nholders = 0;
+		int i = 0, j;
 
-		while (VirtualTransactionIdIsValid(*lockholders))
+		while (VirtualTransactionIdIsValid(lockholders[nholders]))
+			nholders++;
+		j = nholders - 1;
+
+		/* partition 2PC first */
+		while (nholders > 0)
+		{
+			while (i < nholders && VirtualTransactionIdIsPreparedXact(lockholders[i]))
+				i++;
+			while (j >= 0 && !VirtualTransactionIdIsPreparedXact(lockholders[j]))
+				j--;
+			if (i < j)
+			{
+				VirtualTransactionId tmp = lockholders[i];
+				lockholders[i] = lockholders[j];
+				lockholders[j] = tmp;
+				i++;
+				j++;
+			}
+			if (i >= j)
+				break;
+		}
+
+		for (i = 0; i < nholders; i++)
 		{
 			/* If requested, publish who we're going to wait for. */
 			if (progress)
 			{
-				PGPROC	   *holder = BackendIdGetProc(lockholders->backendId);
+				PGPROC	   *holder = BackendIdGetProc(lockholders[i].backendId);
 
 				if (holder)
 					pgstat_progress_update_param(PROGRESS_WAITFOR_CURRENT_PID,
 												 holder->pid);
 			}
-			VirtualXactLock(*lockholders, true);
-			lockholders++;
+			VirtualXactLock(lockholders[i], true);
 
 			if (progress)
 				pgstat_progress_update_param(PROGRESS_WAITFOR_DONE, ++done);
-- 
2.24.3 (Apple Git-128)