diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c
index 555bb13..f53051d 100644
--- a/src/backend/access/transam/varsup.c
+++ b/src/backend/access/transam/varsup.c
@@ -224,6 +224,10 @@ GetNewTransactionId(bool isSubXact)
 			else
 				myproc->subxids.overflowed = true;
 		}
+
+		/* 
+		 * XXX Do we need to invalidate the shared snapshot ?
+		 */
 	}
 
 	LWLockRelease(XidGenLock);
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index e7593fa..91bd26d 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -158,6 +158,8 @@ static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray,
 							   TransactionId xmax);
 static TransactionId KnownAssignedXidsGetOldestXmin(void);
 static void KnownAssignedXidsDisplay(int trace_level);
+static void SetSharedSnapshot(Snapshot snapshot, TransactionId globalxmin);
+static bool GetSharedSnapshot(Snapshot snapshot, TransactionId *globalxmin);
 
 /*
  * Report shared-memory space needed by CreateSharedProcArray.
@@ -379,6 +381,7 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
 								  latestXid))
 			ShmemVariableCache->latestCompletedXid = latestXid;
 
+		ResetSharedSnapshot();
 		LWLockRelease(ProcArrayLock);
 	}
 	else
@@ -1111,6 +1114,60 @@ GetOldestXmin(bool allDbs, bool ignoreVacuum)
 	return result;
 }
 
+static bool
+GetSharedSnapshot(Snapshot snapshot, TransactionId *globalxmin)
+{
+	volatile PROC_HDR *procglobal = ProcGlobal;
+
+	if (!procglobal->sn_isvalid)
+		return false;
+
+	snapshot->xmin = procglobal->sn_xmin;
+	snapshot->xmax = procglobal->sn_xmax;
+	
+	snapshot->xcnt = procglobal->sn_xcnt;
+	if (snapshot->xcnt)
+		memcpy(snapshot->xip, procglobal->sn_xip, snapshot->xcnt);
+	
+	snapshot->subxcnt = procglobal->sn_subxcnt;
+	if (snapshot->subxcnt)
+		memcpy(snapshot->subxip, procglobal->sn_subxip, snapshot->subxcnt);
+	
+	snapshot->suboverflowed = procglobal->sn_suboverflowed;
+	*globalxmin = procglobal->sn_globalxmin;
+
+	return true;
+}
+
+static void
+SetSharedSnapshot(Snapshot snapshot, TransactionId globalxmin)
+{
+	volatile PROC_HDR *procglobal = ProcGlobal;
+
+	procglobal->sn_xmin = snapshot->xmin;
+	procglobal->sn_xmax = snapshot->xmax;
+	
+	procglobal->sn_xcnt = snapshot->xcnt;
+	if (snapshot->xcnt)
+		memcpy(procglobal->sn_xip, snapshot->xip, snapshot->xcnt);
+	
+	procglobal->sn_subxcnt = snapshot->subxcnt;
+	if (snapshot->subxcnt)
+		memcpy(procglobal->sn_subxip, snapshot->subxip, snapshot->subxcnt);
+	
+	procglobal->sn_suboverflowed = snapshot->suboverflowed;
+
+	procglobal->sn_isvalid = true;
+	procglobal->sn_globalxmin = globalxmin;
+}
+
+void
+ResetSharedSnapshot()
+{
+	volatile PROC_HDR *procglobal = ProcGlobal;
+	procglobal->sn_isvalid = false;
+}
+
 /*
  * GetSnapshotData -- returns information about running transactions.
  *
@@ -1216,83 +1273,101 @@ GetSnapshotData(Snapshot snapshot)
 
 	if (!snapshot->takenDuringRecovery)
 	{
-		/*
-		 * Spin over procArray checking xid, xmin, and subxids.  The goal is
-		 * to gather all active xids, find the lowest xmin, and try to record
-		 * subxids. During recovery no xids will be assigned, so all normal
-		 * backends can be ignored, nor are there any VACUUMs running. All
-		 * prepared transaction xids are held in KnownAssignedXids, so these
-		 * will be seen without needing to loop through procs here.
-		 */
-		for (index = 0; index < arrayP->numProcs; index++)
+		if (!GetSharedSnapshot(snapshot, &globalxmin))
 		{
-			volatile PGPROC *proc = arrayP->procs[index];
-			TransactionId xid;
-
-			/* Ignore procs running LAZY VACUUM */
-			if (proc->vacuumFlags & PROC_IN_VACUUM)
-				continue;
-
-			/* Update globalxmin to be the smallest valid xmin */
-			xid = proc->xmin;	/* fetch just once */
-			if (TransactionIdIsNormal(xid) &&
-				TransactionIdPrecedes(xid, globalxmin))
-				globalxmin = xid;
-
-			/* Fetch xid just once - see GetNewTransactionId */
-			xid = proc->xid;
-
 			/*
-			 * If the transaction has been assigned an xid < xmax we add it to
-			 * the snapshot, and update xmin if necessary.	There's no need to
-			 * store XIDs >= xmax, since we'll treat them as running anyway.
-			 * We don't bother to examine their subxids either.
-			 *
-			 * We don't include our own XID (if any) in the snapshot, but we
-			 * must include it into xmin.
+			 * Spin over procArray checking xid, xmin, and subxids.  The goal is
+			 * to gather all active xids, find the lowest xmin, and try to record
+			 * subxids. During recovery no xids will be assigned, so all normal
+			 * backends can be ignored, nor are there any VACUUMs running. All
+			 * prepared transaction xids are held in KnownAssignedXids, so these
+			 * will be seen without needing to loop through procs here.
 			 */
-			if (TransactionIdIsNormal(xid))
+			for (index = 0; index < arrayP->numProcs; index++)
 			{
-				if (TransactionIdFollowsOrEquals(xid, xmax))
+				volatile PGPROC *proc = arrayP->procs[index];
+				TransactionId xid;
+
+				/* Ignore procs running LAZY VACUUM */
+				if (proc->vacuumFlags & PROC_IN_VACUUM)
 					continue;
-				if (proc != MyProc)
-					snapshot->xip[count++] = xid;
-				if (TransactionIdPrecedes(xid, xmin))
-					xmin = xid;
-			}
 
-			/*
-			 * Save subtransaction XIDs if possible (if we've already
-			 * overflowed, there's no point).  Note that the subxact XIDs must
-			 * be later than their parent, so no need to check them against
-			 * xmin.  We could filter against xmax, but it seems better not to
-			 * do that much work while holding the ProcArrayLock.
-			 *
-			 * The other backend can add more subxids concurrently, but cannot
-			 * remove any.	Hence it's important to fetch nxids just once.
-			 * Should be safe to use memcpy, though.  (We needn't worry about
-			 * missing any xids added concurrently, because they must postdate
-			 * xmax.)
-			 *
-			 * Again, our own XIDs are not included in the snapshot.
-			 */
-			if (!suboverflowed && proc != MyProc)
-			{
-				if (proc->subxids.overflowed)
-					suboverflowed = true;
-				else
+				/* Update globalxmin to be the smallest valid xmin */
+				xid = proc->xmin;	/* fetch just once */
+				if (TransactionIdIsNormal(xid) &&
+					TransactionIdPrecedes(xid, globalxmin))
+					globalxmin = xid;
+
+				/* Fetch xid just once - see GetNewTransactionId */
+				xid = proc->xid;
+
+				/*
+				 * If the transaction has been assigned an xid < xmax we add it to
+				 * the snapshot, and update xmin if necessary.	There's no need to
+				 * store XIDs >= xmax, since we'll treat them as running anyway.
+				 * We don't bother to examine their subxids either.
+				 *
+				 * We don't include our own XID (if any) in the snapshot, but we
+				 * must include it into xmin.
+				 */
+				if (TransactionIdIsNormal(xid))
 				{
-					int			nxids = proc->subxids.nxids;
+					if (TransactionIdFollowsOrEquals(xid, xmax))
+						continue;
+					if (proc != MyProc)
+						snapshot->xip[count++] = xid;
+					if (TransactionIdPrecedes(xid, xmin))
+						xmin = xid;
+				}
 
-					if (nxids > 0)
+				/*
+				 * Save subtransaction XIDs if possible (if we've already
+				 * overflowed, there's no point).  Note that the subxact XIDs must
+				 * be later than their parent, so no need to check them against
+				 * xmin.  We could filter against xmax, but it seems better not to
+				 * do that much work while holding the ProcArrayLock.
+				 *
+				 * The other backend can add more subxids concurrently, but cannot
+				 * remove any.	Hence it's important to fetch nxids just once.
+				 * Should be safe to use memcpy, though.  (We needn't worry about
+				 * missing any xids added concurrently, because they must postdate
+				 * xmax.)
+				 *
+				 * Again, our own XIDs are not included in the snapshot.
+				 */
+				if (!suboverflowed && proc != MyProc)
+				{
+					if (proc->subxids.overflowed)
+						suboverflowed = true;
+					else
 					{
-						memcpy(snapshot->subxip + subcount,
-							   (void *) proc->subxids.xids,
-							   nxids * sizeof(TransactionId));
-						subcount += nxids;
+						int			nxids = proc->subxids.nxids;
+
+						if (nxids > 0)
+						{
+							memcpy(snapshot->subxip + subcount,
+								   (void *) proc->subxids.xids,
+								   nxids * sizeof(TransactionId));
+							subcount += nxids;
+						}
 					}
 				}
 			}
+
+			snapshot->xmin = xmin;
+			snapshot->xmax = xmax;
+			snapshot->xcnt = count;
+			snapshot->subxcnt = subcount;
+			snapshot->suboverflowed = suboverflowed;
+
+			/*
+			 * Update globalxmin to include actual process xids.  This is a slightly
+			 * different way of computing it than GetOldestXmin uses, but should give
+			 * the same result.
+			 */
+			if (TransactionIdPrecedes(snapshot->xmin, globalxmin))
+				globalxmin = snapshot->xmin;
+			SetSharedSnapshot(snapshot, globalxmin);
 		}
 	}
 	else
@@ -1325,32 +1400,32 @@ GetSnapshotData(Snapshot snapshot)
 
 		if (TransactionIdPrecedesOrEquals(xmin, procArray->lastOverflowedXid))
 			suboverflowed = true;
+
+		snapshot->xmin = xmin;
+		snapshot->xmax = xmax;
+		snapshot->xcnt = count;
+		snapshot->subxcnt = subcount;
+		snapshot->suboverflowed = suboverflowed;
+
+		/*
+		 * Update globalxmin to include actual process xids.  This is a slightly
+		 * different way of computing it than GetOldestXmin uses, but should give
+		 * the same result.
+		 */
+		if (TransactionIdPrecedes(snapshot->xmin, globalxmin))
+			globalxmin = snapshot->xmin;
 	}
 
 	if (!TransactionIdIsValid(MyProc->xmin))
-		MyProc->xmin = TransactionXmin = xmin;
+		MyProc->xmin = TransactionXmin = snapshot->xmin;
 
 	LWLockRelease(ProcArrayLock);
 
-	/*
-	 * Update globalxmin to include actual process xids.  This is a slightly
-	 * different way of computing it than GetOldestXmin uses, but should give
-	 * the same result.
-	 */
-	if (TransactionIdPrecedes(xmin, globalxmin))
-		globalxmin = xmin;
-
 	/* Update global variables too */
 	RecentGlobalXmin = globalxmin - vacuum_defer_cleanup_age;
 	if (!TransactionIdIsNormal(RecentGlobalXmin))
 		RecentGlobalXmin = FirstNormalTransactionId;
-	RecentXmin = xmin;
-
-	snapshot->xmin = xmin;
-	snapshot->xmax = xmax;
-	snapshot->xcnt = count;
-	snapshot->subxcnt = subcount;
-	snapshot->suboverflowed = suboverflowed;
+	RecentXmin = snapshot->xmin;
 
 	snapshot->curcid = GetCurrentCommandId(false);
 
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index f4091ec..0d82561 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -109,6 +109,9 @@ ProcGlobalShmemSize(void)
 	size = add_size(size, mul_size(NUM_AUXILIARY_PROCS, sizeof(PGPROC)));
 	/* MyProcs, including autovacuum workers and launcher */
 	size = add_size(size, mul_size(MaxBackends, sizeof(PGPROC)));
+	/* Shared snapshot xip/subxip array */
+	size = add_size(size, mul_size(2 * MaxBackends, sizeof (TransactionId)));
+	size = add_size(size, mul_size(2 * NUM_AUXILIARY_PROCS, sizeof (TransactionId)));
 	/* ProcStructLock */
 	size = add_size(size, sizeof(slock_t));
 
@@ -229,6 +232,9 @@ InitProcGlobal(void)
 	 */
 	AuxiliaryProcs = &procs[MaxBackends];
 
+	ProcGlobal->sn_xip = (TransactionId *) ShmemAlloc(sizeof (TransactionId) * (MaxBackends + NUM_AUXILIARY_PROCS));
+	ProcGlobal->sn_subxip = (TransactionId *) ShmemAlloc(sizeof (TransactionId) * (MaxBackends + NUM_AUXILIARY_PROCS));
+
 	/* Create ProcStructLock spinlock, too */
 	ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
 	SpinLockInit(ProcStructLock);
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 8b09b2a..5831f5a 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -183,6 +183,18 @@ typedef struct PROC_HDR
 	int			startupProcPid;
 	/* Buffer id of the buffer that Startup process waits for pin on, or -1 */
 	int			startupBufferPinWaitBufId;
+
+	/* Shared snapshot information */
+	bool		  sn_isvalid;		/* is shared snapshot still valid ? */
+	TransactionId sn_xmin;			/* all XID < xmin are visible to me */
+	TransactionId sn_xmax;			/* all XID >= xmax are invisible to me */
+	uint32		sn_xcnt;			/* # of xact ids in xip[] */
+	TransactionId *sn_xip;			/* array of xact IDs in progress */
+	/* note: all ids in xip[] satisfy xmin <= xip[i] < xmax */
+	int32		sn_subxcnt;		/* # of xact ids in subxip[] */
+	TransactionId *sn_subxip;		/* array of subxact IDs in progress */
+	bool		sn_suboverflowed;	/* has the subxip array overflowed? */
+	TransactionId sn_globalxmin;
 } PROC_HDR;
 
 extern PROC_HDR *ProcGlobal;
diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
index 3c20fc4..ac0211b 100644
--- a/src/include/storage/procarray.h
+++ b/src/include/storage/procarray.h
@@ -70,5 +70,6 @@ extern bool CountOtherDBBackends(Oid databaseId,
 extern void XidCacheRemoveRunningXids(TransactionId xid,
 						  int nxids, const TransactionId *xids,
 						  TransactionId latestXid);
+extern void ResetSharedSnapshot(void);
 
 #endif   /* PROCARRAY_H */
