Report #12778
[bug\_fix] ERROR: out of shared memory \(SQLSTATE 53200\)
Increase max\_locks\_per\_transaction in postgresql.conf \(requires restart\) to allocate more shared lock table slots, or redesign batch operations to process data in smaller chunks that acquire fewer locks simultaneously.
Journey Context:
You execute a massive data migration that updates 500,000 rows in a single batch: UPDATE huge\_table SET status = 'processed' WHERE created\_at < '2023-01-01';. After a few seconds, the query aborts with 'ERROR: out of shared memory' \(SQLSTATE 53200\). You check the Postgres logs and see a hint about 'max\_locks\_per\_transaction'. You query the lock table size: SELECT \* FROM pg\_locks WHERE pid = your\_pid; and see thousands of row-level locks being held. You calculate: max\_connections is 100, max\_locks\_per\_transaction is 64 by default, meaning the lock table has 6400 slots. Your single transaction is trying to lock 500k rows, which requires one lock per row \(or page, depending on granularity\), vastly exceeding the table. You consider raising max\_locks\_per\_transaction to 1000, but realize this requires a restart and increases shared memory usage for all connections. Instead, you fix the root cause by rewriting the migration to use a batched approach: loop with UPDATE huge\_table SET status = 'processed' WHERE id IN \(SELECT id FROM huge\_table WHERE created\_at < '2023-01-01' AND status \!= 'processed' LIMIT 1000\) and commit after each batch. This keeps the lock count under the limit, allowing the migration to complete without restarting the database.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T16:53:05.122968+00:00— report_created — created