PostgreSQL-Fehler: out of shared memory
ERROR: out of shared memory
HINT: You might need to increase max_locks_per_transaction.
Trotz der alarmierenden Formulierung geht es fast nie darum, dass dem Server generell der Speicher ausgeht. Wenn es mit dem max_locks_per_transaction-Hinweis kommt, bedeutet es eine bestimmte Sache: die gemeinsame Lock-Tabelle — die Struktur fester Größe, in der PostgreSQL Locks auf Tabellen, Indizes und anderen Objekten verfolgt — ist voll.
Was dieser Fehler bedeutet
Die Lock-Tabelle wird beim Serverstart dimensioniert, mit Platz für etwa max_locks_per_transaction × (max_connections + max_prepared_transactions) Objekt-Locks. Zwei Eigenschaften erklären alles, was Sie beobachten:
- Trotz des Namens ist
max_locks_per_transactionkeine Obergrenze pro Transaktion — es dimensioniert nur den gemeinsamen Pool. Eine einzige Transaktion kann problemlos Tausende Locks halten, solange der Pool Platz hat. - Was auch bedeutet, dass eine gierige Transaktion den Pool für alle leeren kann: der Fehler kann einen unschuldigen Umstehenden treffen, nicht die Transaktion, die die Locks verbraucht hat.
Jede Tabelle, Partition und jeder Index, den eine Query anfasst, braucht einen eigenen Lock-Eintrag, gehalten bis zum Ende der Transaktion. Das ist die Arithmetik, die Sie erwischt: eine Query über eine Tabelle mit 2.000 Partitionen und je einigen Indizes kann viele Tausend Einträge brauchen — während die Standarddimensionierung (64 × ~100 Verbindungen) Ihnen rund 6.400 für den gesamten Server gibt.
Häufige Ursachen
- Partitionierte Tabellen mit vielen Partitionen: eine Query, die nicht prunen kann, fasst jede Partition und jeden ihrer Indizes an. Mit Abstand der häufigste Auslöser.
pg_dump/pg_restoreauf Datenbanken mit einer sehr großen Anzahl von Objekten (es sperrt jede Tabelle, die es dumpt, in einer Transaktion).- Migrationen, die viele Tabellen in einer einzigen Transaktion ändern oder verwerfen.
- Viele gleichzeitige Transaktionen, die jeweils eine mäßige Anzahl von Relationen anfassen — der Pool ist geteilt, es kommt also auf die Summe an.
So diagnostizieren Sie ihn
Während die fehlschlagende Arbeitslast läuft (oder kurz bevor sie fehlschlägt):
-- Wie voll die Lock-Tabelle ist:
SELECT count(*) FROM pg_locks;
-- Wer die Einträge verbraucht:
SELECT pid, count(*)
FROM pg_locks
GROUP BY pid
ORDER BY count(*) DESC
LIMIT 10;
Vergleichen Sie die Gesamtzahl mit der obigen Formel bei Ihren Einstellungen. Wenn eine PID Tausende Locks hält, schauen Sie, was sie ausführt — und wenn Partitionen beteiligt sind, zählen Sie sie: SELECT count(*) FROM pg_inherits WHERE inhparent = 'events'::regclass;
So beheben Sie ihn
- Erhöhen Sie
max_locks_per_transaction— z. B. von 64 auf 256 oder 512 auf Servern mit stark partitionierten Schemas. Erfordert einen Neustart; der zusätzliche Shared Memory ist bescheiden.ALTER SYSTEM SET max_locks_per_transaction = 256; -- danach Neustart des Servers - Helfen Sie dem Partition-Pruning: stellen Sie sicher, dass Queries auf dem Partitionsschlüssel mit Werten filtern, die der Planner sehen kann, sodass überhaupt nur die relevanten Partitionen gesperrt werden.
- Batchen Sie breite Operationen: teilen Sie Migrationen und Wartungsskripte in mehrere Transaktionen statt einer riesigen.
- Überdenken Sie Partitionsanzahlen: Schemas mit vielen Tausend winzigen Partitionen zahlen diese Abgabe überall, nicht nur hier.
