From 0b018fabaaba77e39539ce7eb71e34a90ceb0825 Mon Sep 17 00:00:00 2001 From: Peter Geoghegan Date: Sun, 3 Apr 2022 09:57:21 -0700 Subject: Set relfrozenxid to oldest extant XID seen by VACUUM. When VACUUM set relfrozenxid before now, it set it to whatever value was used to determine which tuples to freeze -- the FreezeLimit cutoff. This approach was very naive. The relfrozenxid invariant only requires that new relfrozenxid values be <= the oldest extant XID remaining in the table (at the point that the VACUUM operation ends), which in general might be much more recent than FreezeLimit. VACUUM now carefully tracks the oldest remaining XID/MultiXactId as it goes (the oldest remaining values _after_ lazy_scan_prune processing). The final values are set as the table's new relfrozenxid and new relminmxid in pg_class at the end of each VACUUM. The oldest XID might come from a tuple's xmin, xmax, or xvac fields. It might even come from one of the table's remaining MultiXacts. Final relfrozenxid values must still be >= FreezeLimit in an aggressive VACUUM (FreezeLimit still acts as a lower bound on the final value that aggressive VACUUM can set relfrozenxid to). Since standard VACUUMs still make no guarantees about advancing relfrozenxid, they might as well set relfrozenxid to a value from well before FreezeLimit when the opportunity presents itself. In general standard VACUUMs may now set relfrozenxid to any value > the original relfrozenxid and <= OldestXmin. Credit for the general idea of using the oldest extant XID to set pg_class.relfrozenxid at the end of VACUUM goes to Andres Freund. Author: Peter Geoghegan Reviewed-By: Andres Freund Reviewed-By: Robert Haas Discussion: https://postgr.es/m/CAH2-WzkymFbz6D_vL+jmqSn_5q1wsFvFrE+37yLgL_Rkfd6Gzg@mail.gmail.com --- doc/src/sgml/maintenance.sgml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'doc') diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml index 84fba9dcb10..2e09fee5aeb 100644 --- a/doc/src/sgml/maintenance.sgml +++ b/doc/src/sgml/maintenance.sgml @@ -586,11 +586,11 @@ statistics in the system tables pg_class and pg_database. In particular, the relfrozenxid column of a table's - pg_class row contains the freeze cutoff XID that was used - by the last aggressive VACUUM for that table. All rows - inserted by transactions with XIDs older than this cutoff XID are - guaranteed to have been frozen. Similarly, - the datfrozenxid column of a database's + pg_class row contains the oldest remaining unfrozen + XID at the end of the most recent VACUUM that successfully + advanced relfrozenxid (typically the most recent + aggressive VACUUM). Similarly, the + datfrozenxid column of a database's pg_database row is a lower bound on the unfrozen XIDs appearing in that database — it is just the minimum of the per-table relfrozenxid values within the database. @@ -638,7 +638,11 @@ SELECT datname, age(datfrozenxid) FROM pg_database; set age(relfrozenxid) to a value just a little more than the vacuum_freeze_min_age setting that was used (more by the number of transactions started since the - VACUUM started). If no relfrozenxid-advancing + VACUUM started). VACUUM + will set relfrozenxid to the oldest XID + that remains in the table, so it's possible that the final value + will be much more recent than strictly required. + If no relfrozenxid-advancing VACUUM is issued on the table until autovacuum_freeze_max_age is reached, an autovacuum will soon be forced for the table. -- cgit v1.2.3