DB Internals AtlasPostgreSQL 18.6 Home About

Parameter · Lock Management

max_locks_per_transaction

Sets the maximum number of locks per transaction. The shared lock table is sized on the assumption that at most "max_locks_per_transaction" objects per server process or prepared transaction will need to be locked at any one time.

  • Default: 64
  • Type: integer
  • Range: 10 … 2147483647
  • Applies: Restart required

In plain words

Every table, index or other object a transaction uses gets a lock entry in a shared lock table. This setting decides how big that table is: roughly max_locks_per_transaction × (max_connections + other backends + max_prepared_transactions) entries. Despite the name, one transaction can use more than this, as long as the whole table has room.

Raise it when you see out of shared memory with the hint to increase it, typically with heavily partitioned tables or pg_dump of databases with many objects.

For DBAs and operators

The lock table (and its companion PROCLOCK table) is allocated at startup with max_locks_per_transaction × (MaxBackends + max_prepared_transactions) entries, where MaxBackends = max_connections + autovacuum_worker_slots + max_worker_processes + max_wal_senders + a couple of special processes. When it is full:

ERROR: out of shared memory
HINT: You might need to increase "max_locks_per_transaction".

It limits objects, not rows (row locks live in the tuples). Common triggers: a query on a table with thousands of partitions (each partition and its indexes is locked when not pruned at plan time), pg_dump / pg_upgrade on databases with very many tables (it locks all of them in one transaction), and DROP SCHEMA … CASCADE.

Since PostgreSQL 18 it also sets the number of fast-path lock slots per backend (previously fixed at 16), so raising it can reduce contention on the shared lock table for partitioned workloads.

SELECT count(*), mode, fastpath FROM pg_locks GROUP BY 2, 3;

Each entry costs a few hundred bytes of shared memory, so 256 or 1024 is affordable. On a hot standby the value must be ≥ the primary's.

How to change it

Change in postgresql.conf or ALTER SYSTEM, then restart the server.

See it in context

Locking and deadlocks Memory architecture

Related parameters

max_pred_locks_per_transaction max_connections max_prepared_transactions deadlock_timeout

All Lock Management parameters