OOM pomimo dostępnej pamięci (pamięci podręcznej)

12

Wpadamy na zabójcę OOM, mimo że prawie połowa naszej pamięci jest wykorzystywana na pamięć podręczną FS. Rejestrujemy statystyki pamięci raz na minutę (jak donosi u góry), ale wydaje się, że jest duża dostępność.

...

Mem:  15339640k total, 15268304k used,    71336k free,     3152k buffers
Swap:        0k total,        0k used,        0k free,  6608384k cached

Mem:  15339640k total, 14855280k used,   484360k free,    13748k buffers
Swap:        0k total,        0k used,        0k free,  6481852k cached

[OOM killer: postgres killed]

Mem:  15339640k total,  8212200k used,  7127440k free,    32776k buffers
Swap:        0k total,        0k used,        0k free,  2394444k cached

...

Szczegóły OOM z syslog:

...
Jun 10 05:45:25 db kernel: [11209156.840462] wal-e invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0, oom_score_adj=0
Jun 10 05:45:25 db kernel: [11209156.840469] wal-e cpuset=/ mems_allowed=0
Jun 10 05:45:25 db kernel: [11209156.840474] Pid: 7963, comm: wal-e Not tainted 3.2.0-43-virtual #68-Ubuntu
Jun 10 05:45:25 db kernel: [11209156.840477] Call Trace:
Jun 10 05:45:25 db kernel: [11209156.840498]  [<ffffffff81119711>] dump_header+0x91/0xe0
Jun 10 05:45:25 db kernel: [11209156.840502]  [<ffffffff81119a95>] oom_kill_process+0x85/0xb0
Jun 10 05:45:25 db kernel: [11209156.840506]  [<ffffffff81119e3a>] out_of_memory+0xfa/0x220
Jun 10 05:45:25 db kernel: [11209156.840511]  [<ffffffff8111f823>] __alloc_pages_nodemask+0x8c3/0x8e0
Jun 10 05:45:25 db kernel: [11209156.840520]  [<ffffffff81216e00>] ? noalloc_get_block_write+0x30/0x30
Jun 10 05:45:25 db kernel: [11209156.840528]  [<ffffffff811566c6>] alloc_pages_current+0xb6/0x120
Jun 10 05:45:25 db kernel: [11209156.840534]  [<ffffffff81116637>] __page_cache_alloc+0xb7/0xd0
Jun 10 05:45:25 db kernel: [11209156.840539]  [<ffffffff81118602>] filemap_fault+0x212/0x3c0
Jun 10 05:45:25 db kernel: [11209156.840553]  [<ffffffff81138c32>] __do_fault+0x72/0x550
Jun 10 05:45:25 db kernel: [11209156.840557]  [<ffffffff8113c2ea>] handle_pte_fault+0xfa/0x200
Jun 10 05:45:25 db kernel: [11209156.840562]  [<ffffffff8100638e>] ? xen_pmd_val+0xe/0x10
Jun 10 05:45:25 db kernel: [11209156.840567]  [<ffffffff81005309>] ? __raw_callee_save_xen_pmd_val+0x11/0x1e
Jun 10 05:45:25 db kernel: [11209156.840571]  [<ffffffff8113d559>] handle_mm_fault+0x269/0x370
Jun 10 05:45:25 db kernel: [11209156.840576]  [<ffffffff8100a56d>] ? xen_force_evtchn_callback+0xd/0x10
Jun 10 05:45:25 db kernel: [11209156.840581]  [<ffffffff8100ad42>] ? check_events+0x12/0x20
Jun 10 05:45:25 db kernel: [11209156.840589]  [<ffffffff8165b3cb>] do_page_fault+0x14b/0x520
Jun 10 05:45:25 db kernel: [11209156.840594]  [<ffffffff81160d64>] ? kmem_cache_free+0x104/0x110
Jun 10 05:45:25 db kernel: [11209156.840600]  [<ffffffff811ba2c8>] ? ep_remove+0xa8/0xc0
Jun 10 05:45:25 db kernel: [11209156.840604]  [<ffffffff811bb133>] ? sys_epoll_ctl+0xb3/0x3d0
Jun 10 05:45:25 db kernel: [11209156.840614]  [<ffffffff81658035>] page_fault+0x25/0x30
Jun 10 05:45:25 db kernel: [11209156.840617] Mem-Info:
Jun 10 05:45:25 db kernel: [11209156.840618] Node 0 DMA per-cpu:
Jun 10 05:45:25 db kernel: [11209156.840622] CPU    0: hi:    0, btch:   1 usd:   0
Jun 10 05:45:25 db kernel: [11209156.840624] CPU    1: hi:    0, btch:   1 usd:   0
Jun 10 05:45:25 db kernel: [11209156.840627] CPU    2: hi:    0, btch:   1 usd:   0
Jun 10 05:45:25 db kernel: [11209156.840629] CPU    3: hi:    0, btch:   1 usd:   0
Jun 10 05:45:25 db kernel: [11209156.840631] Node 0 DMA32 per-cpu:
Jun 10 05:45:25 db kernel: [11209156.840634] CPU    0: hi:  186, btch:  31 usd:  30
Jun 10 05:45:25 db kernel: [11209156.840637] CPU    1: hi:  186, btch:  31 usd:  47
Jun 10 05:45:25 db kernel: [11209156.840639] CPU    2: hi:  186, btch:  31 usd:  15
Jun 10 05:45:25 db kernel: [11209156.840641] CPU    3: hi:  186, btch:  31 usd:   2
Jun 10 05:45:25 db kernel: [11209156.840643] Node 0 Normal per-cpu:
Jun 10 05:45:25 db kernel: [11209156.840646] CPU    0: hi:  186, btch:  31 usd:   0
Jun 10 05:45:25 db kernel: [11209156.840648] CPU    1: hi:  186, btch:  31 usd:  14
Jun 10 05:45:25 db kernel: [11209156.840650] CPU    2: hi:  186, btch:  31 usd:   0
Jun 10 05:45:25 db kernel: [11209156.840653] CPU    3: hi:  186, btch:  31 usd:   1
Jun 10 05:45:25 db kernel: [11209156.840658] active_anon:3616567 inactive_anon:4798 isolated_anon:0
Jun 10 05:45:25 db kernel: [11209156.840660]  active_file:98 inactive_file:168 isolated_file:20
Jun 10 05:45:25 db kernel: [11209156.840661]  unevictable:1597 dirty:73 writeback:0 unstable:0
Jun 10 05:45:25 db kernel: [11209156.840662]  free:16921 slab_reclaimable:17631 slab_unreclaimable:7534
Jun 10 05:45:25 db kernel: [11209156.840663]  mapped:1614529 shmem:1613928 pagetables:124012 bounce:0
Jun 10 05:45:25 db kernel: [11209156.840666] Node 0 DMA free:7888kB min:4kB low:4kB high:4kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:7632kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:0kB slab_unreclaimable:0kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
Jun 10 05:45:25 db kernel: [11209156.840681] lowmem_reserve[]: 0 4016 15112 15112
Jun 10 05:45:25 db kernel: [11209156.840686] Node 0 DMA32 free:48368kB min:4176kB low:5220kB high:6264kB active_anon:3776804kB inactive_anon:28kB active_file:0kB inactive_file:20kB unevictable:932kB isolated(anon):0kB isolated(file):0kB present:4112640kB mlocked:932kB dirty:0kB writeback:0kB mapped:1458536kB shmem:1458632kB slab_reclaimable:17604kB slab_unreclaimable:8088kB kernel_stack:1872kB pagetables:190616kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:437 all_unreclaimable? yes
Jun 10 05:45:25 db kernel: [11209156.840698] lowmem_reserve[]: 0 0 11095 11095
Jun 10 05:45:25 db kernel: [11209156.840703] Node 0 Normal free:11428kB min:11548kB low:14432kB high:17320kB active_anon:10689464kB inactive_anon:19164kB active_file:528kB inactive_file:652kB unevictable:5456kB isolated(anon):0kB isolated(file):80kB present:11362176kB mlocked:5456kB dirty:292kB writeback:0kB mapped:4999580kB shmem:4997080kB slab_reclaimable:52920kB slab_unreclaimable:22048kB kernel_stack:2584kB pagetables:305432kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:1974 all_unreclaimable? yes
Jun 10 05:45:25 db kernel: [11209156.840715] lowmem_reserve[]: 0 0 0 0
Jun 10 05:45:25 db kernel: [11209156.840720] Node 0 DMA: 2*4kB 3*8kB 1*16kB 3*32kB 3*64kB 3*128kB 2*256kB 1*512kB 2*1024kB 2*2048kB 0*4096kB = 7888kB
Jun 10 05:45:25 db kernel: [11209156.840752] Node 0 DMA32: 5813*4kB 2636*8kB 114*16kB 15*32kB 5*64kB 1*128kB 1*256kB 0*512kB 1*1024kB 0*2048kB 0*4096kB = 48372kB
Jun 10 05:45:25 db kernel: [11209156.840776] Node 0 Normal: 1888*4kB 10*8kB 46*16kB 4*32kB 3*64kB 2*128kB 1*256kB 1*512kB 0*1024kB 1*2048kB 0*4096kB = 11760kB
Jun 10 05:45:25 db kernel: [11209156.840788] 1615243 total pagecache pages
Jun 10 05:45:25 db kernel: [11209156.840790] 0 pages in swap cache
Jun 10 05:45:25 db kernel: [11209156.840801] Swap cache stats: add 0, delete 0, find 0/0
Jun 10 05:45:25 db kernel: [11209156.840803] Free swap  = 0kB
Jun 10 05:45:25 db kernel: [11209156.840805] Total swap = 0kB
Jun 10 05:45:25 db kernel: [11209156.909794] 3934192 pages RAM
Jun 10 05:45:25 db kernel: [11209156.909804] 99282 pages reserved
Jun 10 05:45:25 db kernel: [11209156.909809] 18899146 pages shared
Jun 10 05:45:25 db kernel: [11209156.909811] 2198511 pages non-shared
Jun 10 05:45:25 db kernel: [11209156.909817] [ pid ]   uid  tgid total_vm      rss cpu oom_adj oom_score_adj name
Jun 10 05:45:25 db kernel: [11209156.909835] [  332]     0   332     4308      109   1       0             0 upstart-udev-br
Jun 10 05:45:25 db kernel: [11209156.909845] [  346]     0   346     5384      271   2     -17         -1000 udevd
Jun 10 05:45:25 db kernel: [11209156.909851] [  408]     0   408     5364      174   2     -17         -1000 udevd
...
Jun 10 05:45:25 db kernel: [11209156.910703] [ 7963]   111  7963    17456     2966   0       0             0 wal-e
Jun 10 05:45:25 db kernel: [11209156.910707] [ 7968]   111  7968  1639372     2351   3       0             0 postgres
Jun 10 05:45:25 db kernel: [11209156.910711] [ 7969]   111  7969  1639371     1934   2       0             0 postgres
Jun 10 05:45:25 db kernel: [11209156.910716] Out of memory: Kill process 12443 (postgres) score 418 or sacrifice child
Jun 10 05:45:25 db kernel: [11209156.910733] Killed process 12443 (postgres) total-vm:6555152kB, anon-rss:4600kB, file-rss:6396572kB
Jun 10 05:45:30 db kernel: [11209159.293083] postgres invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0, oom_score_adj=0
Jun 10 05:45:31 db kernel: [11209159.293091] postgres cpuset=/ mems_allowed=0
Jun 10 05:45:31 db kernel: [11209159.293095] Pid: 6508, comm: postgres Not tainted 3.2.0-43-virtual #68-Ubuntu
Jun 10 05:45:31 db kernel: [11209159.293098] Call Trace:
Jun 10 05:45:31 db kernel: [11209159.293111]  [<ffffffff81119711>] dump_header+0x91/0xe0
Jun 10 05:45:31 db kernel: [11209159.293115]  [<ffffffff81119a95>] oom_kill_process+0x85/0xb0
Jun 10 05:45:31 db kernel: [11209159.293119]  [<ffffffff81119e3a>] out_of_memory+0xfa/0x220
...

Możemy spróbować zwiększyć ich rozdzielczość do mniej więcej raz na sekundę, ale czy byłby tu jakiś powód do OOM? (Widzieliśmy http://bl0rg.krunch.be/oom-frag.html, ale pracujemy z dużo większymi bezwzględnymi ilościami pamięci, z których większość jest pobierana przez pamięć podręczną FS jądra.)

W tym także odpowiednie części naszego postgresql.confponiżej:

shared_buffers = 6GB
effective_cache_size = 8GB
Yang
źródło
Um ... 3.2.0-43? Czas aktualizacji. Zabójca OOM przeszedł wiele (zbyt wiele) zmian w czasie. Niektóre wersje były naprawdę dość bezmyślne, jeśli chodzi o rozliczanie wykorzystania pamięci współdzielonej ... jak PostgreSQL 9.2 i starsze shared_buffers.
Craig Ringer
@CraigRinger Niestety istnieją inne względy, takie jak trzymanie się jądra w dystrybucji Ubuntu 12.04 dla LTS, kompatybilność, aktualizacje zabezpieczeń itp. Jesteśmy tylko zainteresowani, jeśli ktoś wie, jak wyjaśnić, co się tutaj dzieje - jeśli to pomaga, udawaj, że jesteśmy nie jestem zainteresowany zmianą status quo / rozwiązaniem problemu. BTW shared_buffersjest nadal w wersji PG9.3.
Yang,
Tak, shared_bufferswciąż jest w wersji 9.3, ale nie jest już pamięcią współdzieloną POSIX w wersji 9.3. Został zastąpiony anonimowym mmap()edregionem. To omija niektóre kłopotliwe problemy z konfiguracją jądra i problemy z przypinaniem, choć wątpię, by to sprawiło, że zabójca OOM byłby mniej zdezorientowany.
Craig Ringer
1
Prawdopodobnie duplikat serverfault.com/questions/288319/… , który ma potencjalną odpowiedź.
richvdh

Odpowiedzi:

4

Wygląda na to, że ty (i ja w przypadku bardzo podobnych objawów) naprawdę zabrakło pamięci i zostałeś zdezorientowany cachedliczbą.

Najwyraźniej zdarzają się przypadki, gdy Linux nie zwalnia pamięci podręcznej dużego dysku, gdy zapotrzebowanie na pamięć rośnie

W szczególności (naprawdę nie rozumiem dlaczego) postgresy shared_buffersmogą być zgłaszane pod „Cache” (pamięć podręczna strony). W twoim przypadku 6481852k cachedin toppasuje do tej linii w dzienniku zabójcy OOM:

Jun 10 05:45:25 db kernel: [11209156.840788] 1615243 total pagecache pages

(1615243 * 4KB ~ = 6481852k) - co oznacza, że ​​pamięć podręczna strony rzeczywiście nie została upuszczona przed wywołaniem OOM-killera.

Istnieje jednak kilka stron z active_file:98 inactive_file:168kopiami plików (zakładam, że jest podobny do Active (file) / Inactive (file) / proc / meminfo ), więc nie są to strony, które znamy i lubimy.

Post na https://www.depesz.com/2012/06/09/how-much-ram-is-postgresql-using/ pokazuje przykładową sesję, w której zamknięcie postgres prowadzi do zmniejszenia „buforowanej” wielkości shared_buffers(przewiń do „I większość z niego pochodzi z bufora dysku - zgodnie z oczekiwaniami, ponieważ został użyty do shared_buffers.” ) - niestety nie wskazuje wersji postgres ani jądra, które zostało użyte w eksperymencie.

Używam 3.13.0-67 x86_64 z PG 9.3. W 9.3 przestawili się z korzystania z pamięci współużytkowanej Sys V ( shmget) na anonimowąmmap(...R+W, MAP_SHARED|MAP_ANONYMOUS|MAP_HASSEMAPHORE...)+fork() (w 9.4 stało się to konfigurowalne za pomocą typu dynamic_shared_memory_type ). Ale nie mogłem znaleźć żadnego wyjaśnienia, dlaczego te mmap () mają się pojawiać w „buforowanym” i dlaczego, tylko https://access.redhat.com/solutions/406773, który mówi „Cached: Memory in the pagecache (Diskcache and Shared Memory) ”

Biorąc pod uwagę, że istnieje wiele rodzajów wspólnej pamięci , jestem zarówno oświecony, jak i zdezorientowany ...

Nickolay
źródło
Po kilku latach jest to znacznie lepsza odpowiedź, dziękuję. Nadal jest pytanie, dlaczego jest to traktowane jako buforowane, ale zaznaczam to na razie.
Yang
8
  1. Z miłości do wszystkiego, co dobre na świecie, skonfiguruj przestrzeń wymiany na swoich serwerach .
    Naprawdę potrzebujesz przestrzeni wymiany . Nie jestem jedynym, który tak mówi , tutaj jest to uniwersalna prawda . (<- To są trzy linki)
    Oczywiście powinieneś mieć wystarczającą ilość pamięci RAM, aby serwer bazy danych nie zamieniał się regularnie - jeśli nie, rozwiązaniem są pieniądze (które zabierasz dostawcy i używasz, aby uzyskać więcej pamięci RAM) .

  2. Ponieważ masz teraz wystarczającą ilość pamięci RAM i możesz zamienić ją, jeśli coś pójdzie nie tak, możesz wyłączyć zabójcę OOM (poprzez wyłączenie nadpisywania pamięci), tak jak nakazują ci Postgres .
    (Możesz również zastosować ich alternatywne rozwiązanie i powiedzieć OOM-Killerowi, aby nigdy nie zabijał Postgresa - ale wtedy grasz w Rosyjską Ruletkę z resztą procesów twojego systemu ...)

  3. (opcjonalnie) Napisz odpowiedź na temat błędu serwera, wyjaśniając, dlaczego domyślne zachowanie w większości dystrybucji Linuksa jest Złe, Złe i narusza specyfikację POSIX dotyczącą tego, jak ma zachowywać się malloc () . Powtarzaj tę czynność, aż wszyscy będą mieli dość tego słuchania.


Zauważ też, że pamięć podręczna jądra jest dostępna dla postgres (lub dowolnej innej aplikacji) do użycia - powinieneś uwzględnić ją w swoich obliczeniach jako wolną / dostępną pamięć.

Gdybym musiał zaryzykować odgadnięcie, co się tutaj dzieje, powiedziałbym, że masz złożone zapytanie, Postgres prosi o pamięć RAM, aby je wykonać, a zamiast „Nie mam takiej pamięci RAM”, Linux mówi Postgresowi „Jasne, możesz to mieć. ”
Potem, gdy Postgres rzeczywiście próbuje użyć pamięci RAM to było (rzekomo) podane Linux zdaje sobie sprawę, że nie MIEĆ RAM to obiecane Postgresa (bo to overcommitted) - zabójca OOM dowiaduje się, aby zwolnić pamięć RAM i sumiennie zabija program za pomocą najwięcej pamięci - serwer bazy danych.

Postgres to dobrze zaprojektowany program. Jeśli powie, że nie może mieć pamięci RAM, o którą prosi, poradzi sobie z tym z wdziękiem (albo robiąc mniej, albo przerywając wiadomość dla użytkownika).

voretaq7
źródło
4
Dzięki za opracowanie na temat zamiany, ale to nie odpowiada na moje pytanie, dlaczego tak się dzieje . Tak, rozumiem podstawową zasadę, że Linux domyślnie przesadza i że OOM ma miejsce, gdy brakuje nam pamięci RAM - mogłem to powiedzieć w moim pierwotnym pytaniu. Ale pytanie brzmi: dlaczego się uruchamia, gdy wciąż mam dużo pamięci RAM (większość po prostu siedzi w pamięci podręcznej FS)? Załóżmy, że nawet nie jestem zainteresowany zmianą - że zabójca OOM jest w porządku, o ile rozumiem, dlaczego jest uruchamiany.
Yang,
2
Po przejrzeniu linków istnieje niestety szereg twierdzeń bez poparcia dowodów lub konkretnych wyjaśnień technicznych. Z pewnością istnieje wiele środowisk Linux, w których zamiana nie jest nawet opcją (przykład: nie szukaj dalej niż Live CD, na którym nie ma już lokalnej partycji wymiany do ponownego użycia). Ponadto nie jesteśmy zainteresowani umożliwieniem wymiany w oparciu o własne doświadczenia i środowisko - wolelibyśmy mieć OOM. Odpowiedź na pierwotne pytanie będzie mile widziana.
Yang,
1
@Yang Zakładam, że jeśli budujesz serwer dla Postgres, chciałbyś postępować zgodnie z zaleceniami projektu Postgres. Moja odpowiedź brzmi: rób to, co ci mówią (wyłącz zabójcę OOM). Jeśli chcesz poczekać i sprawdzić, czy ktoś oferuje inną odpowiedź, z pewnością możesz to zrobić, ale nie czuję się komfortowo oferując inne rozwiązanie - Moim zdaniem zabójca OOM jest zły, niewłaściwy i narusza POSIX. Może to być akceptowalne na komputerze / stacji roboczej, ale wyłączenie go na serwerach jest, IMO, właściwą rzeczą do zrobienia.
voretaq7
2
Natknąłem się na tę sytuację na serwerze, który ma zamianę, a po nasyceniu dostępnej pamięci + zamiany użyto zabójcy OOM zamiast jądra odzyskującego pamięć „buforowaną”, która oczywiście została w jakiś sposób zablokowana. Nigdy nie rozwiązałem problemu, ale tutaj nie ma odpowiedzi na pierwotne pytanie @ Yang.
Patrick,
2
Zamiana nie jest odpowiedzią, powoduje tylko, że problem pojawia się później. Potrzebujesz wymiany, gdy pamięć RAM jest pełna i potrzebujesz OOM Killer, gdy pamięć RAM + zamiana się zapełni. Jeśli ilość zamiany wynosi zero, potrzebujesz OOM Killera wcześniej, ale nie możesz uniknąć OOM Killera podczas swapu.
Mikko Rantalainen,