Content-Length: 628638 | pFad | http://github.com/postgres/postgres/commit/24135398f1e18e7779fd5052af8399c9d6bb5ff7

52 Ensure we have a snapshot when updating various system catalogs. · postgres/postgres@2413539 · GitHub
Skip to content

Commit 2413539

Browse files
Ensure we have a snapshot when updating various system catalogs.
A few places that access system catalogs don't set up an active snapshot before potentially accessing their TOAST tables. To fix, push an active snapshot just before each section of code that might require accessing one of these TOAST tables, and pop it shortly afterwards. While at it, this commit adds some rather strict assertions in an attempt to prevent such issues in the future. Commit 16bf24e recently removed pg_replication_origen's TOAST table in order to fix the same problem for that catalog. On the back-branches, those bugs are left in place. We cannot easily remove a catalog's TOAST table on released major versions, and only replication origens with extremely long names are affected. Given the low severity of the issue, fixing older versions doesn't seem worth the trouble of significantly modifying the patch. Also, on v13 and v14, the aforementioned strict assertions have been omitted because commit 2776922, which added HaveRegisteredOrActiveSnapshot(), was not back-patched. While we could probably back-patch it now, I've opted against it because it seems unlikely that new TOAST snapshot issues will be introduced in the oldest supported versions. Reported-by: Alexander Lakhin <exclusion@gmail.com> Reviewed-by: Michael Paquier <michael@paquier.xyz> Discussion: https://postgr.es/m/18127-fe54b6a667f29658%40postgresql.org Discussion: https://postgr.es/m/18309-c0bf914950c46692%40postgresql.org Discussion: https://postgr.es/m/ZvMSUPOqUU-VNADN%40nathan Backpatch-through: 13
1 parent 2b92dc4 commit 2413539

File tree

5 files changed

+88
-0
lines changed

5 files changed

+88
-0
lines changed

src/backend/access/heap/heapam.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include "catalog/catalog.h"
5555
#include "catalog/pg_database.h"
5656
#include "catalog/pg_database_d.h"
57+
#include "catalog/pg_replication_origen.h"
5758
#include "commands/vacuum.h"
5859
#include "miscadmin.h"
5960
#include "pgstat.h"
@@ -231,6 +232,38 @@ static const int MultiXactStatusLock[MaxMultiXactStatus + 1] =
231232
#define TUPLOCK_from_mxstatus(status) \
232233
(MultiXactStatusLock[(status)])
233234

235+
/*
236+
* Check that we have a valid snapshot if we might need TOAST access.
237+
*/
238+
static inline void
239+
AssertHasSnapshotForToast(Relation rel)
240+
{
241+
#ifdef USE_ASSERT_CHECKING
242+
243+
/* bootstrap mode in particular breaks this rule */
244+
if (!IsNormalProcessingMode())
245+
return;
246+
247+
/* if the relation doesn't have a TOAST table, we are good */
248+
if (!OidIsValid(rel->rd_rel->reltoastrelid))
249+
return;
250+
251+
/*
252+
* Commit 16bf24e fixed accesses to pg_replication_origen without a
253+
* an active snapshot by removing its TOAST table. On older branches,
254+
* these bugs are left in place. Its only varlena column is roname (the
255+
* replication origen name), so this is only a problem if the name
256+
* requires out-of-line storage, which seems unlikely. In any case,
257+
* fixing it doesn't seem worth extra code churn on the back-branches.
258+
*/
259+
if (RelationGetRelid(rel) == ReplicationOriginRelationId)
260+
return;
261+
262+
Assert(HaveRegisteredOrActiveSnapshot());
263+
264+
#endif /* USE_ASSERT_CHECKING */
265+
}
266+
234267
/* ----------------------------------------------------------------
235268
* heap support routines
236269
* ----------------------------------------------------------------
@@ -1858,6 +1891,8 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
18581891
Assert(HeapTupleHeaderGetNatts(tup->t_data) <=
18591892
RelationGetNumberOfAttributes(relation));
18601893

1894+
AssertHasSnapshotForToast(relation);
1895+
18611896
/*
18621897
* Fill in tuple header fields and toast the tuple if necessary.
18631898
*
@@ -2135,6 +2170,8 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples,
21352170
/* currently not needed (thus unsupported) for heap_multi_insert() */
21362171
Assert(!(options & HEAP_INSERT_NO_LOGICAL));
21372172

2173+
AssertHasSnapshotForToast(relation);
2174+
21382175
needwal = RelationNeedsWAL(relation);
21392176
saveFreeSpace = RelationGetTargetPageFreeSpace(relation,
21402177
HEAP_DEFAULT_FILLFACTOR);
@@ -2557,6 +2594,8 @@ heap_delete(Relation relation, ItemPointer tid,
25572594

25582595
Assert(ItemPointerIsValid(tid));
25592596

2597+
AssertHasSnapshotForToast(relation);
2598+
25602599
/*
25612600
* Forbid this during a parallel operation, lest it allocate a combo CID.
25622601
* Other workers might need that combo CID for visibility checks, and we
@@ -3052,6 +3091,8 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
30523091
Assert(HeapTupleHeaderGetNatts(newtup->t_data) <=
30533092
RelationGetNumberOfAttributes(relation));
30543093

3094+
AssertHasSnapshotForToast(relation);
3095+
30553096
/*
30563097
* Forbid this during a parallel operation, lest it allocate a combo CID.
30573098
* Other workers might need that combo CID for visibility checks, and we

src/backend/commands/indexcmds.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4064,12 +4064,20 @@ ReindexRelationConcurrently(Oid relationOid, ReindexParams *params)
40644064
get_rel_namespace(oldidx->tableId),
40654065
false);
40664066

4067+
/*
4068+
* Swapping the indexes might involve TOAST table access, so ensure we
4069+
* have a valid snapshot.
4070+
*/
4071+
PushActiveSnapshot(GetTransactionSnapshot());
4072+
40674073
/*
40684074
* Swap old index with the new one. This also marks the new one as
40694075
* valid and the old one as not valid.
40704076
*/
40714077
index_concurrently_swap(newidx->indexId, oldidx->indexId, oldName);
40724078

4079+
PopActiveSnapshot();
4080+
40734081
/*
40744082
* Invalidate the relcache for the table, so that after this commit
40754083
* all sessions will refresh any cached plans that might reference the

src/backend/commands/tablecmds.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18789,9 +18789,17 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel,
1878918789
tab->rel = rel;
1879018790
}
1879118791

18792+
/*
18793+
* Detaching the partition might involve TOAST table access, so ensure we
18794+
* have a valid snapshot.
18795+
*/
18796+
PushActiveSnapshot(GetTransactionSnapshot());
18797+
1879218798
/* Do the final part of detaching */
1879318799
DetachPartitionFinalize(rel, partRel, concurrent, defaultPartOid);
1879418800

18801+
PopActiveSnapshot();
18802+
1879518803
ObjectAddressSet(address, RelationRelationId, RelationGetRelid(partRel));
1879618804

1879718805
/* keep our lock until commit */

src/backend/postmaster/autovacuum.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2372,6 +2372,12 @@ do_autovacuum(void)
23722372
get_namespace_name(classForm->relnamespace),
23732373
NameStr(classForm->relname))));
23742374

2375+
/*
2376+
* Deletion might involve TOAST table access, so ensure we have a
2377+
* valid snapshot.
2378+
*/
2379+
PushActiveSnapshot(GetTransactionSnapshot());
2380+
23752381
object.classId = RelationRelationId;
23762382
object.objectId = relid;
23772383
object.objectSubId = 0;
@@ -2384,6 +2390,7 @@ do_autovacuum(void)
23842390
* To commit the deletion, end current transaction and start a new
23852391
* one. Note this also releases the locks we took.
23862392
*/
2393+
PopActiveSnapshot();
23872394
CommitTransactionCommand();
23882395
StartTransactionCommand();
23892396

src/backend/replication/logical/worker.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4725,8 +4725,16 @@ ApplyWorkerMain(Datum main_arg)
47254725
walrcv_startstreaming(LogRepWorkerWalRcvConn, &options);
47264726

47274727
StartTransactionCommand();
4728+
4729+
/*
4730+
* Updating pg_subscription might involve TOAST table access, so
4731+
* ensure we have a valid snapshot.
4732+
*/
4733+
PushActiveSnapshot(GetTransactionSnapshot());
4734+
47284735
UpdateTwoPhaseState(MySubscription->oid, LOGICALREP_TWOPHASE_STATE_ENABLED);
47294736
MySubscription->twophasestate = LOGICALREP_TWOPHASE_STATE_ENABLED;
4737+
PopActiveSnapshot();
47304738
CommitTransactionCommand();
47314739
}
47324740
else
@@ -4779,7 +4787,15 @@ DisableSubscriptionAndExit(void)
47794787

47804788
/* Disable the subscription */
47814789
StartTransactionCommand();
4790+
4791+
/*
4792+
* Updating pg_subscription might involve TOAST table access, so ensure we
4793+
* have a valid snapshot.
4794+
*/
4795+
PushActiveSnapshot(GetTransactionSnapshot());
4796+
47824797
DisableSubscription(MySubscription->oid);
4798+
PopActiveSnapshot();
47834799
CommitTransactionCommand();
47844800

47854801
/* Ensure we remove no-longer-useful entry for worker's start time */
@@ -4883,6 +4899,12 @@ clear_subscription_skip_lsn(XLogRecPtr finish_lsn)
48834899
started_tx = true;
48844900
}
48854901

4902+
/*
4903+
* Updating pg_subscription might involve TOAST table access, so ensure we
4904+
* have a valid snapshot.
4905+
*/
4906+
PushActiveSnapshot(GetTransactionSnapshot());
4907+
48864908
/*
48874909
* Protect subskiplsn of pg_subscription from being concurrently updated
48884910
* while clearing it.
@@ -4941,6 +4963,8 @@ clear_subscription_skip_lsn(XLogRecPtr finish_lsn)
49414963
heap_freetuple(tup);
49424964
table_close(rel, NoLock);
49434965

4966+
PopActiveSnapshot();
4967+
49444968
if (started_tx)
49454969
CommitTransactionCommand();
49464970
}

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/postgres/postgres/commit/24135398f1e18e7779fd5052af8399c9d6bb5ff7

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy