Hi,
As Robert previously complained a database wide VACUUM FULL now (as of
3cff1879f8d03) reliably increases the relfrozenxid for all tables but
pg_class itself. That's a bit sad because it means doing a VACUUM FULL
won't help in a anti-wraparound scenario.
The reason for that is explained by the following comment:
/*
* Update the tuples in pg_class --- unless the target relation of the
* swap is pg_class itself. In that case, there is zero point in making
* changes because we'd be updating the old data that we're about to
throw
* away. Because the real work being done here for a mapped relation is
* just to change the relation map settings, it's all right to not
update
* the pg_class rows in this case.
*/
I think the easiest fix for that is to update pg_class' relfrozenxid in
finish_heap_swap() after the indexes have been rebuilt, that's just a
couple of lines. There's more complex solutions that'd avoid the need
for that special case, but I it's sufficient. A patch doing that is
attached.
Note that VACUUM FULL will still require more xids than a plain VACUUM,
but it scales linearly with the number of relations, so I have a hard
time seing that as problematic.
Greetings,
Andres Freund
--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training Services
From cc8943822e18f283af01c1f14489f7bd9a2abede Mon Sep 17 00:00:00 2001
From: Andres Freund and...@anarazel.de
Date: Thu, 27 Feb 2014 19:00:11 +0100
Subject: [PATCH] Increase relfrozenxid even when doing a VACUUM FULL on
pg_class.
Previously VACUUM FULL (and CLUSTER) didn't update pg_class's own
relfrozenxid because the place doing so only has convenient (as in
indexed) access to the old heap, not to the new rebuilt heap. Fix that
by adding a special case updating pg_class's relfrozenxid after the
indexes have been rebuilt.
That's useful because now a database VACUUM FULL reliably increases
the database's datfrozenxid (and datminmxid, although that's often
less critical).
---
src/backend/commands/cluster.c | 37 -
1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 8b18e4a..c478ba5 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -1269,7 +1269,8 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
* changes because we'd be updating the old data that we're about to throw
* away. Because the real work being done here for a mapped relation is
* just to change the relation map settings, it's all right to not update
- * the pg_class rows in this case.
+ * the pg_class rows in this case. The most important changes will instead
+ * performed later, in finish_heap_swap() itself.
*/
if (!target_is_pg_class)
{
@@ -1504,6 +1505,40 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
reindex_flags |= REINDEX_REL_CHECK_CONSTRAINTS;
reindex_relation(OIDOldHeap, reindex_flags);
+ /*
+ * If the relation being rebuild is pg_class, swap_relation_files()
+ * couldn't update pg_class's own pg_class entry (check comments in
+ * swap_relation_files()), thus relfrozenxid was not updated. That's
+ * annoying because a potential reason for doing a VACUUM FULL is a
+ * imminent or actual anti-wraparound shutdown. So, now that we can
+ * access the new relation using it's indices, update
+ * relfrozenxid. pg_class doesn't have a toast relation, so we don't need
+ * to update the corresponding toast relation. Not that there's little
+ * point moving all relfrozenxid updates here since swap_relation_files()
+ * needs to write to pg_class for non-mapped relations anyway.
+ */
+ if (OIDOldHeap == RelationRelationId)
+ {
+ Relation relRelation;
+ HeapTuple reltup;
+ Form_pg_class relform;
+
+ relRelation = heap_open(RelationRelationId, RowExclusiveLock);
+
+ reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(OIDOldHeap));
+ if (!HeapTupleIsValid(reltup))
+ elog(ERROR, cache lookup failed for relation %u, OIDOldHeap);
+ relform = (Form_pg_class) GETSTRUCT(reltup);
+
+ relform-relfrozenxid = frozenXid;
+ relform-relminmxid = cutoffMulti;
+
+ simple_heap_update(relRelation, reltup-t_self, reltup);
+ CatalogUpdateIndexes(relRelation, reltup);
+
+ heap_close(relRelation, RowExclusiveLock);
+ }
+
/* Destroy new heap with old filenode */
object.classId = RelationRelationId;
object.objectId = OIDNewHeap;
--
1.8.3.251.g1462b67
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers