aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/heap/heapam_visibility.c9
-rw-r--r--src/backend/access/index/genam.c8
-rw-r--r--src/backend/commands/dbcommands.c3
-rw-r--r--src/backend/utils/cache/relcache.c15
-rw-r--r--src/backend/utils/time/snapmgr.c8
5 files changed, 26 insertions, 17 deletions
diff --git a/src/backend/access/heap/heapam_visibility.c b/src/backend/access/heap/heapam_visibility.c
index e146605bd57..05f6946fe60 100644
--- a/src/backend/access/heap/heapam_visibility.c
+++ b/src/backend/access/heap/heapam_visibility.c
@@ -962,6 +962,15 @@ HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot,
{
HeapTupleHeader tuple = htup->t_data;
+ /*
+ * Assert that the caller has registered the snapshot. This function
+ * doesn't care about the registration as such, but in general you
+ * shouldn't try to use a snapshot without registration because it might
+ * get invalidated while it's still in use, and this is a convenient place
+ * to check for that.
+ */
+ Assert(snapshot->regd_count > 0 || snapshot->active_count > 0);
+
Assert(ItemPointerIsValid(&htup->t_self));
Assert(htup->t_tableOid != InvalidOid);
diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
index 886c05655f4..8f532e14590 100644
--- a/src/backend/access/index/genam.c
+++ b/src/backend/access/index/genam.c
@@ -577,17 +577,13 @@ systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup)
Assert(tup == ExecFetchSlotHeapTuple(sysscan->slot, false, NULL));
- /*
- * Trust that table_tuple_satisfies_snapshot() and its subsidiaries
- * (commonly LockBuffer() and HeapTupleSatisfiesMVCC()) do not themselves
- * acquire snapshots, so we need not register the snapshot. Those
- * facilities are too low-level to have any business scanning tables.
- */
freshsnap = GetCatalogSnapshot(RelationGetRelid(sysscan->heap_rel));
+ freshsnap = RegisterSnapshot(freshsnap);
result = table_tuple_satisfies_snapshot(sysscan->heap_rel,
sysscan->slot,
freshsnap);
+ UnregisterSnapshot(freshsnap);
/*
* Handle the concurrent abort while fetching the catalog tuple during
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 1753b289074..5fbbcdaabb1 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -288,7 +288,7 @@ ScanSourceDatabasePgClass(Oid tbid, Oid dbid, char *srcpath)
* snapshot - or the active snapshot - might not be new enough for that,
* but the return value of GetLatestSnapshot() should work fine.
*/
- snapshot = GetLatestSnapshot();
+ snapshot = RegisterSnapshot(GetLatestSnapshot());
/* Process the relation block by block. */
for (blkno = 0; blkno < nblocks; blkno++)
@@ -313,6 +313,7 @@ ScanSourceDatabasePgClass(Oid tbid, Oid dbid, char *srcpath)
UnlockReleaseBuffer(buf);
}
+ UnregisterSnapshot(snapshot);
/* Release relation lock. */
UnlockRelationId(&relid, AccessShareLock);
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index d1ae761b3f6..9f54a9e72b7 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -371,14 +371,13 @@ ScanPgRelation(Oid targetRelId, bool indexOK, bool force_non_historic)
pg_class_desc = table_open(RelationRelationId, AccessShareLock);
/*
- * The caller might need a tuple that's newer than the one the historic
- * snapshot; currently the only case requiring to do so is looking up the
- * relfilenumber of non mapped system relations during decoding. That
- * snapshot can't change in the midst of a relcache build, so there's no
- * need to register the snapshot.
+ * The caller might need a tuple that's newer than what's visible to the
+ * historic snapshot; currently the only case requiring to do so is
+ * looking up the relfilenumber of non mapped system relations during
+ * decoding.
*/
if (force_non_historic)
- snapshot = GetNonHistoricCatalogSnapshot(RelationRelationId);
+ snapshot = RegisterSnapshot(GetNonHistoricCatalogSnapshot(RelationRelationId));
pg_class_scan = systable_beginscan(pg_class_desc, ClassOidIndexId,
indexOK && criticalRelcachesBuilt,
@@ -395,6 +394,10 @@ ScanPgRelation(Oid targetRelId, bool indexOK, bool force_non_historic)
/* all done */
systable_endscan(pg_class_scan);
+
+ if (snapshot)
+ UnregisterSnapshot(snapshot);
+
table_close(pg_class_desc, AccessShareLock);
return pg_class_tuple;
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index 8f1508b1ee2..6ed1c93383e 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -203,10 +203,10 @@ typedef struct SerializedSnapshotData
* GetTransactionSnapshot
* Get the appropriate snapshot for a new query in a transaction.
*
- * Note that the return value may point at static storage that will be modified
- * by future calls and by CommandCounterIncrement(). Callers should call
- * RegisterSnapshot or PushActiveSnapshot on the returned snap if it is to be
- * used very long.
+ * Note that the return value points at static storage that will be modified
+ * by future calls and by CommandCounterIncrement(). Callers must call
+ * RegisterSnapshot or PushActiveSnapshot on the returned snap before doing
+ * any other non-trivial work that could invalidate it.
*/
Snapshot
GetTransactionSnapshot(void)