Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vlDR4-008wc0-1E for pgsql-admin@arkaria.postgresql.org; Wed, 28 Jan 2026 21:50:51 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vlDR3-0043P7-1A for pgsql-admin@arkaria.postgresql.org; Wed, 28 Jan 2026 21:50:49 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vlDR2-0043Ox-2G for pgsql-admin@lists.postgresql.org; Wed, 28 Jan 2026 21:50:49 +0000 Received: from mail-pf1-x433.google.com ([2607:f8b0:4864:20::433]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vlDQz-002oGF-1u for pgsql-admin@lists.postgresql.org; Wed, 28 Jan 2026 21:50:47 +0000 Received: by mail-pf1-x433.google.com with SMTP id d2e1a72fcca58-81e9d0cd082so246386b3a.0 for ; Wed, 28 Jan 2026 13:50:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1769637045; cv=none; d=google.com; s=arc-20240605; b=gGucf4B+9yXEvLXIhpPCAdvm0YmvOn5L5nMY6fBP4w1BPRwoE/pJgz1PN9OCNnSlXr yRylK9ntt4xrLYygRti5pSLRGPixtR6aXnp6uytonR55xLfx8yodSkebhTUusXo4SAw2 POK0mWN733666cpowPZxR4gn+x/0ih9eq1Juk5JTjD+QWcLycwUxICpFJXopSPvHqL5p aNwW+RktISm43wS5kJ9VuIYhXrDJUzS31nD709GVcaJk+eZ8bpqTXjDITT40v2Pze12W O+F1LWrZ694gKNwg1VfVG/RSZtOr2d2CoraG9XimZAJt1oLZv5JvW2TcOQ8n7fSoBTHe 5OMg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :dkim-signature; bh=lPgQckZCVNABrAvSD8GUNSBH3C3VCiWzZVw0sQSEzm8=; fh=NsrcDeWI48aIyx6zGns460Rs/KoAjFnlJFVaNlo6lMg=; b=fORYp2sk1CEoL9hQm9BDNox1Vs5LtRRRYP4q/WhId3L/cWgS45tDOCl1ugRxIkW+rv KBF4qgb1Vw9jbC1C5dBKLSJ2xoJZ+/uU0rIIyLnX2BBxd3x4X9xClJO3HXqM5EwSo1j/ S9ySMo4JgA22M2RVy0JsgfjOSokgR87AqpATSN9UOdFnLGgU5a/FHhTJVNjCTQsC/cSR EWUt3EqW0RIAHZZOvnJ1wFM5RjtvAOeMka97fOMMqJAbmGvXOv/SYe1qK7HjE9cCx5XQ u8r2Y73XzIOJ0eD8kEOUasqNwHaxo94HIMiGGvV3BarUADAER2HKgJX8L5nPlz7HqsBN he0g==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1769637045; x=1770241845; darn=lists.postgresql.org; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=lPgQckZCVNABrAvSD8GUNSBH3C3VCiWzZVw0sQSEzm8=; b=iIvFB74+gGjsu3RodeL344MkbyP9fydVCD+63NO+mFgRGzatrLbSnO3mNbsaQj1c7/ xJjre1wimBgFzG1Dk0r8d1ToWBmTp1Wm4F3Qx4/eVemYiwb/NtOfnJj22gWG/j8q95l0 5GQEdbPymLknfd+NJR1wfR6q704QISE+kFUBU1bqDWBAUG1dLPWKmXGL2uW75wRtgHim HHK04pb9enxb+9WWzCEjraTXB3zkvYfjzpN2JgPuXMvTAii2FkovwUcTMcBoxlQ1VpLM vAc5myds+Pzz4ggRPPRlx+Rp22fLJiNUC2fEVtopMvk7DfA/KhNu0j+ri2NngJmgokg/ /5fA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769637045; x=1770241845; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=lPgQckZCVNABrAvSD8GUNSBH3C3VCiWzZVw0sQSEzm8=; b=gdORarssk4nzDh2c4EPOCHRwr03TU5z6l+3EE3++McTHEJeHHV362WlRqMTtpgUoPh CVIb+2WKgT1lGG2MVMJTP1sgPCaiXhXad7WvOs/LrfkQm9b/PbejsY034SCdFQeQcYaY EIW84AXlzJV7/BtpVf1G2q3Q8F+Q90+Y60heN28MiBbqni/OqxUSrx9KLR8s6IWYfFoR NewnyWdEhR6sxnfH3ZVJSZWapf5sUotLMy36pAY7bVlXkHgpot7FbrPAs16bi0ZXTENI k68H4Jm23e0XSq7+400Km6v+IcUb5hjA7r4ef5zj8JH0bIcknlH3tYlYLB4oj1XGmBgX wdYg== X-Gm-Message-State: AOJu0Ywku5A3Z+LCZuUDiEgxzfQtFJ195OBstKyn/j6PEN3cuZPvOBLD Xz1ig8OzVEYZE1MWrl+Raq7S5not2c6Fnx5AqaLjmXlP3EfrM9IQ71FoAw3XCqszyCx1QE5jxjr 9sTmVgDVTA7iKjxXx3DMnDYKug7CQBdt77vRx X-Gm-Gg: AZuq6aKZiq8wlrl5q8JIVoAGrY5dgxCT4z2SFz6Sh1BGvW1QVmMjXfwYAiTXQtpZFLT euhzvaur6sPBVpk5m4EXg4I+HZ26Ha7HKPGL+2d2RFZdDB0RoZBO93UOmVsrUKWOg4GnhLRscXM pxh/YMvj/qsKQFAcEqroVBmjpMhQGDW8ChxtHfLofNCVzFoq1Z+jkJD9hJsZ8KfQBJ+F0DVv+qJ FKW5d45rPyZOEdyq2Yra0ZVMr0NqSfEGQwqzbQYsYk7yC685lwVGaFvA5busC+VZEeqMWaTUP3h h3SPTCw= X-Received: by 2002:a05:6a20:2d13:b0:35e:5a46:2d6b with SMTP id adf61e73a8af0-38ec6246b51mr6627429637.8.1769637044492; Wed, 28 Jan 2026 13:50:44 -0800 (PST) MIME-Version: 1.0 References: <854468.1769633854@sss.pgh.pa.us> In-Reply-To: <854468.1769633854@sss.pgh.pa.us> From: Ron Johnson Date: Wed, 28 Jan 2026 16:50:32 -0500 X-Gm-Features: AZwV_Qh-oxOMGUUhe-2cPMWp2Akc62iYLgOR6b7DFt7uXLUQucMSqpEUipTtJMQ Message-ID: Subject: Re: Maximum amount of pg_locks To: "pgsql-admin@lists.postgresql.org" Content-Type: multipart/alternative; boundary="0000000000006b1db1064979bb3c" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --0000000000006b1db1064979bb3c Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Wed, Jan 28, 2026 at 3:57=E2=80=AFPM Tom Lane wrote: > Tim Herren writes: > > I'm trying to wrap my head around the way the calculation for the > maximum amount of locks works in postgres 16.11 > > I already came to the understanding that the maximum amount of locks ar= e > not on a transaction basis, but rather influenced by the setting > "max_locks_per_transaction" and the "max_connections". > > I'm saying influenced rather than calculated because on my server a > simple multiplication of those two values, set at 512 and 180 respectivel= y > gives 92160. > > Yet I regularly observe around 119k locks during my backup using > "pg_dump -Fc". > > Well, the hash table size is indeed set by a calculation of that form, > but it's max_locks_per_transaction times the number of potential > locker processes --- not only regular sessions (max_connections), > but also autovacuum processes and other background workers. And > prepared transactions, too. lock.c has > > #define NLOCKENTS() \ > mul_size(max_locks_per_xact, add_size(MaxBackends, > max_prepared_xacts)) > > where postinit.c calculates MaxBackends as: > > /* Note that this does not include "auxiliary" processes */ > MaxBackends =3D MaxConnections + autovacuum_worker_slots + > max_worker_processes + max_wal_senders + > NUM_SPECIAL_WORKER_PROCS; > > Then on top of that, there's a pretty considerable fudge factor: > lock.c scales up its shared-memory size request by 10%, and there > is (from memory) about 100K slop space added on top of the total of > shared-memory size requests from all modules, and all of that space > is potentially available for the lock table to overflow into. (Other > shared data structures could claim it too, but I think the lock table > is the only one that we don't have a hard upper bound for.) > > If you really want to know how many locks can be taken in your > particular setup, I'd counsel experimenting by deliberately exhausting > the lock space. (Maybe not during production hours.) The precise > limit will vary across PG versions, and potentially depend on other > factors like what extensions you have loaded. > I asked a similar question a few years ago, and you said that on modern systems it's no problem to bump max_locks_per_transaction pretty darned high (like 1 million). "The default, 64, has historically proven sufficient" had me slowly incrementing, but after your comment *I added a zero* to my existing max_locks_per_transaction value (1536, one and a half KiB) *and haven't thought about it since*. --=20 Death to , and butter sauce. Don't boil me, I'm still alive. lobster! --0000000000006b1db1064979bb3c Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
On Wed, Jan 28, 2026 at 3:57=E2=80=AFPM T= om Lane <tgl@sss.pgh.pa.us> = wrote:
Tim Herren <tim.herren@protonmail.ch> writ= es:
> I'm trying to wrap my head around the way the calculation for the = maximum amount of locks works in postgres 16.11
> I already came to the understanding that the maximum amount of locks a= re not on a transaction basis, but rather influenced by the setting "m= ax_locks_per_transaction" and the "max_connections".
> I'm saying influenced rather than calculated because on my server = a simple multiplication of those two values, set at 512 and 180 respectivel= y gives 92160.
> Yet I regularly observe around 119k locks during my backup using "= ;pg_dump -Fc".

Well, the hash table size is indeed set by a calculation of that form,
but it's max_locks_per_transaction times the number of potential
locker processes --- not only regular sessions (max_connections),
but also autovacuum processes and other background workers.=C2=A0 And
prepared transactions, too.=C2=A0 lock.c has

#define NLOCKENTS() \
=C2=A0 =C2=A0 =C2=A0 =C2=A0 mul_size(max_locks_per_xact, add_size(MaxBacken= ds, max_prepared_xacts))

where postinit.c calculates MaxBackends as:

=C2=A0 =C2=A0 =C2=A0 =C2=A0 /* Note that this does not include "auxili= ary" processes */
=C2=A0 =C2=A0 =C2=A0 =C2=A0 MaxBackends =3D MaxConnections + autovacuum_wor= ker_slots +
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 max_worker_processe= s + max_wal_senders + NUM_SPECIAL_WORKER_PROCS;

Then on top of that, there's a pretty considerable fudge factor:
lock.c scales up its shared-memory size request by 10%, and there
is (from memory) about 100K slop space added on top of the total of
shared-memory size requests from all modules, and all of that space
is potentially available for the lock table to overflow into.=C2=A0 (Other<= br> shared data structures could claim it too, but I think the lock table
is the only one that we don't have a hard upper bound for.)

If you really want to know how many locks can be taken in your
particular setup, I'd counsel experimenting by deliberately exhausting<= br> the lock space.=C2=A0 (Maybe not during production hours.)=C2=A0 The precis= e
limit will vary across PG versions, and potentially depend on other
factors like what extensions you have loaded.

I asked a similar question a few years ago, and you said that on mod= ern systems it's no problem to bump max_locks_per_transaction pretty da= rned high (like 1 million).=C2=A0 =C2=A0"The default, 64, has historic= ally proven sufficient" had me slowly incrementing, but after your com= ment I added a zero to my existing max_locks_per_transaction value (= 1536, one and a half KiB) and haven't thought about it since.

--
Death to <= Redacted>, and butter sauce.
Don't boil me, I'm still alive.=
<Redacted> lobster!
--0000000000006b1db1064979bb3c--