diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index 3a58f1e..f19b5ce 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -262,9 +262,16 @@ TransactionIdSetPageStatus(TransactionId xid, int nsubxids,
 		   status == TRANSACTION_STATUS_ABORTED ||
 		   (status == TRANSACTION_STATUS_SUB_COMMITTED && !TransactionIdIsValid(xid)));
 
-	LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
-
 	/*
+	 * Acquire ClogCtl Share lock while we set commit bits, if possible.
+	 *
+	 * This is safe because all callers of these routines always
+	 * check the xid is complete first, either by checking
+	 * TransactionIdIsInProgress() or by waiting for the transaction
+	 * to complete via the lock manager. As a result,
+	 * anybody checking visibility of our xids will never get as far as
+	 * checking the status here at the same time we are setting it.
+	 *
 	 * If we're doing an async commit (ie, lsn is valid), then we must wait
 	 * for any active write on the page slot to complete.  Otherwise our
 	 * update could reach disk in that write, which will not do since we
@@ -273,7 +280,17 @@ TransactionIdSetPageStatus(TransactionId xid, int nsubxids,
 	 * write-busy, since we don't care if the update reaches disk sooner than
 	 * we think.
 	 */
-	slotno = SimpleLruReadPage(ClogCtl, pageno, XLogRecPtrIsInvalid(lsn), xid);
+	slotno = SimpleLruReadPage_optShared(ClogCtl, pageno, XLogRecPtrIsInvalid(lsn), xid);
+
+	/*
+	 * We might have problems with concurrent writes, but we solve
+	 * that by acquiring an exclusive page lock to serialize commits and ensure
+	 * there is a memory barrier between commit writes. Note that we
+	 * acquire and release the lock for each page, to ensure that
+	 * transactions with huge numbers of subxacts don't hold up everyone else.
+	 */
+	if (!InRecovery)
+		LWLockAcquire(ClogCtl->shared->buffer_locks[slotno], LW_EXCLUSIVE);
 
 	/*
 	 * Set the main transaction id, if any.
@@ -311,6 +328,9 @@ TransactionIdSetPageStatus(TransactionId xid, int nsubxids,
 
 	ClogCtl->shared->page_dirty[slotno] = true;
 
+	if (!InRecovery)
+		LWLockRelease(ClogCtl->shared->buffer_locks[slotno]);
+
 	LWLockRelease(CLogControlLock);
 }
 
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index 5fcea11..38440f4 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -449,6 +449,13 @@ SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok,
 int
 SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid)
 {
+	return SimpleLruReadPage_optShared(ctl, pageno, true, xid);
+}
+
+int
+SimpleLruReadPage_optShared(SlruCtl ctl, int pageno, bool write_ok,
+						   TransactionId xid)
+{
 	SlruShared	shared = ctl->shared;
 	int			slotno;
 
@@ -460,7 +467,9 @@ SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid)
 	{
 		if (shared->page_number[slotno] == pageno &&
 			shared->page_status[slotno] != SLRU_PAGE_EMPTY &&
-			shared->page_status[slotno] != SLRU_PAGE_READ_IN_PROGRESS)
+			shared->page_status[slotno] != SLRU_PAGE_READ_IN_PROGRESS &&
+			(write_ok ||
+			 shared->page_status[slotno] != SLRU_PAGE_WRITE_IN_PROGRESS))
 		{
 			/* See comments for SlruRecentlyUsed macro */
 			SlruRecentlyUsed(shared, slotno);
@@ -472,7 +481,7 @@ SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid)
 	LWLockRelease(shared->ControlLock);
 	LWLockAcquire(shared->ControlLock, LW_EXCLUSIVE);
 
-	return SimpleLruReadPage(ctl, pageno, true, xid);
+	return SimpleLruReadPage(ctl, pageno, write_ok, xid);
 }
 
 /*
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
index 9c7f019..256b03d 100644
--- a/src/include/access/slru.h
+++ b/src/include/access/slru.h
@@ -142,6 +142,8 @@ extern int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok,
 				  TransactionId xid);
 extern int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno,
 						   TransactionId xid);
+extern int SimpleLruReadPage_optShared(SlruCtl ctl, int pageno,
+						   bool write_ok, TransactionId xid);
 extern void SimpleLruWritePage(SlruCtl ctl, int slotno);
 extern void SimpleLruFlush(SlruCtl ctl, bool checkpoint);
 extern void SimpleLruTruncate(SlruCtl ctl, int cutoffPage);
