Ho un server che esegue Postgres 9.1.15. Il server ha 2 GB di RAM e non lo scambio. Intermittently Postgres inizierà a ricevere errori di "memoria insufficiente" su alcuni SELECT e continuerà a farlo finché non riavvio Postgres o alcuni dei client che sono connessi ad esso. La cosa strana è che quando ciò accade, free
riporta ancora oltre 500 MB di memoria libera.Postgres perde gli errori di memoria nonostante abbia un sacco di memoria libera
select version();
:
PostgreSQL 9.1.15 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, 64-bit
uname -a
:
Linux db 3.2.0-23-virtual #36-Ubuntu SMP Tue Apr 10 22:29:03 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
postgresql.conf (tutto il resto è commentata/default):
max_connections = 100
shared_buffers = 500MB
work_mem = 2000kB
maintenance_work_mem = 128MB
wal_buffers = 16MB
checkpoint_segments = 32
checkpoint_completion_target = 0.9
random_page_cost = 2.0
effective_cache_size = 1000MB
default_statistics_target = 100
log_temp_files = 0
ho ottenuto questi valori da pgtune (I ha scelto "tipi di applicazioni misti") e ha continuato a giocherellare li basati su ciò che ho letto, senza fare molti progressi reali. Al momento ci sono 68 connessioni, che è un numero tipico (non sto ancora utilizzando pgbouncer o qualsiasi altro gestore di connessione).
/etc/sysctl.conf
:
kernel.shmmax=1050451968
kernel.shmall=256458
vm.overcommit_ratio=100
vm.overcommit_memory=2
prima ho cambiato overcommit_memory
-2 una quindicina di giorni fa, dopo il killer OOM ha ucciso il server Postgres. In precedenza il server funzionava bene da molto tempo. Gli errori che ottengo ora sono meno catastrofici ma molto più fastidiosi perché sono molto più frequenti.
Non ho avuto molta fortuna nell'individuare il primo evento che causa il postgres "fuori dalla memoria" - sembra essere diverso ogni volta. Il momento più recente si è schiantato, le prime tre righe registrati sono stati:
2015-04-07 05:32:39 UTC ERROR: out of memory
2015-04-07 05:32:39 UTC DETAIL: Failed on request of size 125.
2015-04-07 05:32:39 UTC CONTEXT: automatic analyze of table "xxx.public.delayed_jobs"
TopMemoryContext: 68688 total in 10 blocks; 4560 free (4 chunks); 64128 used
[... snipped heaps of lines which I can provide if they are useful ...]
---
2015-04-07 05:33:58 UTC ERROR: out of memory
2015-04-07 05:33:58 UTC DETAIL: Failed on request of size 16.
2015-04-07 05:33:58 UTC STATEMENT: SELECT oid, typname, typelem, typdelim, typinput FROM pg_type
2015-04-07 05:33:59 UTC LOG: could not fork new process for connection: Cannot allocate memory
2015-04-07 05:33:59 UTC LOG: could not fork new process for connection: Cannot allocate memory
2015-04-07 05:33:59 UTC LOG: could not fork new process for connection: Cannot allocate memory
TopMemoryContext: 396368 total in 50 blocks; 10160 free (28 chunks); 386208 used
[... snipped heaps of lines which I can provide if they are useful ...]
---
2015-04-07 05:33:59 UTC ERROR: out of memory
2015-04-07 05:33:59 UTC DETAIL: Failed on request of size 1840.
2015-04-07 05:33:59 UTC STATEMENT: SELECT... [nested select with 4 joins, 19 ands, and 2 order bys]
TopMemoryContext: 388176 total in 49 blocks; 17264 free (55 chunks); 370912 used
L'incidente, prima che, poche ore prima, aveva solo tre istanze di tale ultima query come le prime tre righe del disastro. Quella query viene eseguita molto spesso, quindi non sono sicuro se i problemi sono perché di questa query, o se compare appena nel log degli errori perché è un SELECT ragionevolmente complesso che viene eseguito sempre. Detto questo, ecco un EXPLAIN ANALYZE di esso: http://explain.depesz.com/s/r00
Questo è ciò che ulimit -a
per l'utente postgres assomiglia:
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 15956
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 15956
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
Cercherò di ottenere il numero esatto dalla free
la prossima volta che c'è un incidente, nel frattempo questo è un braindump di tutte le informazioni che ho.
Qualche idea su dove andare da qui?
per quanto ne so il kernel deve promettere di memoria per i processi se è allocata, anche se sono mai intenzione di usarlo. Ciò include le regioni di memoria copy-on-write 'fork()' ed del postmaster. Quindi, anche se la memoria è libera nel senso di non essere attualmente mappata nello spazio degli indirizzi di un processo, viene commessa. Credo. Potrei essere totalmente sventolante qui. È anche possibile che alcune delle stranezze del kernel riguardo alla contabilità della memoria condivisa siano in discussione. –
'maintenance_work_mem = 128 MB 'sembra abbastanza grande se si considerano i limiti di memoria. Il fatto che il problema si verifichi quando viene eseguita un'analisi automatica, indica anche che questo parametro è troppo grande. –
@a_horse_with_no_name Ho provato a impostarlo su '16MB'. Riferirà i risultati. Qualcos'altro da cercare nel frattempo? –