Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f1169ab

Browse files
committed
Don't count background workers against a user's connection limit.
Doing so doesn't seem to be within the purpose of the per user connection limits, and has particularly unfortunate effects in conjunction with parallel queries. Backpatch to 9.6 where parallel queries were introduced. David Rowley, reviewed by Robert Haas and Albe Laurenz.
1 parent aedd554 commit f1169ab

File tree

8 files changed

+47
-3
lines changed

8 files changed

+47
-3
lines changed

doc/src/sgml/ref/create_database.sgml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,8 @@ CREATE DATABASE <replaceable class="PARAMETER">name</replaceable>
258258
The <literal>CONNECTION LIMIT</> option is only enforced approximately;
259259
if two new sessions start at about the same time when just one
260260
connection <quote>slot</> remains for the database, it is possible that
261-
both will fail. Also, the limit is not enforced against superusers.
261+
both will fail. Also, the limit is not enforced against superusers or
262+
background worker processes.
262263
</para>
263264
</refsect1>
264265

doc/src/sgml/ref/create_role.sgml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,10 @@ CREATE ROLE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replac
198198
<listitem>
199199
<para>
200200
If role can log in, this specifies how many concurrent connections
201-
the role can make. -1 (the default) means no limit.
201+
the role can make. -1 (the default) means no limit. Note that only
202+
normal connections are counted towards this limit. Neither prepared
203+
transactions nor background worker connections are counted towards
204+
this limit.
202205
</para>
203206
</listitem>
204207
</varlistentry>

src/backend/access/transam/twophase.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ MarkAsPreparing(TransactionId xid, const char *gid,
420420
proc->backendId = InvalidBackendId;
421421
proc->databaseId = databaseid;
422422
proc->roleId = owner;
423+
proc->isBackgroundWorker = false;
423424
proc->lwWaiting = false;
424425
proc->lwWaitMode = 0;
425426
proc->waitLock = NULL;

src/backend/storage/ipc/procarray.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2744,6 +2744,38 @@ CountDBBackends(Oid databaseid)
27442744
return count;
27452745
}
27462746

2747+
/*
2748+
* CountDBConnections --- counts database backends ignoring any background
2749+
* worker processes
2750+
*/
2751+
int
2752+
CountDBConnections(Oid databaseid)
2753+
{
2754+
ProcArrayStruct *arrayP = procArray;
2755+
int count = 0;
2756+
int index;
2757+
2758+
LWLockAcquire(ProcArrayLock, LW_SHARED);
2759+
2760+
for (index = 0; index < arrayP->numProcs; index++)
2761+
{
2762+
int pgprocno = arrayP->pgprocnos[index];
2763+
volatile PGPROC *proc = &allProcs[pgprocno];
2764+
2765+
if (proc->pid == 0)
2766+
continue; /* do not count prepared xacts */
2767+
if (proc->isBackgroundWorker)
2768+
continue; /* do not count background workers */
2769+
if (!OidIsValid(databaseid) ||
2770+
proc->databaseId == databaseid)
2771+
count++;
2772+
}
2773+
2774+
LWLockRelease(ProcArrayLock);
2775+
2776+
return count;
2777+
}
2778+
27472779
/*
27482780
* CancelDBBackends --- cancel backends that are using specified database
27492781
*/
@@ -2803,6 +2835,8 @@ CountUserBackends(Oid roleid)
28032835

28042836
if (proc->pid == 0)
28052837
continue; /* do not count prepared xacts */
2838+
if (proc->isBackgroundWorker)
2839+
continue; /* do not count background workers */
28062840
if (proc->roleId == roleid)
28072841
count++;
28082842
}

src/backend/storage/lmgr/proc.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ InitProcess(void)
370370
MyProc->backendId = InvalidBackendId;
371371
MyProc->databaseId = InvalidOid;
372372
MyProc->roleId = InvalidOid;
373+
MyProc->isBackgroundWorker = IsBackgroundWorker;
373374
MyPgXact->delayChkpt = false;
374375
MyPgXact->vacuumFlags = 0;
375376
/* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
@@ -542,6 +543,7 @@ InitAuxiliaryProcess(void)
542543
MyProc->backendId = InvalidBackendId;
543544
MyProc->databaseId = InvalidOid;
544545
MyProc->roleId = InvalidOid;
546+
MyProc->isBackgroundWorker = IsBackgroundWorker;
545547
MyPgXact->delayChkpt = false;
546548
MyPgXact->vacuumFlags = 0;
547549
MyProc->lwWaiting = false;

src/backend/utils/init/postinit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ CheckMyDatabase(const char *name, bool am_superuser)
350350
*/
351351
if (dbform->datconnlimit >= 0 &&
352352
!am_superuser &&
353-
CountDBBackends(MyDatabaseId) > dbform->datconnlimit)
353+
CountDBConnections(MyDatabaseId) > dbform->datconnlimit)
354354
ereport(FATAL,
355355
(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
356356
errmsg("too many connections for database \"%s\"",

src/include/storage/proc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ struct PGPROC
103103
Oid databaseId; /* OID of database this backend is using */
104104
Oid roleId; /* OID of role using this backend */
105105

106+
bool isBackgroundWorker; /* true if background worker. */
107+
106108
/*
107109
* While in hot standby mode, shows that a conflict signal has been sent
108110
* for the current transaction. Set/cleared while holding ProcArrayLock,

src/include/storage/procarray.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ extern pid_t CancelVirtualTransaction(VirtualTransactionId vxid, ProcSignalReaso
7373

7474
extern bool MinimumActiveBackends(int min);
7575
extern int CountDBBackends(Oid databaseid);
76+
extern int CountDBConnections(Oid databaseid);
7677
extern void CancelDBBackends(Oid databaseid, ProcSignalReason sigmode, bool conflictPending);
7778
extern int CountUserBackends(Oid roleid);
7879
extern bool CountOtherDBBackends(Oid databaseId,

0 commit comments

Comments
 (0)