1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-22 12:22:45 +03:00

Remove remants of "snapshot too old"

Remove the 'whenTaken' and 'lsn' fields from SnapshotData. After the
removal of the "snapshot too old" feature, they were never set to a
non-zero value.

This largely reverts commit 3e2f3c2e42, which added the
OldestActiveSnapshot tracking, and the init_toast_snapshot()
function. That was only required for setting the 'whenTaken' and 'lsn'
fields. SnapshotToast is now a constant again, like SnapshotSelf and
SnapshotAny. I kept a thin get_toast_snapshot() wrapper around
SnapshotToast though, to check that you have a registered or active
snapshot. That's still a useful sanity check.

Reviewed-by: Nathan Bossart, Andres Freund, Tom Lane
Discussion: https://www.postgresql.org/message-id/cd4b4f8c-e63a-41c0-95f6-6e6cd9b83f6d@iki.fi
This commit is contained in:
Heikki Linnakangas
2024-12-09 18:13:03 +02:00
parent f64ec81a81
commit 4d8275046c
10 changed files with 28 additions and 114 deletions

View File

@@ -393,7 +393,6 @@ toast_delete_datum(Relation rel, Datum value, bool is_speculative)
HeapTuple toasttup;
int num_indexes;
int validIndex;
SnapshotData SnapshotToast;
if (!VARATT_IS_EXTERNAL_ONDISK(attr))
return;
@@ -425,9 +424,8 @@ toast_delete_datum(Relation rel, Datum value, bool is_speculative)
* sequence or not, but since we've already locked the index we might as
* well use systable_beginscan_ordered.)
*/
init_toast_snapshot(&SnapshotToast);
toastscan = systable_beginscan_ordered(toastrel, toastidxs[validIndex],
&SnapshotToast, 1, &toastkey);
get_toast_snapshot(), 1, &toastkey);
while ((toasttup = systable_getnext_ordered(toastscan, ForwardScanDirection)) != NULL)
{
/*
@@ -631,41 +629,28 @@ toast_close_indexes(Relation *toastidxs, int num_indexes, LOCKMODE lock)
}
/* ----------
* init_toast_snapshot
* get_toast_snapshot
*
* Initialize an appropriate TOAST snapshot. We must use an MVCC snapshot
* to initialize the TOAST snapshot; since we don't know which one to use,
* just use the oldest one.
* Return the TOAST snapshot. Detoasting *must* happen in the same
* transaction that originally fetched the toast pointer.
*/
void
init_toast_snapshot(Snapshot toast_snapshot)
Snapshot
get_toast_snapshot(void)
{
Snapshot snapshot = GetOldestSnapshot();
/*
* GetOldestSnapshot returns NULL if the session has no active snapshots.
* We can get that if, for example, a procedure fetches a toasted value
* into a local variable, commits, and then tries to detoast the value.
* Such coding is unsafe, because once we commit there is nothing to
* prevent the toast data from being deleted. Detoasting *must* happen in
* the same transaction that originally fetched the toast pointer. Hence,
* rather than trying to band-aid over the problem, throw an error. (This
* is not very much protection, because in many scenarios the procedure
* would have already created a new transaction snapshot, preventing us
* from detecting the problem. But it's better than nothing, and for sure
* we shouldn't expend code on masking the problem more.)
* We cannot directly check that detoasting happens in the same
* transaction that originally fetched the toast pointer, but at least
* check that the session has some active snapshots. It might not if, for
* example, a procedure fetches a toasted value into a local variable,
* commits, and then tries to detoast the value. Such coding is unsafe,
* because once we commit there is nothing to prevent the toast data from
* being deleted. (This is not very much protection, because in many
* scenarios the procedure would have already created a new transaction
* snapshot, preventing us from detecting the problem. But it's better
* than nothing.)
*/
if (snapshot == NULL)
if (!HaveRegisteredOrActiveSnapshot())
elog(ERROR, "cannot fetch toast data without an active snapshot");
/*
* Catalog snapshots can be returned by GetOldestSnapshot() even if not
* registered or active. That easily hides bugs around not having a
* snapshot set up - most of the time there is a valid catalog snapshot.
* So additionally insist that the current snapshot is registered or
* active.
*/
Assert(HaveRegisteredOrActiveSnapshot());
InitToastSnapshot(*toast_snapshot, snapshot->lsn, snapshot->whenTaken);
return &SnapshotToastData;
}

View File

@@ -639,7 +639,6 @@ heap_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize,
int endchunk;
int num_indexes;
int validIndex;
SnapshotData SnapshotToast;
/* Look for the valid index of toast relation */
validIndex = toast_open_indexes(toastrel,
@@ -685,9 +684,8 @@ heap_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize,
}
/* Prepare for scan */
init_toast_snapshot(&SnapshotToast);
toastscan = systable_beginscan_ordered(toastrel, toastidxs[validIndex],
&SnapshotToast, nscankeys, toastkey);
get_toast_snapshot(), nscankeys, toastkey);
/*
* Read the chunks by index