PostgreSQLを作るときはOOM Killer対策が必要

カーネルは、他のプロセスのメモリ要求がシステムの仮想メモリを枯渇させた場合、PostgreSQLを終了させる可能性がある。
カーネルメッセージ:Out of Memory: Killed process 12345 (postgres).

OOM Killer(Out Of Memory Killer)によって、PostgreSQLが殺されている。

【対策その1】

  • vm.overcommit_memory
    大量メモリの要求を受け入れるか拒否するかを決定する条件。

    0 デフォルト設定。オーバーコミット有効。
    カーネルがメモリの空き容量を概算し、明らかに無効な要求を失敗させることで、ヒューリスティックなメモリオーバーコミット処理を実行する。メモリは厳密なアルゴリズムではなくヒューリスティックなアルゴリズムを使用して割り当てられるため、この設定でシステム上のメモリの空き容量がオーバーロードとなる場合がある。
    1 常にオーバーコミット可能。
    メモリを使い切るまでは十分なメモリがあるように振る舞う。メモリのオーバーロードの可能性が高くなるが、メモリ集約型のタスクのパフォーマンスも向上する。
    2 オーバーコミット無効。
    メモリをオーバーコミットさせないようにし、OOM Killerの発生頻度を軽減する。
    カーネルは、利用可能なスワップとovercommit_ratioで指定されている物理RAMの割合の合計とメモリが同等もしくはそれよりも大きい場合の要求を拒否する。メモリのオーバーコミットのリスクを減らしたい場合は、この設定が最適。
  • vm.overcommit_ratio
    overcommit_memoryが2に設定されている場合に考慮される物理RAMの割合を指定する。デフォルト値は50なので、搭載メモリの半分までしか確保できない。
    malloc_limit[MB] = swapサイズ[MB] + (物理メモリサイズ[MB] * overcommit_ratio / 100)

【対策その2】
postgresの起動スクリプトを作り、pg_ctl start,restartの直前に

  • oom_score_adj
    vm.overcommit_memoryの変更と関係ないが、vm.overcommit_memoryの設定では完全にOOM Killerを防げないので、OOM Killerの対象とならないように設定する。
    /proc/postgresのPID/oom_score_adjを-1000にする必要があるが、起動スクリプト内でPIDにselfを指定して、自らoom_score_adjを設定する。

参考
https://www.postgresql.jp/document/9.2/html/kernel-resources.html
http://dbnote.web.fc2.com/note_install_06_oomkiller.html
https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Performance_Tuning_Guide/s-memory-captun.html

-PostgreSQL