1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-07 00:36:50 +03:00

Fix hash index vs "snapshot too old" problemms

Hash indexes are not WAL-logged, and so do not maintain the LSN of
index pages.  Since the "snapshot too old" feature counts on
detecting error conditions using the LSN of a table and all indexes
on it, this makes it impossible to safely do early vacuuming on any
table with a hash index, so add this to the tests for whether the
xid used to vacuum a table can be adjusted based on
old_snapshot_threshold.

While at it, add a paragraph to the docs for old_snapshot_threshold
which specifically mentions this and other aspects of the feature
which may otherwise surprise users.

Problem reported and patch reviewed by Amit Kapila
This commit is contained in:
Kevin Grittner
2016-05-06 07:47:12 -05:00
parent 9b66aa006f
commit 2cc41acd8f
6 changed files with 62 additions and 6 deletions

View File

@ -5312,6 +5312,52 @@ RelationIdIsInInitFile(Oid relationId)
return RelationSupportsSysCache(relationId);
}
/*
* Tells whether any index for the relation is unlogged.
*
* Any index using the hash AM is implicitly unlogged.
*
* Note: There doesn't seem to be any way to have an unlogged index attached
* to a permanent table except to create a hash index, but it seems best to
* keep this general so that it returns sensible results even when they seem
* obvious (like for an unlogged table) and to handle possible future unlogged
* indexes on permanent tables.
*/
bool
RelationHasUnloggedIndex(Relation rel)
{
List *indexoidlist;
ListCell *indexoidscan;
bool result = false;
indexoidlist = RelationGetIndexList(rel);
foreach(indexoidscan, indexoidlist)
{
Oid indexoid = lfirst_oid(indexoidscan);
HeapTuple tp;
Form_pg_class reltup;
tp = SearchSysCache1(RELOID, ObjectIdGetDatum(indexoid));
if (!HeapTupleIsValid(tp))
elog(ERROR, "cache lookup failed for relation %u", indexoid);
reltup = (Form_pg_class) GETSTRUCT(tp);
if (reltup->relpersistence == RELPERSISTENCE_UNLOGGED
|| reltup->relam == HASH_AM_OID)
result = true;
ReleaseSysCache(tp);
if (result == true)
break;
}
list_free(indexoidlist);
return result;
}
/*
* Invalidate (remove) the init file during commit of a transaction that
* changed one or more of the relation cache entries that are kept in the