@@ -956,24 +956,25 @@ get_all_vacuum_rels(int options)
956
956
bool
957
957
vacuum_set_xid_limits (Relation rel ,
958
958
int freeze_min_age ,
959
- int freeze_table_age ,
960
959
int multixact_freeze_min_age ,
960
+ int freeze_table_age ,
961
961
int multixact_freeze_table_age ,
962
962
TransactionId * oldestXmin ,
963
963
MultiXactId * oldestMxact ,
964
964
TransactionId * freezeLimit ,
965
965
MultiXactId * multiXactCutoff )
966
966
{
967
- int freezemin ;
968
- int mxid_freezemin ;
967
+ TransactionId nextXID ,
968
+ safeOldestXmin ,
969
+ aggressiveXIDCutoff ;
970
+ MultiXactId nextMXID ,
971
+ safeOldestMxact ,
972
+ aggressiveMXIDCutoff ;
969
973
int effective_multixact_freeze_max_age ;
970
- TransactionId limit ;
971
- TransactionId safeLimit ;
972
- MultiXactId mxactLimit ;
973
- MultiXactId safeMxactLimit ;
974
- int freezetable ;
975
974
976
975
/*
976
+ * Acquire oldestXmin.
977
+ *
977
978
* We can always ignore processes running lazy vacuum. This is because we
978
979
* use these values only for deciding which tuples we must keep in the
979
980
* tables. Since lazy vacuum doesn't write its XID anywhere (usually no
@@ -1005,44 +1006,32 @@ vacuum_set_xid_limits(Relation rel,
1005
1006
1006
1007
Assert (TransactionIdIsNormal (* oldestXmin ));
1007
1008
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
+
1008
1017
/*
1009
1018
* Determine the minimum freeze age to use: as specified by the caller, or
1010
1019
* vacuum_freeze_min_age, but in any case not more than half
1011
1020
* autovacuum_freeze_max_age, so that autovacuums to prevent XID
1012
1021
* wraparound won't occur too frequently.
1013
1022
*/
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 );
1019
1027
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 ;
1046
1035
1047
1036
/*
1048
1037
* Compute the multixact age for which freezing is urgent. This is
@@ -1057,93 +1046,83 @@ vacuum_set_xid_limits(Relation rel,
1057
1046
* than half effective_multixact_freeze_max_age, so that autovacuums to
1058
1047
* prevent MultiXact wraparound won't occur too frequently.
1059
1048
*/
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 ))
1082
1074
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." )));
1093
1083
1094
1084
/*
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.
1097
1086
*
1098
1087
* 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 ;
1117
1100
if (TransactionIdPrecedesOrEquals (rel -> rd_rel -> relfrozenxid ,
1118
- limit ))
1101
+ aggressiveXIDCutoff ))
1119
1102
return true;
1120
1103
1121
1104
/*
1122
1105
* 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.
1126
1109
* nightly VACUUM schedule, the nightly VACUUM gets a chance to freeze
1127
1110
* multixacts before anti-wraparound autovacuum is launched.
1128
1111
*/
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 ;
1143
1121
if (MultiXactIdPrecedesOrEquals (rel -> rd_rel -> relminmxid ,
1144
- mxactLimit ))
1122
+ aggressiveMXIDCutoff ))
1145
1123
return true;
1146
1124
1125
+ /* Non-aggressive VACUUM */
1147
1126
return false;
1148
1127
}
1149
1128
0 commit comments