Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4ce3afb

Browse files
Refactor how VACUUM passes around its XID cutoffs.
Use a dedicated struct for the XID/MXID cutoffs used by VACUUM, such asFreezeLimit and OldestXmin. This state is initialized in vacuum.c, andthen passed around by code from vacuumlazy.c to heapam.c freezingrelated routines. The new convention is that everybody works off of thesame cutoff state, which is passed around via pointers to const.Also simplify some of the logic for dealing with frozen xmin inheap_prepare_freeze_tuple: add dedicated "xmin_already_frozen" state toclearly distinguish xmin XIDs that we're going to freeze from those thatwere already frozen from before. That way the routine's xmin handlingcode is symmetrical with the existing xmax handling code. This ispreparation for an upcoming commit that will add page level freezing.Also refactor the control flow within FreezeMultiXactId(), while addingstricter sanity checks. We now test OldestXmin directly, instead ofusing FreezeLimit as an inexact proxy for OldestXmin. This is furtherpreparation for the page level freezing work, which will make thefunction's caller cede control of page level freezing to the functionwhere appropriate (where heap_prepare_freeze_tuple sees a tuple thathappens to contain a MultiXactId in its xmax).Author: Peter Geoghegan <pg@bowt.ie>Reviewed-By: Jeff Davis <pgsql@j-davis.com>Discussion:https://postgr.es/m/CAH2-WznS9TxXmz2_=SY+SyJyDFbiOftKofM9=aDo68BbXNBUMA@mail.gmail.com
1 parente42e312 commit4ce3afb

File tree

8 files changed

+431
-458
lines changed

8 files changed

+431
-458
lines changed

‎src/backend/access/heap/heapam.c

Lines changed: 232 additions & 246 deletions
Large diffs are not rendered by default.

‎src/backend/access/heap/vacuumlazy.c

Lines changed: 81 additions & 115 deletions
Large diffs are not rendered by default.

‎src/backend/access/transam/multixact.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2813,14 +2813,11 @@ ReadMultiXactCounts(uint32 *multixacts, MultiXactOffset *members)
28132813
* As the fraction of the member space currently in use grows, we become
28142814
* more aggressive in clamping this value. That not only causes autovacuum
28152815
* to ramp up, but also makes any manual vacuums the user issues more
2816-
* aggressive. This happens becausevacuum_set_xid_limits()clamps the
2817-
* freeze table and the minimum freeze age based on the effective
2816+
* aggressive. This happens becausevacuum_get_cutoffs()will clamp the
2817+
* freeze table and the minimum freeze agecutoffsbased on the effective
28182818
* autovacuum_multixact_freeze_max_age this function returns. In the worst
28192819
* case, we'll claim the freeze_max_age to zero, and every vacuum of any
2820-
* table will try to freeze every multixact.
2821-
*
2822-
* It's possible that these thresholds should be user-tunable, but for now
2823-
* we keep it simple.
2820+
* table will freeze every multixact.
28242821
*/
28252822
int
28262823
MultiXactMemberFreezeThreshold(void)

‎src/backend/commands/cluster.c

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -826,10 +826,7 @@ copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
826826
TupleDescoldTupDescPG_USED_FOR_ASSERTS_ONLY;
827827
TupleDescnewTupDescPG_USED_FOR_ASSERTS_ONLY;
828828
VacuumParamsparams;
829-
TransactionIdOldestXmin,
830-
FreezeXid;
831-
MultiXactIdOldestMxact,
832-
MultiXactCutoff;
829+
structVacuumCutoffscutoffs;
833830
booluse_sort;
834831
doublenum_tuples=0,
835832
tups_vacuumed=0,
@@ -918,23 +915,24 @@ copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
918915
* not to be aggressive about this.
919916
*/
920917
memset(&params,0,sizeof(VacuumParams));
921-
vacuum_set_xid_limits(OldHeap,&params,&OldestXmin,&OldestMxact,
922-
&FreezeXid,&MultiXactCutoff);
918+
vacuum_get_cutoffs(OldHeap,&params,&cutoffs);
923919

924920
/*
925921
* FreezeXid will become the table's new relfrozenxid, and that mustn't go
926922
* backwards, so take the max.
927923
*/
928924
if (TransactionIdIsValid(OldHeap->rd_rel->relfrozenxid)&&
929-
TransactionIdPrecedes(FreezeXid,OldHeap->rd_rel->relfrozenxid))
930-
FreezeXid=OldHeap->rd_rel->relfrozenxid;
925+
TransactionIdPrecedes(cutoffs.FreezeLimit,
926+
OldHeap->rd_rel->relfrozenxid))
927+
cutoffs.FreezeLimit=OldHeap->rd_rel->relfrozenxid;
931928

932929
/*
933930
* MultiXactCutoff, similarly, shouldn't go backwards either.
934931
*/
935932
if (MultiXactIdIsValid(OldHeap->rd_rel->relminmxid)&&
936-
MultiXactIdPrecedes(MultiXactCutoff,OldHeap->rd_rel->relminmxid))
937-
MultiXactCutoff=OldHeap->rd_rel->relminmxid;
933+
MultiXactIdPrecedes(cutoffs.MultiXactCutoff,
934+
OldHeap->rd_rel->relminmxid))
935+
cutoffs.MultiXactCutoff=OldHeap->rd_rel->relminmxid;
938936

939937
/*
940938
* Decide whether to use an indexscan or seqscan-and-optional-sort to scan
@@ -973,13 +971,14 @@ copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
973971
* values (e.g. because the AM doesn't use freezing).
974972
*/
975973
table_relation_copy_for_cluster(OldHeap,NewHeap,OldIndex,use_sort,
976-
OldestXmin,&FreezeXid,&MultiXactCutoff,
974+
cutoffs.OldestXmin,&cutoffs.FreezeLimit,
975+
&cutoffs.MultiXactCutoff,
977976
&num_tuples,&tups_vacuumed,
978977
&tups_recently_dead);
979978

980979
/* return selected values to caller, get set as relfrozenxid/minmxid */
981-
*pFreezeXid=FreezeXid;
982-
*pCutoffMulti=MultiXactCutoff;
980+
*pFreezeXid=cutoffs.FreezeLimit;
981+
*pCutoffMulti=cutoffs.MultiXactCutoff;
983982

984983
/* Reset rd_toastoid just to be tidy --- it shouldn't be looked at again */
985984
NewHeap->rd_toastoid=InvalidOid;

‎src/backend/commands/vacuum.c

Lines changed: 55 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -907,34 +907,20 @@ get_all_vacuum_rels(int options)
907907
}
908908

909909
/*
910-
*vacuum_set_xid_limits() -- compute OldestXmin and freeze cutoff points
910+
*vacuum_get_cutoffs() -- compute OldestXmin and freeze cutoff points
911911
*
912912
* The target relation and VACUUM parameters are our inputs.
913913
*
914-
* Our output parameters are:
915-
* - OldestXmin is the Xid below which tuples deleted by any xact (that
916-
* committed) should be considered DEAD, not just RECENTLY_DEAD.
917-
* - OldestMxact is the Mxid below which MultiXacts are definitely not
918-
* seen as visible by any running transaction.
919-
* - FreezeLimit is the Xid below which all Xids are definitely frozen or
920-
* removed during aggressive vacuums.
921-
* - MultiXactCutoff is the value below which all MultiXactIds are definitely
922-
* removed from Xmax during aggressive vacuums.
914+
* Output parameters are the cutoffs that VACUUM caller should use.
923915
*
924916
* Return value indicates if vacuumlazy.c caller should make its VACUUM
925917
* operation aggressive. An aggressive VACUUM must advance relfrozenxid up to
926918
* FreezeLimit (at a minimum), and relminmxid up to MultiXactCutoff (at a
927919
* minimum).
928-
*
929-
* OldestXmin and OldestMxact are the most recent values that can ever be
930-
* passed to vac_update_relstats() as frozenxid and minmulti arguments by our
931-
* vacuumlazy.c caller later on. These values should be passed when it turns
932-
* out that VACUUM will leave no unfrozen XIDs/MXIDs behind in the table.
933920
*/
934921
bool
935-
vacuum_set_xid_limits(Relationrel,constVacuumParams*params,
936-
TransactionId*OldestXmin,MultiXactId*OldestMxact,
937-
TransactionId*FreezeLimit,MultiXactId*MultiXactCutoff)
922+
vacuum_get_cutoffs(Relationrel,constVacuumParams*params,
923+
structVacuumCutoffs*cutoffs)
938924
{
939925
intfreeze_min_age,
940926
multixact_freeze_min_age,
@@ -954,6 +940,10 @@ vacuum_set_xid_limits(Relation rel, const VacuumParams *params,
954940
freeze_table_age=params->freeze_table_age;
955941
multixact_freeze_table_age=params->multixact_freeze_table_age;
956942

943+
/* Set pg_class fields in cutoffs */
944+
cutoffs->relfrozenxid=rel->rd_rel->relfrozenxid;
945+
cutoffs->relminmxid=rel->rd_rel->relminmxid;
946+
957947
/*
958948
* Acquire OldestXmin.
959949
*
@@ -965,14 +955,14 @@ vacuum_set_xid_limits(Relation rel, const VacuumParams *params,
965955
* that only one vacuum process can be working on a particular table at
966956
* any time, and that each vacuum is always an independent transaction.
967957
*/
968-
*OldestXmin=GetOldestNonRemovableTransactionId(rel);
958+
cutoffs->OldestXmin=GetOldestNonRemovableTransactionId(rel);
969959

970960
if (OldSnapshotThresholdActive())
971961
{
972962
TransactionIdlimit_xmin;
973963
TimestampTzlimit_ts;
974964

975-
if (TransactionIdLimitedForOldSnapshots(*OldestXmin,rel,
965+
if (TransactionIdLimitedForOldSnapshots(cutoffs->OldestXmin,rel,
976966
&limit_xmin,&limit_ts))
977967
{
978968
/*
@@ -982,20 +972,48 @@ vacuum_set_xid_limits(Relation rel, const VacuumParams *params,
982972
* frequency), but would still be a significant improvement.
983973
*/
984974
SetOldSnapshotThresholdTimestamp(limit_ts,limit_xmin);
985-
*OldestXmin=limit_xmin;
975+
cutoffs->OldestXmin=limit_xmin;
986976
}
987977
}
988978

989-
Assert(TransactionIdIsNormal(*OldestXmin));
979+
Assert(TransactionIdIsNormal(cutoffs->OldestXmin));
990980

991981
/* Acquire OldestMxact */
992-
*OldestMxact=GetOldestMultiXactId();
993-
Assert(MultiXactIdIsValid(*OldestMxact));
982+
cutoffs->OldestMxact=GetOldestMultiXactId();
983+
Assert(MultiXactIdIsValid(cutoffs->OldestMxact));
994984

995985
/* Acquire next XID/next MXID values used to apply age-based settings */
996986
nextXID=ReadNextTransactionId();
997987
nextMXID=ReadNextMultiXactId();
998988

989+
/*
990+
* Also compute the multixact age for which freezing is urgent. This is
991+
* normally autovacuum_multixact_freeze_max_age, but may be less if we are
992+
* short of multixact member space.
993+
*/
994+
effective_multixact_freeze_max_age=MultiXactMemberFreezeThreshold();
995+
996+
/*
997+
* Almost ready to set freeze output parameters; check if OldestXmin or
998+
* OldestMxact are held back to an unsafe degree before we start on that
999+
*/
1000+
safeOldestXmin=nextXID-autovacuum_freeze_max_age;
1001+
if (!TransactionIdIsNormal(safeOldestXmin))
1002+
safeOldestXmin=FirstNormalTransactionId;
1003+
safeOldestMxact=nextMXID-effective_multixact_freeze_max_age;
1004+
if (safeOldestMxact<FirstMultiXactId)
1005+
safeOldestMxact=FirstMultiXactId;
1006+
if (TransactionIdPrecedes(cutoffs->OldestXmin,safeOldestXmin))
1007+
ereport(WARNING,
1008+
(errmsg("cutoff for removing and freezing tuples is far in the past"),
1009+
errhint("Close open transactions soon to avoid wraparound problems.\n"
1010+
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1011+
if (MultiXactIdPrecedes(cutoffs->OldestMxact,safeOldestMxact))
1012+
ereport(WARNING,
1013+
(errmsg("cutoff for freezing multixacts is far in the past"),
1014+
errhint("Close open transactions soon to avoid wraparound problems.\n"
1015+
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1016+
9991017
/*
10001018
* Determine the minimum freeze age to use: as specified by the caller, or
10011019
* vacuum_freeze_min_age, but in any case not more than half
@@ -1008,19 +1026,12 @@ vacuum_set_xid_limits(Relation rel, const VacuumParams *params,
10081026
Assert(freeze_min_age >=0);
10091027

10101028
/* Compute FreezeLimit, being careful to generate a normal XID */
1011-
*FreezeLimit=nextXID-freeze_min_age;
1012-
if (!TransactionIdIsNormal(*FreezeLimit))
1013-
*FreezeLimit=FirstNormalTransactionId;
1029+
cutoffs->FreezeLimit=nextXID-freeze_min_age;
1030+
if (!TransactionIdIsNormal(cutoffs->FreezeLimit))
1031+
cutoffs->FreezeLimit=FirstNormalTransactionId;
10141032
/* FreezeLimit must always be <= OldestXmin */
1015-
if (TransactionIdPrecedes(*OldestXmin,*FreezeLimit))
1016-
*FreezeLimit=*OldestXmin;
1017-
1018-
/*
1019-
* Compute the multixact age for which freezing is urgent. This is
1020-
* normally autovacuum_multixact_freeze_max_age, but may be less if we are
1021-
* short of multixact member space.
1022-
*/
1023-
effective_multixact_freeze_max_age=MultiXactMemberFreezeThreshold();
1033+
if (TransactionIdPrecedes(cutoffs->OldestXmin,cutoffs->FreezeLimit))
1034+
cutoffs->FreezeLimit=cutoffs->OldestXmin;
10241035

10251036
/*
10261037
* Determine the minimum multixact freeze age to use: as specified by
@@ -1035,33 +1046,12 @@ vacuum_set_xid_limits(Relation rel, const VacuumParams *params,
10351046
Assert(multixact_freeze_min_age >=0);
10361047

10371048
/* Compute MultiXactCutoff, being careful to generate a valid value */
1038-
*MultiXactCutoff=nextMXID-multixact_freeze_min_age;
1039-
if (*MultiXactCutoff<FirstMultiXactId)
1040-
*MultiXactCutoff=FirstMultiXactId;
1049+
cutoffs->MultiXactCutoff=nextMXID-multixact_freeze_min_age;
1050+
if (cutoffs->MultiXactCutoff<FirstMultiXactId)
1051+
cutoffs->MultiXactCutoff=FirstMultiXactId;
10411052
/* MultiXactCutoff must always be <= OldestMxact */
1042-
if (MultiXactIdPrecedes(*OldestMxact,*MultiXactCutoff))
1043-
*MultiXactCutoff=*OldestMxact;
1044-
1045-
/*
1046-
* Done setting output parameters; check if OldestXmin or OldestMxact are
1047-
* held back to an unsafe degree in passing
1048-
*/
1049-
safeOldestXmin=nextXID-autovacuum_freeze_max_age;
1050-
if (!TransactionIdIsNormal(safeOldestXmin))
1051-
safeOldestXmin=FirstNormalTransactionId;
1052-
safeOldestMxact=nextMXID-effective_multixact_freeze_max_age;
1053-
if (safeOldestMxact<FirstMultiXactId)
1054-
safeOldestMxact=FirstMultiXactId;
1055-
if (TransactionIdPrecedes(*OldestXmin,safeOldestXmin))
1056-
ereport(WARNING,
1057-
(errmsg("cutoff for removing and freezing tuples is far in the past"),
1058-
errhint("Close open transactions soon to avoid wraparound problems.\n"
1059-
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1060-
if (MultiXactIdPrecedes(*OldestMxact,safeOldestMxact))
1061-
ereport(WARNING,
1062-
(errmsg("cutoff for freezing multixacts is far in the past"),
1063-
errhint("Close open transactions soon to avoid wraparound problems.\n"
1064-
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1053+
if (MultiXactIdPrecedes(cutoffs->OldestMxact,cutoffs->MultiXactCutoff))
1054+
cutoffs->MultiXactCutoff=cutoffs->OldestMxact;
10651055

10661056
/*
10671057
* Finally, figure out if caller needs to do an aggressive VACUUM or not.
@@ -1113,13 +1103,13 @@ vacuum_set_xid_limits(Relation rel, const VacuumParams *params,
11131103
* mechanism to determine if its table's relfrozenxid and relminmxid are now
11141104
* dangerously far in the past.
11151105
*
1116-
* Input parameters are the target relation's relfrozenxid and relminmxid.
1117-
*
11181106
* When we return true, VACUUM caller triggers the failsafe.
11191107
*/
11201108
bool
1121-
vacuum_xid_failsafe_check(TransactionIdrelfrozenxid,MultiXactIdrelminmxid)
1109+
vacuum_xid_failsafe_check(conststructVacuumCutoffs*cutoffs)
11221110
{
1111+
TransactionIdrelfrozenxid=cutoffs->relfrozenxid;
1112+
MultiXactIdrelminmxid=cutoffs->relminmxid;
11231113
TransactionIdxid_skip_limit;
11241114
MultiXactIdmulti_skip_limit;
11251115
intskip_index_vacuum;

‎src/include/access/heapam.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
typedefstructBulkInsertStateData*BulkInsertState;
4040
structTupleTableSlot;
41+
structVacuumCutoffs;
4142

4243
#defineMaxLockTupleModeLockTupleExclusive
4344

@@ -178,8 +179,7 @@ extern TM_Result heap_lock_tuple(Relation relation, HeapTuple tuple,
178179

179180
externvoidheap_inplace_update(Relationrelation,HeapTupletuple);
180181
externboolheap_prepare_freeze_tuple(HeapTupleHeadertuple,
181-
TransactionIdrelfrozenxid,TransactionIdrelminmxid,
182-
TransactionIdcutoff_xid,TransactionIdcutoff_multi,
182+
conststructVacuumCutoffs*cutoffs,
183183
HeapTupleFreeze*frz,bool*totally_frozen,
184184
TransactionId*relfrozenxid_out,
185185
MultiXactId*relminmxid_out);
@@ -188,9 +188,9 @@ extern void heap_freeze_execute_prepared(Relation rel, Buffer buffer,
188188
HeapTupleFreeze*tuples,intntuples);
189189
externboolheap_freeze_tuple(HeapTupleHeadertuple,
190190
TransactionIdrelfrozenxid,TransactionIdrelminmxid,
191-
TransactionIdcutoff_xid,TransactionIdcutoff_multi);
192-
externboolheap_tuple_would_freeze(HeapTupleHeadertuple,TransactionIdcutoff_xid,
193-
MultiXactIdcutoff_multi,
191+
TransactionIdFreezeLimit,TransactionIdMultiXactCutoff);
192+
externboolheap_tuple_would_freeze(HeapTupleHeadertuple,
193+
conststructVacuumCutoffs*cutoffs,
194194
TransactionId*relfrozenxid_out,
195195
MultiXactId*relminmxid_out);
196196
externboolheap_tuple_needs_eventual_freeze(HeapTupleHeadertuple);

‎src/include/access/tableam.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1634,7 +1634,7 @@ table_relation_copy_data(Relation rel, const RelFileLocator *newrlocator)
16341634
* in that index's order; if false and OldIndex is InvalidOid, no sorting is
16351635
* performed
16361636
* - OldIndex - see use_sort
1637-
* - OldestXmin - computed byvacuum_set_xid_limits(), even when
1637+
* - OldestXmin - computed byvacuum_get_cutoffs(), even when
16381638
* not needed for the relation's AM
16391639
* - *xid_cutoff - ditto
16401640
* - *multi_cutoff - ditto

‎src/include/commands/vacuum.h

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,45 @@ typedef struct VacuumParams
235235
intnworkers;
236236
}VacuumParams;
237237

238+
/*
239+
* VacuumCutoffs is immutable state that describes the cutoffs used by VACUUM.
240+
* Established at the beginning of each VACUUM operation.
241+
*/
242+
structVacuumCutoffs
243+
{
244+
/*
245+
* Existing pg_class fields at start of VACUUM
246+
*/
247+
TransactionIdrelfrozenxid;
248+
MultiXactIdrelminmxid;
249+
250+
/*
251+
* OldestXmin is the Xid below which tuples deleted by any xact (that
252+
* committed) should be considered DEAD, not just RECENTLY_DEAD.
253+
*
254+
* OldestMxact is the Mxid below which MultiXacts are definitely not seen
255+
* as visible by any running transaction.
256+
*
257+
* OldestXmin and OldestMxact are also the most recent values that can
258+
* ever be passed to vac_update_relstats() as frozenxid and minmulti
259+
* arguments at the end of VACUUM. These same values should be passed
260+
* when it turns out that VACUUM will leave no unfrozen XIDs/MXIDs behind
261+
* in the table.
262+
*/
263+
TransactionIdOldestXmin;
264+
MultiXactIdOldestMxact;
265+
266+
/*
267+
* FreezeLimit is the Xid below which all Xids are definitely frozen or
268+
* removed in pages VACUUM scans and cleanup locks.
269+
*
270+
* MultiXactCutoff is the value below which all MultiXactIds are
271+
* definitely removed from Xmax in pages VACUUM scans and cleanup locks.
272+
*/
273+
TransactionIdFreezeLimit;
274+
MultiXactIdMultiXactCutoff;
275+
};
276+
238277
/*
239278
* VacDeadItems stores TIDs whose index tuples are deleted by index vacuuming.
240279
*/
@@ -286,13 +325,9 @@ extern void vac_update_relstats(Relation relation,
286325
bool*frozenxid_updated,
287326
bool*minmulti_updated,
288327
boolin_outer_xact);
289-
externboolvacuum_set_xid_limits(Relationrel,constVacuumParams*params,
290-
TransactionId*OldestXmin,
291-
MultiXactId*OldestMxact,
292-
TransactionId*FreezeLimit,
293-
MultiXactId*MultiXactCutoff);
294-
externboolvacuum_xid_failsafe_check(TransactionIdrelfrozenxid,
295-
MultiXactIdrelminmxid);
328+
externboolvacuum_get_cutoffs(Relationrel,constVacuumParams*params,
329+
structVacuumCutoffs*cutoffs);
330+
externboolvacuum_xid_failsafe_check(conststructVacuumCutoffs*cutoffs);
296331
externvoidvac_update_datfrozenxid(void);
297332
externvoidvacuum_delay_point(void);
298333
externboolvacuum_is_permitted_for_relation(Oidrelid,Form_pg_classreltuple,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp