mirror of
https://github.com/postgres/postgres.git
synced 2025-05-03 22:24:49 +03:00
Avoid catalog lookups in RelationAllowsEarlyPruning().
RelationAllowsEarlyPruning() performed a catalog scan, but is used in two contexts where that was a bad idea: 1. In heap_page_prune_opt(), which runs very frequently in some large scans. This caused major performance problems in a field report that was easy to reproduce. 2. In TestForOldSnapshot(), which runs while we hold a buffer content lock. It's not clear if this was guaranteed to be free of buffer deadlock risk. The check was introduced in commit 2cc41acd8 and defended against a real problem: 9.6's hash indexes have no page LSN and so we can't allow early pruning (ie the snapshot-too-old feature). We can remove the check from all later releases though: hash indexes are now logged, and there is no way to create UNLOGGED indexes on regular logged tables. If a future release allows such a combination, it might need to put a similar check in place, but it'll need some more thought. Back-patch to 10. Author: Thomas Munro Reviewed-by: Tom Lane, who spotted the second problem Discussion: https://postgr.es/m/CA%2BhUKGKT8oTkp5jw_U4p0S-7UG9zsvtw_M47Y285bER6a2gD%2Bg%40mail.gmail.com Discussion: https://postgr.es/m/CAA4eK1%2BWy%2BN4eE5zPm765h68LrkWc3Biu_8rzzi%2BOYX4j%2BiHRw%40mail.gmail.com
This commit is contained in:
parent
80d0e5ba3f
commit
720b59b55b
42
src/backend/utils/cache/relcache.c
vendored
42
src/backend/utils/cache/relcache.c
vendored
@ -5913,48 +5913,6 @@ RelationIdIsInInitFile(Oid relationId)
|
||||
return RelationSupportsSysCache(relationId);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tells whether any index for the relation is unlogged.
|
||||
*
|
||||
* Note: There doesn't seem to be any way to have an unlogged index attached
|
||||
* to a permanent table, 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)
|
||||
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
|
||||
|
@ -605,6 +605,5 @@ typedef struct ViewOptions
|
||||
/* routines in utils/cache/relcache.c */
|
||||
extern void RelationIncrementReferenceCount(Relation rel);
|
||||
extern void RelationDecrementReferenceCount(Relation rel);
|
||||
extern bool RelationHasUnloggedIndex(Relation rel);
|
||||
|
||||
#endif /* REL_H */
|
||||
|
@ -40,7 +40,6 @@
|
||||
RelationNeedsWAL(rel) \
|
||||
&& !IsCatalogRelation(rel) \
|
||||
&& !RelationIsAccessibleInLogicalDecoding(rel) \
|
||||
&& !RelationHasUnloggedIndex(rel) \
|
||||
)
|
||||
|
||||
#define EarlyPruningEnabled(rel) (old_snapshot_threshold >= 0 && RelationAllowsEarlyPruning(rel))
|
||||
|
Loading…
x
Reference in New Issue
Block a user