diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c
index 61f2ce4..5feaedc 100644
--- a/src/backend/access/heap/pruneheap.c
+++ b/src/backend/access/heap/pruneheap.c
@@ -16,13 +16,13 @@
 
 #include "access/heapam.h"
 #include "access/transam.h"
+#include "catalog/catalog.h"
 #include "miscadmin.h"
 #include "pgstat.h"
 #include "storage/bufmgr.h"
 #include "utils/rel.h"
 #include "utils/tqual.h"
 
-
 /* Working data for heap_page_prune and subroutines */
 typedef struct
 {
@@ -72,6 +72,7 @@ heap_page_prune_opt(Relation relation, Buffer buffer, TransactionId OldestXmin)
 {
 	Page		page = BufferGetPage(buffer);
 	Size		minfree;
+	Transactionid	CutoffXmin = OldestXmin;
 
 	/*
 	 * Let's see if we really need pruning.
@@ -91,6 +92,18 @@ heap_page_prune_opt(Relation relation, Buffer buffer, TransactionId OldestXmin)
 		return;
 
 	/*
+	 * We choose to set RecentGlobalXmin only for the current database, which
+	 * means we cannot use it to prune shared relations when reading them with
+	 * MVCC snapshots. By making that choice it allows our snapshots to be
+	 * smaller and faster, and the RecentGlobalXmin will be further forward
+	 * and offer better pruning of non-shared relations. So when accessing a
+	 * shared relation and we see the page is prunable (above) we get an
+	 * OldestXmin across all databases.
+	 */
+	if (IsSharedRelation(relation->rd_id))
+		CutoffXmin = GetOldestXmin(true, true);
+
+	/*
 	 * We prune when a previous UPDATE failed to find enough space on the page
 	 * for a new tuple version, or when free space falls below the relation's
 	 * fill-factor target (but not less than 10%).
@@ -124,7 +137,7 @@ heap_page_prune_opt(Relation relation, Buffer buffer, TransactionId OldestXmin)
 																 * needed */
 
 			/* OK to prune */
-			(void) heap_page_prune(relation, buffer, OldestXmin, true, &ignore);
+			(void) heap_page_prune(relation, buffer, CutoffXmin, true, &ignore);
 		}
 
 		/* And release buffer lock */
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 1a48485..60153f4 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -55,6 +55,7 @@
 #include "storage/spin.h"
 #include "utils/builtins.h"
 #include "utils/snapmgr.h"
+#include "utils/tqual.h"
 
 
 /* Our shared memory area */
@@ -1185,6 +1186,8 @@ GetMaxSnapshotSubxidCount(void)
  *		RecentGlobalXmin: the global xmin (oldest TransactionXmin across all
  *			running transactions, except those running LAZY VACUUM).  This is
  *			the same computation done by GetOldestXmin(true, true).
+ *			For MVCC snapshots we examine transactions running only in our
+ *			database, ignoring longer running transactions in other databases.
  *
  * Note: this function should probably not be called with an argument that's
  * not statically allocated (see xip allocation below).
@@ -1200,9 +1203,12 @@ GetSnapshotData(Snapshot snapshot)
 	int			count = 0;
 	int			subcount = 0;
 	bool		suboverflowed = false;
+	bool		allDbs = false;
 
 	Assert(snapshot != NULL);
 
+	allDbs = !IsMVCCSnapshot(snapshot);
+
 	/*
 	 * Allocating space for maxProcs xids is usually overkill; numProcs would
 	 * be sufficient.  But it seems better to do the malloc while not holding
@@ -1278,6 +1284,12 @@ GetSnapshotData(Snapshot snapshot)
 			if (proc->vacuumFlags & PROC_IN_VACUUM)
 				continue;
 
+			/* MVCC snapshots ignore other databases */
+			if (!allDbs &&
+				proc->databaseId != MyDatabaseId &&
+				proc->databaseId != 0)		/* always include WalSender */
+				continue;
+
 			/* Update globalxmin to be the smallest valid xmin */
 			xid = proc->xmin;	/* fetch just once */
 			if (TransactionIdIsNormal(xid) &&
