aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/lmgr/predicate.c48
-rw-r--r--src/backend/utils/misc/guc.c22
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample4
-rw-r--r--src/include/storage/predicate.h2
4 files changed, 59 insertions, 17 deletions
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index 7aa719d6123..10bac71e94b 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -352,8 +352,15 @@ static OldSerXidControl oldSerXidControl;
static SERIALIZABLEXACT *OldCommittedSxact;
-/* This configuration variable is used to set the predicate lock table size */
+/*
+ * These configuration variables are used to set the predicate lock table size
+ * and to control promotion of predicate locks to coarser granularity in an
+ * attempt to degrade performance (mostly as false positive serialization
+ * failure) gracefully in the face of memory pressurel
+ */
int max_predicate_locks_per_xact; /* set by guc.c */
+int max_predicate_locks_per_relation; /* set by guc.c */
+int max_predicate_locks_per_page; /* set by guc.c */
/*
* This provides a list of objects in order to track transactions
@@ -437,7 +444,7 @@ static void RestoreScratchTarget(bool lockheld);
static void RemoveTargetIfNoLongerUsed(PREDICATELOCKTARGET *target,
uint32 targettaghash);
static void DeleteChildTargetLocks(const PREDICATELOCKTARGETTAG *newtargettag);
-static int PredicateLockPromotionThreshold(const PREDICATELOCKTARGETTAG *tag);
+static int MaxPredicateChildLocks(const PREDICATELOCKTARGETTAG *tag);
static bool CheckAndPromotePredicateLockRequest(const PREDICATELOCKTARGETTAG *reqtag);
static void DecrementParentLocks(const PREDICATELOCKTARGETTAG *targettag);
static void CreatePredicateLock(const PREDICATELOCKTARGETTAG *targettag,
@@ -2118,28 +2125,35 @@ DeleteChildTargetLocks(const PREDICATELOCKTARGETTAG *newtargettag)
}
/*
- * Returns the promotion threshold for a given predicate lock
- * target. This is the number of descendant locks required to promote
- * to the specified tag. Note that the threshold includes non-direct
- * descendants, e.g. both tuples and pages for a relation lock.
+ * Returns the promotion limit for a given predicate lock target. This is the
+ * max number of descendant locks allowed before promoting to the specified
+ * tag. Note that the limit includes non-direct descendants (e.g., both tuples
+ * and pages for a relation lock).
+ *
+ * Currently the default limit is 2 for a page lock, and half of the value of
+ * max_pred_locks_per_transaction - 1 for a relation lock, to match behavior
+ * of earlier releases when upgrading.
*
- * TODO SSI: We should do something more intelligent about what the
- * thresholds are, either making it proportional to the number of
- * tuples in a page & pages in a relation, or at least making it a
- * GUC. Currently the threshold is 3 for a page lock, and
- * max_pred_locks_per_transaction/2 for a relation lock, chosen
- * entirely arbitrarily (and without benchmarking).
+ * TODO SSI: We should probably add additional GUCs to allow a maximum ratio
+ * of page and tuple locks based on the pages in a relation, and the maximum
+ * ratio of tuple locks to tuples in a page. This would provide more
+ * generally "balanced" allocation of locks to where they are most useful,
+ * while still allowing the absolute numbers to prevent one relation from
+ * tying up all predicate lock resources.
*/
static int
-PredicateLockPromotionThreshold(const PREDICATELOCKTARGETTAG *tag)
+MaxPredicateChildLocks(const PREDICATELOCKTARGETTAG *tag)
{
switch (GET_PREDICATELOCKTARGETTAG_TYPE(*tag))
{
case PREDLOCKTAG_RELATION:
- return max_predicate_locks_per_xact / 2;
+ return max_predicate_locks_per_relation < 0
+ ? (max_predicate_locks_per_xact
+ / (-max_predicate_locks_per_relation)) - 1
+ : max_predicate_locks_per_relation;
case PREDLOCKTAG_PAGE:
- return 3;
+ return max_predicate_locks_per_page;
case PREDLOCKTAG_TUPLE:
@@ -2194,8 +2208,8 @@ CheckAndPromotePredicateLockRequest(const PREDICATELOCKTARGETTAG *reqtag)
else
parentlock->childLocks++;
- if (parentlock->childLocks >=
- PredicateLockPromotionThreshold(&targettag))
+ if (parentlock->childLocks >
+ MaxPredicateChildLocks(&targettag))
{
/*
* We should promote to this parent lock. Continue to check its
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index a57b175b2d3..19d258d0336 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -2200,6 +2200,28 @@ static struct config_int ConfigureNamesInt[] =
},
{
+ {"max_pred_locks_per_relation", PGC_SIGHUP, LOCK_MANAGEMENT,
+ gettext_noop("Sets the maximum number of predicate-locked pages and tuples per relation."),
+ gettext_noop("If more than this total of pages and tuples in the same relation are locked "
+ "by a connection, those locks are replaced by a relation level lock.")
+ },
+ &max_predicate_locks_per_relation,
+ -2, INT_MIN, INT_MAX,
+ NULL, NULL, NULL
+ },
+
+ {
+ {"max_pred_locks_per_page", PGC_SIGHUP, LOCK_MANAGEMENT,
+ gettext_noop("Sets the maximum number of predicate-locked tuples per page."),
+ gettext_noop("If more than this number of tuples on the same page are locked "
+ "by a connection, those locks are replaced by a page level lock.")
+ },
+ &max_predicate_locks_per_page,
+ 2, 0, INT_MAX,
+ NULL, NULL, NULL
+ },
+
+ {
{"authentication_timeout", PGC_SIGHUP, CONN_AUTH_SECURITY,
gettext_noop("Sets the maximum allowed time to complete client authentication."),
NULL,
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 8a93bdcb3f0..512be0a92ed 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -593,6 +593,10 @@
# (change requires restart)
#max_pred_locks_per_transaction = 64 # min 10
# (change requires restart)
+#max_pred_locks_per_relation = -2 # negative values mean
+ # (max_pred_locks_per_transaction
+ # / -max_pred_locks_per_relation) - 1
+#max_pred_locks_per_page = 2 # min 0
#------------------------------------------------------------------------------
diff --git a/src/include/storage/predicate.h b/src/include/storage/predicate.h
index f996d8e8181..8f9ea29917b 100644
--- a/src/include/storage/predicate.h
+++ b/src/include/storage/predicate.h
@@ -22,6 +22,8 @@
* GUC variables
*/
extern int max_predicate_locks_per_xact;
+extern int max_predicate_locks_per_relation;
+extern int max_predicate_locks_per_page;
/* Number of SLRU buffers to use for predicate locking */