diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index 3a58f1e..89f0572 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);
 }
 
@@ -369,7 +389,26 @@ TransactionIdSetStatusBit(TransactionId xid, XidStatus status, XLogRecPtr lsn, i
 		int			lsnindex = GetLSNIndex(slotno, xid);
 
 		if (ClogCtl->shared->group_lsn[lsnindex] < lsn)
-			ClogCtl->shared->group_lsn[lsnindex] = lsn;
+		{
+			LWLockMode	mode;
+
+			Assert (LWLockHeldByMe(CLogControlLock));
+
+			mode = LWLockModeHeldByMe(CLogControlLock);
+
+			Assert (mode == LW_SHARED || mode == LW_EXCLUSIVE);
+
+			if (mode == LW_EXCLUSIVE)
+				ClogCtl->shared->group_lsn[lsnindex] = lsn;
+			else
+			{
+				LWLockRelease(CLogControlLock);
+				LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
+				if (ClogCtl->shared->group_lsn[lsnindex] < lsn)
+					ClogCtl->shared->group_lsn[lsnindex] = lsn;
+			}
+
+		}
 	}
 }
 
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/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 687ed63..9f42449 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -1656,3 +1656,27 @@ LWLockHeldByMe(LWLock *l)
 	}
 	return false;
 }
+
+/*
+ * LWLockModeHeldByMe - returns lock mode.
+ *
+ * Caller mush ensure that this is API is called only for acquired locks.
+ * Usually this API will be used to refer the latest-acquired lock, so we
+ * have optimized it by scanning held lock array from backwards.
+ */
+LWLockMode
+LWLockModeHeldByMe(LWLock *lock)
+{
+	int			i;
+
+	for (i = num_held_lwlocks; --i >= 0;)
+	{
+		if (lock == held_lwlocks[i].lock)
+			return held_lwlocks[i].mode;
+	}
+
+	Assert(false);
+
+	/* The control should never reach here, it is just to silence warning */
+	return 0;
+}
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);
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index f2ff6a0..8d86094 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -189,6 +189,7 @@ extern void LWLockRelease(LWLock *lock);
 extern void LWLockReleaseClearVar(LWLock *lock, uint64 *valptr, uint64 val);
 extern void LWLockReleaseAll(void);
 extern bool LWLockHeldByMe(LWLock *lock);
+extern LWLockMode LWLockModeHeldByMe(LWLock *lock);
 
 extern bool LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval);
 extern void LWLockUpdateVar(LWLock *lock, uint64 *valptr, uint64 value);
