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

Commitc3ffa73

Browse files
Derive freeze cutoff from nextXID, not OldestXmin.
Before now, the cutoffs that VACUUM used to determine which XIDs/MXIDsto freeze were determined at the start of each VACUUM by taking relatedcutoffs that represent which XIDs/MXIDs VACUUM should treat as stillrunning, and subtracting an XID/MXID age based value controlled by GUCslike vacuum_freeze_min_age. The FreezeLimit cutoff (XID freeze cutoff)was derived by subtracting an XID age value from OldestXmin, while theMultiXactCutoff cutoff (MXID freeze cutoff) was derived by subtractingan MXID age value from OldestMxact. This approach didn't match theapproach used nearby to determine whether this VACUUM operation shouldbe an aggressive VACUUM or not.VACUUM now uses the standard approach instead: it subtracts the sameage-based values from next XID/next MXID (rather than subtracting fromOldestXmin/OldestMxact). This approach is simpler and more uniform.Most of the time it will have only a negligible impact on how and whenVACUUM freezes. It will occasionally make VACUUM more robust in theevent of problems caused by long running transaction. These are caseswhere OldestXmin and OldestMxact are held back by so much that theyattain an age that is a significant fraction of the value of age-basedsettings like vacuum_freeze_min_age.There is no principled reason why freezing should be affected in any wayby the presence of a long-running transaction -- at least not before thepoint that the OldestXmin and OldestMxact limits used by each VACUUMoperation attain an age that makes it unsafe to freeze some of theXIDs/MXIDs whose age exceeds the value of the relevant age-basedsettings. The new approach should at least make freezing degrade moregracefully than before, even in the most extreme cases.Author: Peter Geoghegan <pg@bowt.ie>Reviewed-By: Nathan Bossart <nathandbossart@gmail.com>Reviewed-By: Matthias van de Meent <boekewurm+postgres@gmail.com>Discussion:https://postgr.es/m/CAH2-WzkOv5CEeyOO=c91XnT5WBR_0gii0Wn5UbZhJ=4TTykDYg@mail.gmail.com
1 parent483ac64 commitc3ffa73

File tree

3 files changed

+92
-112
lines changed

3 files changed

+92
-112
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,8 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
360360
*/
361361
aggressive=vacuum_set_xid_limits(rel,
362362
params->freeze_min_age,
363-
params->freeze_table_age,
364363
params->multixact_freeze_min_age,
364+
params->freeze_table_age,
365365
params->multixact_freeze_table_age,
366366
&OldestXmin,&OldestMxact,
367367
&FreezeLimit,&MultiXactCutoff);

‎src/backend/commands/vacuum.c

Lines changed: 89 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -956,24 +956,25 @@ get_all_vacuum_rels(int options)
956956
bool
957957
vacuum_set_xid_limits(Relationrel,
958958
intfreeze_min_age,
959-
intfreeze_table_age,
960959
intmultixact_freeze_min_age,
960+
intfreeze_table_age,
961961
intmultixact_freeze_table_age,
962962
TransactionId*oldestXmin,
963963
MultiXactId*oldestMxact,
964964
TransactionId*freezeLimit,
965965
MultiXactId*multiXactCutoff)
966966
{
967-
intfreezemin;
968-
intmxid_freezemin;
967+
TransactionIdnextXID,
968+
safeOldestXmin,
969+
aggressiveXIDCutoff;
970+
MultiXactIdnextMXID,
971+
safeOldestMxact,
972+
aggressiveMXIDCutoff;
969973
inteffective_multixact_freeze_max_age;
970-
TransactionIdlimit;
971-
TransactionIdsafeLimit;
972-
MultiXactIdmxactLimit;
973-
MultiXactIdsafeMxactLimit;
974-
intfreezetable;
975974

976975
/*
976+
* Acquire oldestXmin.
977+
*
977978
* We can always ignore processes running lazy vacuum. This is because we
978979
* use these values only for deciding which tuples we must keep in the
979980
* tables. Since lazy vacuum doesn't write its XID anywhere (usually no
@@ -1005,44 +1006,32 @@ vacuum_set_xid_limits(Relation rel,
10051006

10061007
Assert(TransactionIdIsNormal(*oldestXmin));
10071008

1009+
/* Acquire oldestMxact */
1010+
*oldestMxact=GetOldestMultiXactId();
1011+
Assert(MultiXactIdIsValid(*oldestMxact));
1012+
1013+
/* Acquire next XID/next MXID values used to apply age-based settings */
1014+
nextXID=ReadNextTransactionId();
1015+
nextMXID=ReadNextMultiXactId();
1016+
10081017
/*
10091018
* Determine the minimum freeze age to use: as specified by the caller, or
10101019
* vacuum_freeze_min_age, but in any case not more than half
10111020
* autovacuum_freeze_max_age, so that autovacuums to prevent XID
10121021
* wraparound won't occur too frequently.
10131022
*/
1014-
freezemin=freeze_min_age;
1015-
if (freezemin<0)
1016-
freezemin=vacuum_freeze_min_age;
1017-
freezemin=Min(freezemin,autovacuum_freeze_max_age /2);
1018-
Assert(freezemin >=0);
1023+
if (freeze_min_age<0)
1024+
freeze_min_age=vacuum_freeze_min_age;
1025+
freeze_min_age=Min(freeze_min_age,autovacuum_freeze_max_age /2);
1026+
Assert(freeze_min_age >=0);
10191027

1020-
/*
1021-
* Compute the cutoff XID, being careful not to generate a "permanent" XID
1022-
*/
1023-
limit=*oldestXmin-freezemin;
1024-
if (!TransactionIdIsNormal(limit))
1025-
limit=FirstNormalTransactionId;
1026-
1027-
/*
1028-
* If oldestXmin is very far back (in practice, more than
1029-
* autovacuum_freeze_max_age / 2 XIDs old), complain and force a minimum
1030-
* freeze age of zero.
1031-
*/
1032-
safeLimit=ReadNextTransactionId()-autovacuum_freeze_max_age;
1033-
if (!TransactionIdIsNormal(safeLimit))
1034-
safeLimit=FirstNormalTransactionId;
1035-
1036-
if (TransactionIdPrecedes(limit,safeLimit))
1037-
{
1038-
ereport(WARNING,
1039-
(errmsg("oldest xmin is far in the past"),
1040-
errhint("Close open transactions soon to avoid wraparound problems.\n"
1041-
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1042-
limit=*oldestXmin;
1043-
}
1044-
1045-
*freezeLimit=limit;
1028+
/* Compute freezeLimit, being careful to generate a normal XID */
1029+
*freezeLimit=nextXID-freeze_min_age;
1030+
if (!TransactionIdIsNormal(*freezeLimit))
1031+
*freezeLimit=FirstNormalTransactionId;
1032+
/* freezeLimit must always be <= oldestXmin */
1033+
if (TransactionIdPrecedes(*oldestXmin,*freezeLimit))
1034+
*freezeLimit=*oldestXmin;
10461035

10471036
/*
10481037
* Compute the multixact age for which freezing is urgent. This is
@@ -1057,93 +1046,83 @@ vacuum_set_xid_limits(Relation rel,
10571046
* than half effective_multixact_freeze_max_age, so that autovacuums to
10581047
* prevent MultiXact wraparound won't occur too frequently.
10591048
*/
1060-
mxid_freezemin=multixact_freeze_min_age;
1061-
if (mxid_freezemin<0)
1062-
mxid_freezemin=vacuum_multixact_freeze_min_age;
1063-
mxid_freezemin=Min(mxid_freezemin,
1064-
effective_multixact_freeze_max_age /2);
1065-
Assert(mxid_freezemin >=0);
1066-
1067-
/* Remember for caller */
1068-
*oldestMxact=GetOldestMultiXactId();
1069-
1070-
/* compute the cutoff multi, being careful to generate a valid value */
1071-
mxactLimit=*oldestMxact-mxid_freezemin;
1072-
if (mxactLimit<FirstMultiXactId)
1073-
mxactLimit=FirstMultiXactId;
1074-
1075-
safeMxactLimit=
1076-
ReadNextMultiXactId()-effective_multixact_freeze_max_age;
1077-
if (safeMxactLimit<FirstMultiXactId)
1078-
safeMxactLimit=FirstMultiXactId;
1079-
1080-
if (MultiXactIdPrecedes(mxactLimit,safeMxactLimit))
1081-
{
1049+
if (multixact_freeze_min_age<0)
1050+
multixact_freeze_min_age=vacuum_multixact_freeze_min_age;
1051+
multixact_freeze_min_age=Min(multixact_freeze_min_age,
1052+
effective_multixact_freeze_max_age /2);
1053+
Assert(multixact_freeze_min_age >=0);
1054+
1055+
/* Compute multiXactCutoff, being careful to generate a valid value */
1056+
*multiXactCutoff=nextMXID-multixact_freeze_min_age;
1057+
if (*multiXactCutoff<FirstMultiXactId)
1058+
*multiXactCutoff=FirstMultiXactId;
1059+
/* multiXactCutoff must always be <= oldestMxact */
1060+
if (MultiXactIdPrecedes(*oldestMxact,*multiXactCutoff))
1061+
*multiXactCutoff=*oldestMxact;
1062+
1063+
/*
1064+
* Done setting output parameters; check if oldestXmin or oldestMxact are
1065+
* held back to an unsafe degree in passing
1066+
*/
1067+
safeOldestXmin=nextXID-autovacuum_freeze_max_age;
1068+
if (!TransactionIdIsNormal(safeOldestXmin))
1069+
safeOldestXmin=FirstNormalTransactionId;
1070+
safeOldestMxact=nextMXID-effective_multixact_freeze_max_age;
1071+
if (safeOldestMxact<FirstMultiXactId)
1072+
safeOldestMxact=FirstMultiXactId;
1073+
if (TransactionIdPrecedes(*oldestXmin,safeOldestXmin))
10821074
ereport(WARNING,
1083-
(errmsg("oldest multixact is far in the past"),
1084-
errhint("Close open transactions with multixacts soon to avoid wraparound problems.")));
1085-
/* Use the safe limit, unless an older mxact is still running */
1086-
if (MultiXactIdPrecedes(*oldestMxact,safeMxactLimit))
1087-
mxactLimit=*oldestMxact;
1088-
else
1089-
mxactLimit=safeMxactLimit;
1090-
}
1091-
1092-
*multiXactCutoff=mxactLimit;
1075+
(errmsg("cutoff for removing and freezing tuples is far in the past"),
1076+
errhint("Close open transactions soon to avoid wraparound problems.\n"
1077+
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
1078+
if (MultiXactIdPrecedes(*oldestMxact,safeOldestMxact))
1079+
ereport(WARNING,
1080+
(errmsg("cutoff for freezing multixacts is far in the past"),
1081+
errhint("Close open transactions soon to avoid wraparound problems.\n"
1082+
"You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
10931083

10941084
/*
1095-
* Done setting output parameters; just need to figure out if caller needs
1096-
* to do an aggressive VACUUM or not.
1085+
* Finally, figure out if caller needs to do an aggressive VACUUM or not.
10971086
*
10981087
* Determine the table freeze age to use: as specified by the caller, or
1099-
* vacuum_freeze_table_age, but in any case not more than
1100-
* autovacuum_freeze_max_age * 0.95, so that if you have e.g nightly
1101-
* VACUUM schedule, the nightly VACUUM gets a chance to freeze tuples
1102-
* before anti-wraparound autovacuum is launched.
1103-
*/
1104-
freezetable=freeze_table_age;
1105-
if (freezetable<0)
1106-
freezetable=vacuum_freeze_table_age;
1107-
freezetable=Min(freezetable,autovacuum_freeze_max_age*0.95);
1108-
Assert(freezetable >=0);
1109-
1110-
/*
1111-
* Compute XID limit causing an aggressive vacuum, being careful not to
1112-
* generate a "permanent" XID
1113-
*/
1114-
limit=ReadNextTransactionId()-freezetable;
1115-
if (!TransactionIdIsNormal(limit))
1116-
limit=FirstNormalTransactionId;
1088+
* the value of the vacuum_freeze_table_age GUC, but in any case not more
1089+
* than autovacuum_freeze_max_age * 0.95, so that if you have e.g nightly
1090+
* VACUUM schedule, the nightly VACUUM gets a chance to freeze XIDs before
1091+
* anti-wraparound autovacuum is launched.
1092+
*/
1093+
if (freeze_table_age<0)
1094+
freeze_table_age=vacuum_freeze_table_age;
1095+
freeze_table_age=Min(freeze_table_age,autovacuum_freeze_max_age*0.95);
1096+
Assert(freeze_table_age >=0);
1097+
aggressiveXIDCutoff=nextXID-freeze_table_age;
1098+
if (!TransactionIdIsNormal(aggressiveXIDCutoff))
1099+
aggressiveXIDCutoff=FirstNormalTransactionId;
11171100
if (TransactionIdPrecedesOrEquals(rel->rd_rel->relfrozenxid,
1118-
limit))
1101+
aggressiveXIDCutoff))
11191102
return true;
11201103

11211104
/*
11221105
* Similar to the above, determine the table freeze age to use for
1123-
* multixacts: as specified by the caller, or
1124-
* vacuum_multixact_freeze_table_age, but in any case not more than
1125-
*autovacuum_multixact_freeze_table_age * 0.95, so that if you have e.g.
1106+
* multixacts: as specified by the caller, or the value of the
1107+
* vacuum_multixact_freeze_table_age GUC, but in any case not more than
1108+
*effective_multixact_freeze_max_age * 0.95, so that if you have e.g.
11261109
* nightly VACUUM schedule, the nightly VACUUM gets a chance to freeze
11271110
* multixacts before anti-wraparound autovacuum is launched.
11281111
*/
1129-
freezetable=multixact_freeze_table_age;
1130-
if (freezetable<0)
1131-
freezetable=vacuum_multixact_freeze_table_age;
1132-
freezetable=Min(freezetable,
1133-
effective_multixact_freeze_max_age*0.95);
1134-
Assert(freezetable >=0);
1135-
1136-
/*
1137-
* Compute MultiXact limit causing an aggressive vacuum, being careful to
1138-
* generate a valid MultiXact value
1139-
*/
1140-
mxactLimit=ReadNextMultiXactId()-freezetable;
1141-
if (mxactLimit<FirstMultiXactId)
1142-
mxactLimit=FirstMultiXactId;
1112+
if (multixact_freeze_table_age<0)
1113+
multixact_freeze_table_age=vacuum_multixact_freeze_table_age;
1114+
multixact_freeze_table_age=
1115+
Min(multixact_freeze_table_age,
1116+
effective_multixact_freeze_max_age*0.95);
1117+
Assert(multixact_freeze_table_age >=0);
1118+
aggressiveMXIDCutoff=nextMXID-multixact_freeze_table_age;
1119+
if (aggressiveMXIDCutoff<FirstMultiXactId)
1120+
aggressiveMXIDCutoff=FirstMultiXactId;
11431121
if (MultiXactIdPrecedesOrEquals(rel->rd_rel->relminmxid,
1144-
mxactLimit))
1122+
aggressiveMXIDCutoff))
11451123
return true;
11461124

1125+
/* Non-aggressive VACUUM */
11471126
return false;
11481127
}
11491128

‎src/include/commands/vacuum.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,9 @@ extern void vac_update_relstats(Relation relation,
287287
bool*minmulti_updated,
288288
boolin_outer_xact);
289289
externboolvacuum_set_xid_limits(Relationrel,
290-
intfreeze_min_age,intfreeze_table_age,
290+
intfreeze_min_age,
291291
intmultixact_freeze_min_age,
292+
intfreeze_table_age,
292293
intmultixact_freeze_table_age,
293294
TransactionId*oldestXmin,
294295
MultiXactId*oldestMxact,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp