diff options
author | Robert Haas <rhaas@postgresql.org> | 2016-08-03 16:41:43 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2016-08-03 16:50:01 -0400 |
commit | 3e2f3c2e423b3ae906668c186bac79522b8e3e29 (patch) | |
tree | 0223b912d722860ed070bf95719d52e7a3758090 /src/backend/utils | |
parent | a3c7a993d5eb29df4d33075b83c75ae25f257897 (diff) | |
download | postgresql-3e2f3c2e423b3ae906668c186bac79522b8e3e29.tar.gz postgresql-3e2f3c2e423b3ae906668c186bac79522b8e3e29.zip |
Prevent "snapshot too old" from trying to return pruned TOAST tuples.
Previously, we tested for MVCC snapshots to see whether they were too
old, but not TOAST snapshots, which can lead to complaints about missing
TOAST chunks if those chunks are subject to early pruning. Ideally,
the threshold lsn and timestamp for a TOAST snapshot would be that of
the corresponding MVCC snapshot, but since we have no way of deciding
which MVCC snapshot was used to fetch the TOAST pointer, use the oldest
active or registered snapshot instead.
Reported by Andres Freund, who also sketched out what the fix should
look like. Patch by me, reviewed by Amit Kapila.
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/time/snapmgr.c | 38 | ||||
-rw-r--r-- | src/backend/utils/time/tqual.c | 1 |
2 files changed, 38 insertions, 1 deletions
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index e1caf01c603..4bddaed33ba 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -188,6 +188,9 @@ typedef struct ActiveSnapshotElt /* Top of the stack of active snapshots */ static ActiveSnapshotElt *ActiveSnapshot = NULL; +/* Bottom of the stack of active snapshots */ +static ActiveSnapshotElt *OldestActiveSnapshot = NULL; + /* * Currently registered Snapshots. Ordered in a heap by xmin, so that we can * quickly find the one with lowest xmin, to advance our MyPgXat->xmin. @@ -394,6 +397,34 @@ GetLatestSnapshot(void) } /* + * GetOldestSnapshot + * + * Get the oldest known snapshot, as judged by the LSN. + */ +Snapshot +GetOldestSnapshot(void) +{ + Snapshot OldestRegisteredSnapshot = NULL; + XLogRecPtr RegisteredLSN = InvalidXLogRecPtr; + XLogRecPtr ActiveLSN = InvalidXLogRecPtr; + + if (!pairingheap_is_empty(&RegisteredSnapshots)) + { + OldestRegisteredSnapshot = pairingheap_container(SnapshotData, ph_node, + pairingheap_first(&RegisteredSnapshots)); + RegisteredLSN = OldestRegisteredSnapshot->lsn; + } + + if (OldestActiveSnapshot != NULL) + ActiveLSN = OldestActiveSnapshot->as_snap->lsn; + + if (XLogRecPtrIsInvalid(RegisteredLSN) || RegisteredLSN > ActiveLSN) + return OldestActiveSnapshot->as_snap; + + return OldestRegisteredSnapshot; +} + +/* * GetCatalogSnapshot * Get a snapshot that is sufficiently up-to-date for scan of the * system catalog with the specified OID. @@ -674,6 +705,8 @@ PushActiveSnapshot(Snapshot snap) newactive->as_snap->active_count++; ActiveSnapshot = newactive; + if (OldestActiveSnapshot == NULL) + OldestActiveSnapshot = ActiveSnapshot; } /* @@ -744,6 +777,8 @@ PopActiveSnapshot(void) pfree(ActiveSnapshot); ActiveSnapshot = newstack; + if (ActiveSnapshot == NULL) + OldestActiveSnapshot = NULL; SnapshotResetXmin(); } @@ -953,6 +988,8 @@ AtSubAbort_Snapshot(int level) pfree(ActiveSnapshot); ActiveSnapshot = next; + if (ActiveSnapshot == NULL) + OldestActiveSnapshot = NULL; } SnapshotResetXmin(); @@ -1037,6 +1074,7 @@ AtEOXact_Snapshot(bool isCommit) * it'll go away with TopTransactionContext. */ ActiveSnapshot = NULL; + OldestActiveSnapshot = NULL; pairingheap_reset(&RegisteredSnapshots); CurrentSnapshot = NULL; diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c index 2960455d6e3..d99c847000e 100644 --- a/src/backend/utils/time/tqual.c +++ b/src/backend/utils/time/tqual.c @@ -78,7 +78,6 @@ /* Static variables representing various special snapshot semantics */ SnapshotData SnapshotSelfData = {HeapTupleSatisfiesSelf}; SnapshotData SnapshotAnyData = {HeapTupleSatisfiesAny}; -SnapshotData SnapshotToastData = {HeapTupleSatisfiesToast}; /* local functions */ static bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot); |