On 4/6/17 15:01, Peter Eisentraut wrote: > On 2/15/17 11:19, Peter Eisentraut wrote: >> So I would like to have a background worker limit per user, as you >> allude to. Attached is a patch that implements a GUC setting >> max_worker_processes_per_user. >> >> Besides the uses for background sessions, but it can also be useful for >> parallel workers, logical replication apply workers, or things like >> third-party partitioning extensions. > > Given that background sessions have been postponed, is there still > interest in this separate from that? It would be useful for per-user > parallel worker limits, for example.
Here is a slightly updated patch for consideration in the upcoming commit fest. -- Peter Eisentraut http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From e99d8ccf9dfd007c054b20e8d10ffb35cfb722b7 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut <pete...@gmx.net> Date: Wed, 23 Aug 2017 19:10:21 -0400 Subject: [PATCH v2] Add max_worker_processes_per_user setting --- doc/src/sgml/config.sgml | 28 ++++++++++++++++++++++++++++ doc/src/sgml/ref/create_role.sgml | 3 ++- src/backend/postmaster/bgworker.c | 28 ++++++++++++++++++++++++++++ src/backend/utils/init/globals.c | 1 + src/backend/utils/misc/guc.c | 12 ++++++++++++ src/include/miscadmin.h | 1 + 6 files changed, 72 insertions(+), 1 deletion(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 2b6255ed95..24f1d13f8a 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -2041,6 +2041,34 @@ <title>Asynchronous Behavior</title> </listitem> </varlistentry> + <varlistentry id="guc-max-worker-processes-per-user" xreflabel="max_worker_processes_per_user"> + <term><varname>max_worker_processes_per_user</varname> (<type>integer</type>) + <indexterm> + <primary><varname>max_worker_processes_per_user</> configuration parameter</primary> + </indexterm> + </term> + <listitem> + <para> + Sets the maximum number of background processes allowed per user. If + the setting is -1, then there is no limit. That is also the default. + </para> + + <para> + Only superusers can change this setting. + Unlike <varname>max_worker_processes</varname>, which controls the + overall instance limit, this setting can also be changed at run time + and can be set differently for different users by + using <literal>ALTER ROLE ... SET</literal>. + </para> + + <para> + This setting is checked at the time the worker process is started + using the setting in the session that causes it to start. Changes to + the setting will not affect already running workers. + </para> + </listitem> + </varlistentry> + <varlistentry id="guc-max-parallel-workers-per-gather" xreflabel="max_parallel_workers_per_gather"> <term><varname>max_parallel_workers_per_gather</varname> (<type>integer</type>) <indexterm> diff --git a/doc/src/sgml/ref/create_role.sgml b/doc/src/sgml/ref/create_role.sgml index 36772b678a..a7c547d907 100644 --- a/doc/src/sgml/ref/create_role.sgml +++ b/doc/src/sgml/ref/create_role.sgml @@ -204,7 +204,8 @@ <title>Parameters</title> the role can make. -1 (the default) means no limit. Note that only normal connections are counted towards this limit. Neither prepared transactions nor background worker connections are counted towards - this limit. + this limit (see <xref linkend="guc-max-worker-processes-per-user"> + for the latter). </para> </listitem> </varlistentry> diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index 28af6f0f07..443dcaa4f3 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -79,6 +79,7 @@ typedef struct BackgroundWorkerSlot bool in_use; bool terminate; pid_t pid; /* InvalidPid = not started yet; 0 = dead */ + Oid roleid; /* user responsible for it */ uint64 generation; /* incremented when slot is recycled */ BackgroundWorker worker; } BackgroundWorkerSlot; @@ -976,6 +977,32 @@ RegisterDynamicBackgroundWorker(BackgroundWorker *worker, return false; } + /* + * Check number of used slots for user + */ + if (max_worker_processes_per_user >= 0) + { + int count = 0; + + for (slotno = 0; slotno < BackgroundWorkerData->total_slots; ++slotno) + { + BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno]; + + if (slot->in_use && slot->roleid == GetUserId()) + count++; + } + + if (count > max_worker_processes_per_user) + { + ereport(LOG, + (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED), + errmsg("too many worker processes for role \"%s\"", + GetUserNameFromId(GetUserId(), false)))); + LWLockRelease(BackgroundWorkerLock); + return false; + } + } + /* * Look for an unused slot. If we find one, grab it. */ @@ -987,6 +1014,7 @@ RegisterDynamicBackgroundWorker(BackgroundWorker *worker, { memcpy(&slot->worker, worker, sizeof(BackgroundWorker)); slot->pid = InvalidPid; /* indicates not started yet */ + slot->roleid = GetUserId(); slot->generation++; slot->terminate = false; generation = slot->generation; diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index 7c09498dc0..fa1b689ae7 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -123,6 +123,7 @@ int replacement_sort_tuples = 150000; int NBuffers = 1000; int MaxConnections = 90; int max_worker_processes = 8; +int max_worker_processes_per_user = -1; int max_parallel_workers = 8; int MaxBackends = 0; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 246fea8693..23dc33bd61 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -2506,6 +2506,18 @@ static struct config_int ConfigureNamesInt[] = check_max_worker_processes, NULL, NULL }, + { + {"max_worker_processes_per_user", + PGC_SUSET, + RESOURCES_ASYNCHRONOUS, + gettext_noop("Maximum number of concurrent worker processes per user."), + NULL, + }, + &max_worker_processes_per_user, + -1, -1, MAX_BACKENDS, + NULL, NULL, NULL + }, + { {"max_logical_replication_workers", PGC_POSTMASTER, diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index dad98de98d..a9f21cc34b 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -158,6 +158,7 @@ extern PGDLLIMPORT int NBuffers; extern int MaxBackends; extern int MaxConnections; extern int max_worker_processes; +extern int max_worker_processes_per_user; extern int max_parallel_workers; extern PGDLLIMPORT int MyProcPid; -- 2.14.1
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers