*** a/src/backend/access/heap/heapam.c --- b/src/backend/access/heap/heapam.c *************** *** 1201,1206 **** heap_beginscan_internal(Relation relation, Snapshot snapshot, --- 1201,1208 ---- */ scan->rs_pageatatime = IsMVCCSnapshot(snapshot); + InitSnapshotNowIfNeeded(snapshot); + /* * For a seqscan in a serializable transaction, acquire a predicate lock * on the entire relation. This is required not only to lock all the *************** *** 1270,1275 **** heap_endscan(HeapScanDesc scan) --- 1272,1279 ---- if (BufferIsValid(scan->rs_cbuf)) ReleaseBuffer(scan->rs_cbuf); + FinishSnapshotNow(scan->rs_snapshot); + /* * decrement relation reference count and free scan descriptor storage */ *************** *** 1680,1685 **** heap_get_latest_tid(Relation relation, --- 1684,1691 ---- if (!ItemPointerIsValid(tid)) return; + InitSnapshotNowIfNeeded(snapshot); + /* * Since this can be called with user-supplied TID, don't trust the input * too much. (RelationGetNumberOfBlocks is an expensive check, so we *************** *** 1775,1780 **** heap_get_latest_tid(Relation relation, --- 1781,1788 ---- priorXmax = HeapTupleHeaderGetXmax(tp.t_data); UnlockReleaseBuffer(buffer); } /* end of loop */ + + FinishSnapshotNow(snapshot); } *** a/src/backend/access/index/indexam.c --- b/src/backend/access/index/indexam.c *************** *** 292,297 **** index_beginscan_internal(Relation indexRelation, --- 292,299 ---- */ RelationIncrementReferenceCount(indexRelation); + InitSnapshotNowIfNeeded(snapshot); + /* * Tell the AM to open a scan. */ *************** *** 370,375 **** index_endscan(IndexScanDesc scan) --- 372,379 ---- /* End the AM's scan */ FunctionCall1(procedure, PointerGetDatum(scan)); + FinishSnapshotNow(scan->xs_snapshot); + /* Release index refcount acquired by index_beginscan */ RelationDecrementReferenceCount(scan->indexRelation); *** a/src/backend/utils/time/snapmgr.c --- b/src/backend/utils/time/snapmgr.c *************** *** 205,210 **** GetLatestSnapshot(void) --- 205,235 ---- return SecondarySnapshot; } + static bool SnapshotNowActive; + + /* + * InitSnapshotNowIfNeeded + * If passed snapshot is SnapshotNow then refresh it with latest info. + */ + void + InitSnapshotNowIfNeeded(Snapshot snap) + { + if (!IsSnapshotNow(snap)) + return; + + if (SnapshotNowActive) + elog(WARNING, "SnapshotNow used concurrently"); + + snap = GetSnapshotData(&SnapshotNowData); + SnapshotNowActive = true; + } + + void FinishSnapshotNow(Snapshot snap) + { + if (IsSnapshotNow(snap)) + SnapshotNowActive = false; + } + /* * SnapshotSetCommandId * Propagate CommandCounterIncrement into the static snapshots, if set *** a/src/backend/utils/time/tqual.c --- b/src/backend/utils/time/tqual.c *************** *** 67,73 **** /* Static variables representing various special snapshot semantics */ ! SnapshotData SnapshotNowData = {HeapTupleSatisfiesNow}; SnapshotData SnapshotSelfData = {HeapTupleSatisfiesSelf}; SnapshotData SnapshotAnyData = {HeapTupleSatisfiesAny}; SnapshotData SnapshotToastData = {HeapTupleSatisfiesToast}; --- 67,73 ---- /* Static variables representing various special snapshot semantics */ ! SnapshotData SnapshotNowData = {HeapTupleSatisfiesMVCC}; SnapshotData SnapshotSelfData = {HeapTupleSatisfiesSelf}; SnapshotData SnapshotAnyData = {HeapTupleSatisfiesAny}; SnapshotData SnapshotToastData = {HeapTupleSatisfiesToast}; *************** *** 293,298 **** HeapTupleSatisfiesSelf(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) --- 293,299 ---- return false; } + #ifdef RECENTLY_DEAD_CODE /* * HeapTupleSatisfiesNow * True iff heap tuple is valid "now". *************** *** 474,479 **** HeapTupleSatisfiesNow(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer) --- 475,481 ---- HeapTupleHeaderGetXmax(tuple)); return false; } + #endif /* * HeapTupleSatisfiesAny *** a/src/include/utils/snapmgr.h --- b/src/include/utils/snapmgr.h *************** *** 24,29 **** extern TransactionId RecentGlobalXmin; --- 24,31 ---- extern Snapshot GetTransactionSnapshot(void); extern Snapshot GetLatestSnapshot(void); + extern void InitSnapshotNowIfNeeded(Snapshot snap); + extern void FinishSnapshotNow(Snapshot snap); extern void SnapshotSetCommandId(CommandId curcid); extern void PushActiveSnapshot(Snapshot snapshot); *** a/src/include/utils/tqual.h --- b/src/include/utils/tqual.h *************** *** 40,45 **** extern PGDLLIMPORT SnapshotData SnapshotToastData; --- 40,47 ---- /* This macro encodes the knowledge of which snapshots are MVCC-safe */ #define IsMVCCSnapshot(snapshot) \ ((snapshot)->satisfies == HeapTupleSatisfiesMVCC) + #define IsSnapshotNow(snapshot) \ + ((snapshot) == (&SnapshotNowData)) /* * HeapTupleSatisfiesVisibility