database resource_error ai_generated true

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

ID: database/postgresql-too-many-snapshots

Also available as: JSON · Markdown · 中文
78%Fix Rate
89%Confidence
1Evidence
2024-04-18First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
PostgreSQL 14 active — — —
PostgreSQL 15 active — — —
PostgreSQL 16 active — — —

Root Cause

PostgreSQL's shared memory for lock management is exhausted, typically because too many concurrent transactions hold locks or snapshots, exceeding the max_locks_per_transaction * max_connections limit.

generic

中文

PostgreSQL 用于锁管理的共享内存耗尽,通常是因为太多并发事务持有锁或快照,超过了 max_locks_per_transaction * max_connections 的限制。

Official Documentation

https://www.postgresql.org/docs/16/runtime-config-resource.html#GUC-MAX-LOCKS-PER-TRANSACTION

Workarounds

  1. 85% success Increase max_locks_per_transaction in postgresql.conf (e.g., to 128 or 256), then restart PostgreSQL. Verify with SHOW max_locks_per_transaction;. Also consider reducing the number of concurrent long-running transactions.
    Increase max_locks_per_transaction in postgresql.conf (e.g., to 128 or 256), then restart PostgreSQL. Verify with SHOW max_locks_per_transaction;. Also consider reducing the number of concurrent long-running transactions.
  2. 80% success Identify and terminate idle-in-transaction sessions that hold locks: SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle in transaction' AND xact_start < now() - interval '10 minutes';
    Identify and terminate idle-in-transaction sessions that hold locks: SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle in transaction' AND xact_start < now() - interval '10 minutes';

中文步骤

  1. Increase max_locks_per_transaction in postgresql.conf (e.g., to 128 or 256), then restart PostgreSQL. Verify with SHOW max_locks_per_transaction;. Also consider reducing the number of concurrent long-running transactions.
  2. Identify and terminate idle-in-transaction sessions that hold locks: SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle in transaction' AND xact_start < now() - interval '10 minutes';

Dead Ends

Common approaches that don't work:

  1. Restart PostgreSQL to clear the shared memory, assuming it's a temporary leak 85% fail

    If the workload pattern (e.g., many concurrent long-running transactions) remains the same, the error will recur quickly after restart.

  2. Increase max_connections instead of max_locks_per_transaction 75% fail

    max_connections increases the number of possible connections but does not increase the lock space per connection; the shared memory limit is still bounded by max_locks_per_transaction * max_connections.