= 2ndQuadrant AntiFreeze

This extension is an alternative to emergency anti-wraparound vacuums,
allowing tables to be scanned much more quickly than normal VACUUM.
It scans each block to see if any tuples need freezing. If so, it
cleans the whole heap block, meaning that it reduces dead tuples to
just their line pointer, equivalent to Phase1 of VACUUM.  So it does
less work on the table itself, and does not need to modify indexes.
Regular VACUUMs are still required to cleanup indexes.

The extension currently supports PostgreSQL 9.2, 9.3, 9.4, and 9.5.

Usage
-----

The extension provides two functions:

 - `pg_antifreeze(oid)`
 - `pg_update_datfrozenxid()`

`pg_antifreeze` is the main function, doing all the hard work on tables. The
tables that need to be frozen may be selected from `pg_class` e.g. like this:

    SELECT relname FROM pg_class
        WHERE relkind='r' AND relminmxid::text < '123984';

    SELECT relname FROM pg_class
        WHERE relkind='r' AND age(t.relfrozenxid) > 12374872;

`pg_update_datfrozenxid` advances the min XID fields in `pg_database` catalog
(`datfrozenxid` and `datminmxid`) based on `pg_class` contents. This allows
the database to remove unnecessary multixacts, for example. The function is
fairly cheap as it does not perform any cleanup on its own, so you may call it
once all the tables are processed or even after each table. If you don't call
it the fields will be updated by autovacuum later.

Run pg_antifreeze(regclass) on each candidate table based on a query of
pg_class to find tables with the lowest pg_class.relminmxid and
pg_class.relfrozenxid.

Transactions
------------

`pg_antifreeze` has the same restriction as `VACUUM` - each invocation
must run in a separate top-level transaction, i.e. must NOT be executed
from inside a function or a `DO` block.

The function takes a `SHARE UPDATE EXCLUSIVE` lock on the relation, the
same as vacuum itself. See

http://www.postgresql.org/docs/current/static/explicit-locking.html

Cost-Based Throttling
---------------------

The extension respects cost-based throttling, using the same GUC options
as VACUUM. Make sure you have set those options accordingly if you want
to limit the freeze or run at full speed.

Freeze Limits
-------------

Multixacts are frozen according to the vacuum_multixact_freeze_min_age
parameter: any Multixact older than that value is frozen.  The table's
pg_class.relminmxid value is set to the corresponding multixact at the
time the run starts.

Regular Xids are frozen according to a custom parameter
antifreeze.freeze_xid_trigger_age.  Any page that contains at least one
tuple older than that value is frozen.  In pages that are frozen, all
tuples older than the oldest transaction that was running when the
oldest currently-running transaction started, are frozen.  Dead (but not
recently dead) tuples are removed just as for HOT pruning: any index
entries are kept, and heap line pointers are kept also.  A later regular
vacuum run is expected to clean up the pages more fully.

Currently the freeze thresholds are very conservative, but this could be
changed relatively easily to freeze more aggressively.

Caveats
-------

There is one edge case in which freezing a multixact creates a new
multixact.  This happens when a very old multixact is still seen as
"running" (because one of the member transactions is still running) but
is older than the multixact cutoff point.  In order to be able to freeze
the tuple in that case, what we do is create a new multixact with the
surviving members of the old one. Handling this would probably require
the freeze code to do one scan to freeze all multixacts up to the first
one seen as still-running to make room, then scan again. It doesn't do
that yet.

Copyright 2ndQuadrant 2016
Licensed for use on PostgreSQL servers covered by 2ndQuadrant Product Support
