Kevin Grittner <kgri...@gmail.com> writes: > It occurred to me that it would make sense to allow these settings > to be attached to a database or table (though *not* a role). I'll > look at that when I get back if you don't get to it first.
Attached is a draft patch (no docs or tests) on top of the previous one, adding reloptions for the per-relation and per-page thresholds. That made me realise that the corresponding GUCs don't need to be PGC_SIGHUP, but could be PGC_SUSET or PGC_USERSET. I'll adjust the original patch if you agree. I have not got around around to adding per-database versions of the setting, but could have a stab at that. -- - Twitter seems more influential [than blogs] in the 'gets reported in the mainstream press' sense at least. - Matt McLeod - That'd be because the content of a tweet is easier to condense down to a mainstream media article. - Calle Dybedahl
>From e2ae108ca8212790604ef7e54f278e41ca460ffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dagfinn=20Ilmari=20Manns=C3=A5ker?= <ilm...@ilmari.org> Date: Wed, 25 Jan 2017 00:13:53 +0000 Subject: [PATCH 2/2] Add max_pred_locks_per_{relation,page} reloptions --- src/backend/access/common/reloptions.c | 24 +++++++++++++++++++++- src/backend/storage/lmgr/predicate.c | 37 +++++++++++++++++++++++----------- src/bin/psql/tab-complete.c | 2 ++ src/include/utils/rel.h | 21 +++++++++++++++++++ 4 files changed, 71 insertions(+), 13 deletions(-) diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index 42b4ea410f..ab8977a218 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -284,6 +284,24 @@ static relopt_int intRelOpts[] = }, -1, 0, 1024 }, + { + { + "max_pred_locks_per_relation", + "Maximum number of pages or rows that can be predicate-locked before locking the whole relation.", + RELOPT_KIND_HEAP, + AccessExclusiveLock, + }, + -1, 0, INT_MAX + }, + { + { + "max_pred_locks_per_page", + "Maximum number of rows on a single page that can be predicate-locked before locking the whole page.", + RELOPT_KIND_HEAP, + AccessExclusiveLock, + }, + -1, 0, INT_MAX + }, /* list terminator */ {{NULL}} @@ -1310,7 +1328,11 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind) {"user_catalog_table", RELOPT_TYPE_BOOL, offsetof(StdRdOptions, user_catalog_table)}, {"parallel_workers", RELOPT_TYPE_INT, - offsetof(StdRdOptions, parallel_workers)} + offsetof(StdRdOptions, parallel_workers)}, + {"max_pred_locks_per_relation", RELOPT_TYPE_INT, + offsetof(StdRdOptions, max_predicate_locks_per_relation)}, + {"max_pred_locks_per_page", RELOPT_TYPE_INT, + offsetof(StdRdOptions, max_predicate_locks_per_page)} }; options = parseRelOptions(reloptions, validate, kind, &numoptions); diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index ac927f2c3a..9b767d7e04 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -443,8 +443,9 @@ static void RestoreScratchTarget(bool lockheld); static void RemoveTargetIfNoLongerUsed(PREDICATELOCKTARGET *target, uint32 targettaghash); static void DeleteChildTargetLocks(const PREDICATELOCKTARGETTAG *newtargettag); -static int MaxPredicateChildLocks(const PREDICATELOCKTARGETTAG *tag); -static bool CheckAndPromotePredicateLockRequest(const PREDICATELOCKTARGETTAG *reqtag); +static int MaxPredicateChildLocks(const PREDICATELOCKTARGETTAG *tag, Relation relation); +static bool CheckAndPromotePredicateLockRequest(const PREDICATELOCKTARGETTAG *reqtag, + Relation relation); static void DecrementParentLocks(const PREDICATELOCKTARGETTAG *targettag); static void CreatePredicateLock(const PREDICATELOCKTARGETTAG *targettag, uint32 targettaghash, @@ -453,7 +454,8 @@ static void DeleteLockTarget(PREDICATELOCKTARGET *target, uint32 targettaghash); static bool TransferPredicateLocksToNewTarget(PREDICATELOCKTARGETTAG oldtargettag, PREDICATELOCKTARGETTAG newtargettag, bool removeOld); -static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag); +static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag, + Relation relation); static void DropAllPredicateLocksFromTable(Relation relation, bool transfer); static void SetNewSxactGlobalXmin(void); @@ -2138,17 +2140,27 @@ DeleteChildTargetLocks(const PREDICATELOCKTARGETTAG *newtargettag) * entirely arbitrarily (and without benchmarking). */ static int -MaxPredicateChildLocks(const PREDICATELOCKTARGETTAG *tag) +MaxPredicateChildLocks(const PREDICATELOCKTARGETTAG *tag, Relation relation) { switch (GET_PREDICATELOCKTARGETTAG_TYPE(*tag)) { case PREDLOCKTAG_RELATION: + { + int rel_max_pred_locks = RelationGetMaxPredicateLocksPerRelation(relation, -1); + if (rel_max_pred_locks != -1) + return rel_max_pred_locks; return max_predicate_locks_per_relation < 0 ? max_predicate_locks_per_xact / -max_predicate_locks_per_relation : max_predicate_locks_per_relation; + } case PREDLOCKTAG_PAGE: + { + int rel_max_pred_locks_per_page = RelationGetMaxPredicateLocksPerPage(relation, -1); + if (rel_max_pred_locks_per_page != -1) + return rel_max_pred_locks_per_page; return max_predicate_locks_per_page; + } case PREDLOCKTAG_TUPLE: @@ -2174,7 +2186,8 @@ MaxPredicateChildLocks(const PREDICATELOCKTARGETTAG *tag) * Returns true if a parent lock was acquired and false otherwise. */ static bool -CheckAndPromotePredicateLockRequest(const PREDICATELOCKTARGETTAG *reqtag) +CheckAndPromotePredicateLockRequest(const PREDICATELOCKTARGETTAG *reqtag, + Relation relation) { PREDICATELOCKTARGETTAG targettag, nexttag, @@ -2204,7 +2217,7 @@ CheckAndPromotePredicateLockRequest(const PREDICATELOCKTARGETTAG *reqtag) parentlock->childLocks++; if (parentlock->childLocks > - MaxPredicateChildLocks(&targettag)) + MaxPredicateChildLocks(&targettag, relation)) { /* * We should promote to this parent lock. Continue to check its @@ -2220,7 +2233,7 @@ CheckAndPromotePredicateLockRequest(const PREDICATELOCKTARGETTAG *reqtag) if (promote) { /* acquire coarsest ancestor eligible for promotion */ - PredicateLockAcquire(&promotiontag); + PredicateLockAcquire(&promotiontag, relation); return true; } else @@ -2362,7 +2375,7 @@ CreatePredicateLock(const PREDICATELOCKTARGETTAG *targettag, * any finer-grained locks covered by the new one. */ static void -PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag) +PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag, Relation relation) { uint32 targettaghash; bool found; @@ -2395,7 +2408,7 @@ PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag) * coarser granularity, or whether there are finer-granularity locks to * clean up. */ - if (CheckAndPromotePredicateLockRequest(targettag)) + if (CheckAndPromotePredicateLockRequest(targettag, relation)) { /* * Lock request was promoted to a coarser-granularity lock, and that @@ -2431,7 +2444,7 @@ PredicateLockRelation(Relation relation, Snapshot snapshot) SET_PREDICATELOCKTARGETTAG_RELATION(tag, relation->rd_node.dbNode, relation->rd_id); - PredicateLockAcquire(&tag); + PredicateLockAcquire(&tag, relation); } /* @@ -2455,7 +2468,7 @@ PredicateLockPage(Relation relation, BlockNumber blkno, Snapshot snapshot) relation->rd_node.dbNode, relation->rd_id, blkno); - PredicateLockAcquire(&tag); + PredicateLockAcquire(&tag, relation); } /* @@ -2518,7 +2531,7 @@ PredicateLockTuple(Relation relation, HeapTuple tuple, Snapshot snapshot) relation->rd_id, ItemPointerGetBlockNumber(tid), ItemPointerGetOffsetNumber(tid)); - PredicateLockAcquire(&tag); + PredicateLockAcquire(&tag, relation); } diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index ddad71a10f..ca75de7df6 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -1919,6 +1919,8 @@ psql_completion(const char *text, int start, int end) "autovacuum_vacuum_threshold", "fillfactor", "parallel_workers", + "max_pred_locks_per_relation", + "max_pred_locks_per_page", "log_autovacuum_min_duration", "toast.autovacuum_enabled", "toast.autovacuum_freeze_max_age", diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index a617a7cf56..0e5722f6ed 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -277,6 +277,8 @@ typedef struct StdRdOptions bool user_catalog_table; /* use as an additional catalog * relation */ int parallel_workers; /* max number of parallel workers */ + int max_predicate_locks_per_relation; /* max number of predicate locks */ + int max_predicate_locks_per_page; /* max number of predicate locks per page */ } StdRdOptions; #define HEAP_MIN_FILLFACTOR 10 @@ -325,6 +327,25 @@ typedef struct StdRdOptions ((StdRdOptions *) (relation)->rd_options)->parallel_workers : (defaultpw)) +/* + * RelationGetMaxPredicateLocksPerRelation + * Returns the relation's max_predicate_locks_per_relation reloption setting. + * Note multiple eval of argument! + */ +#define RelationGetMaxPredicateLocksPerRelation(relation, defaultmpl) \ + ((relation)->rd_options ? \ + ((StdRdOptions *) (relation)->rd_options)->max_predicate_locks_per_relation : (defaultmpl)) + +/* + * RelationGetMaxPredicateLocksPerPage + * Returns the relation's max_predicate_locks_per_page reloption setting. + * Note multiple eval of argument! + */ +#define RelationGetMaxPredicateLocksPerPage(relation, defaultmplpp) \ + ((relation)->rd_options ? \ + ((StdRdOptions *) (relation)->rd_options)->max_predicate_locks_per_page : (defaultmplpp)) + + /* * ViewOptions * Contents of rd_options for views -- 2.11.0
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers