Report #16681
[bug\_fix] out of shared memory \(max\_locks\_per\_transaction\)
Increase \`max\_locks\_per\_transaction\` in postgresql.conf \(requires restart\) and ensure \`max\_connections\` is tuned accordingly since total locks = max\_locks\_per\_transaction \* max\_connections. Alternatively, break large transactions into smaller batches to reduce concurrent lock usage.
Journey Context:
A batch ETL job or maintenance script touching thousands of partitioned tables fails with ERROR: out of shared memory or could not lock table: out of shared memory. The error suggests increasing max\_locks\_per\_transaction. Investigation reveals that PostgreSQL pre-allocates shared memory for the lock table at startup. The size is determined by the formula: max\_locks\_per\_transaction \* \(max\_connections \+ max\_prepared\_transactions\). Each table, index, partition, or row locked in a transaction consumes one slot in this table. When a transaction touches thousands of partitions \(common in time-series databases with monthly partitions over many years\), it exhausts the pre-allocated lock slots. The debugging involves checking the number of tables/partitions being touched, calculating lock usage, and realizing the default max\_locks\_per\_transaction \(typically 64\) is too low for this workload. The fix requires editing postgresql.conf to increase max\_locks\_per\_transaction to 256, 512, or higher depending on the number of objects touched in a single transaction, then restarting PostgreSQL. Additionally, the developer refactors the ETL job to process partitions in smaller batches \(e.g., 100 at a time\) rather than all in one transaction, reducing peak lock usage.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T03:17:57.500431+00:00— report_created — created