<structfield>relminxid</structfield> is oldest. Do not use <literal>VACUUM FULL</literal>
in this scenario, because it requires an XID and will therefore fail, except in super-user
mode, where it will instead consume an XID and thus increase the risk of transaction ID
wraparound. Do not use <literal>VACUUM FREEZE</literal> either, because it will do
more than the minimum amount of work required to restore normal operation.</simpara>
</listitem>
<listitem>
<simpara>Once normal operation is restored, ensure that autovacuum is properly configured
in the target database in order to avoid future problems.</simpara>
</listitem>
</orderedlist>
</para>
<note>
<para>
In earlier versions, it was sometimes necessary to stop the postmaster and
<command>VACUUM</command> the database in a single-user mode. In typical scenarios, this
is no longer necessary, and should be avoided whenever possible, since it involves taking
the system down. It is also riskier, since it disables transaction ID wraparound safeguards
that are designed to prevent data loss. The only reason to use single-user mode in this
scenario is if you wish to <command>TRUNCATE</command> or <command>DROP</command> unneeded
tables to avoid needing to <command>VACUUM</command> them. The three-million-transaction
safety margin exists to let the administrator do this. See the
<xref linkend="app-postgres"/> reference page for details about using single-user mode.
</para>
</note>
<sect3 id="vacuum-for-multixact-wraparound">
<title>Multixacts and Wraparound</title>
<indexterm>
<primary>MultiXactId</primary>
</indexterm>
<indexterm>
<primary>wraparound</primary>
<secondary>of multixact IDs</secondary>
</indexterm>
<para>
<firstterm>Multixact IDs</firstterm> are used to support row locking by
multiple transactions. Since there is only limited space in a tuple
header to store lock information, that information is encoded as
a <quote>multiple transaction ID</quote>, or multixact ID for short,
whenever there is more than one transaction concurrently locking a
row. Information about which transaction IDs are included in any
particular multixact ID is stored separately in
the <filename>pg_multixact</filename> subdirectory, and only the multixact ID
appears in the <structfield>xmax</structfield> field in the tuple header.
Like transaction IDs, multixact IDs are implemented as a
32-bit counter and corresponding storage, all of which requires
careful aging management, storage cleanup, and wraparound handling.
There is a separate storage area which holds the list of members in
each multixact, which also uses a 32-bit counter and which must also
be managed.
</para>
<para>
Whenever <command>VACUUM</command> scans any part of a table, it will replace
any multixact ID it encounters which is older than
<xref linkend="guc-vacuum-multixact-freeze-min-age"/>
by a different value, which can be the zero value, a single
transaction ID, or a newer multixact ID. For each table,
<structname>pg_class</structname>.<structfield>relminmxid</structfield> stores the oldest
possible multixact ID still appearing in any tuple of that table.
If this value is older than
<xref linkend="guc-vacuum-multixact-freeze-table-age"/>, an aggressive
vacuum is forced. As discussed in the previous section, an aggressive
vacuum means that only those pages which are known to be all-frozen will
be skipped. <function>mxid_age()</function> can be used on
<structname>pg_class</structname>.<structfield>relminmxid</structfield> to find its age.
</para>
<para>
Aggressive <command>VACUUM</command>s, regardless of what causes
them, are <emphasis>guaranteed</emphasis> to be able to advance
the table's