web-dev-qa-db-ja.com

OOM Killer-MySQLサーバーを強制終了

私たちのMySQLマスターの1つで、OOM Killerが呼び出され、MySQLサーバーを停止したため、大規模な障害が発生しました。カーネルログは次のとおりです。

[2006013.230723] mysqld invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0
[2006013.230733] Pid: 1319, comm: mysqld Tainted: P           2.6.32-5-AMD64 #1
[2006013.230735] Call Trace:
[2006013.230744]  [<ffffffff810b6708>] ? oom_kill_process+0x7f/0x23f
[2006013.230750]  [<ffffffff8106bde2>] ? timekeeping_get_ns+0xe/0x2e
[2006013.230754]  [<ffffffff810b6c2c>] ? __out_of_memory+0x12a/0x141
[2006013.230757]  [<ffffffff810b6d83>] ? out_of_memory+0x140/0x172
[2006013.230762]  [<ffffffff810baae8>] ? __alloc_pages_nodemask+0x4ec/0x5fc
[2006013.230768]  [<ffffffff812fca02>] ? io_schedule+0x93/0xb7
[2006013.230773]  [<ffffffff810bc051>] ? __do_page_cache_readahead+0x9b/0x1b4
[2006013.230778]  [<ffffffff810652f8>] ? wake_bit_function+0x0/0x23
[2006013.230782]  [<ffffffff810bc186>] ? ra_submit+0x1c/0x20
[2006013.230785]  [<ffffffff810b4e53>] ? filemap_fault+0x17d/0x2f6
[2006013.230790]  [<ffffffff810cae1e>] ? __do_fault+0x54/0x3c3
[2006013.230794]  [<ffffffff812fce29>] ? __wait_on_bit_lock+0x76/0x84
[2006013.230798]  [<ffffffff810cd172>] ? handle_mm_fault+0x3b8/0x80f
[2006013.230803]  [<ffffffff8103a9a0>] ? pick_next_task+0x21/0x3c
[2006013.230808]  [<ffffffff810168ba>] ? sched_clock+0x5/0x8
[2006013.230813]  [<ffffffff81300186>] ? do_page_fault+0x2e0/0x2fc
[2006013.230817]  [<ffffffff812fe025>] ? page_fault+0x25/0x30

このマシンには64 GBのRAMが搭載されています。

Mysql構成変数は次のとおりです。

innodb_buffer_pool_size        = 48G
innodb_additional_mem_pool_size = 512M
innodb_log_buffer_size         = 64M

Nagiosプラグインとメトリックコレクションスクリプトの一部を除いて、このマシンでは他に何も実行されません。誰かが私にOOMキラーが呼び出された理由と、今後呼び出されるのを防ぐ方法を見つけるのを手伝ってくれませんか? mysqlサーバーを殺さないようにOOMキラーに指示できる方法はありますか? oom_adj値を非常に小さくして、プロセスがOOMキラーによって強制終了されるのを防ぎます。しかし、これを防ぐ他の方法はありますか?.

10
pradeepchhetri

Linuxはメモリのオーバーコミットを行います。つまり、プロセスがシステムで実際に利用可能なメモリよりも多くのメモリを要求できるようになります。プログラムがmalloc()を試行すると、カーネルは「OKメモリを取得しました」と言いますが、予約しないでください。メモリは、プロセスがこのスペースに何かを書き込むときにのみ予約されます。

違いを確認するには、仮想メモリと常駐メモリの2つのインジケータがあります。仮想はプロセスが要求するメモリであり、常駐はプロセスが実際に使用するメモリです。

このシステムでは、「オーバーブッキング」に入る可能性があり、カーネルは利用可能なメモリより多くのメモリを許可します。次に、システムが0バイトの空きメモリとスワップを実行するとき、空きメモリを得るためにプロセスを犠牲(kill)にする必要があります。

それがOOM Killerが行動を起こすときです。 OOMは、彼のメモリ消費と他の多くの要素に基づいてプロセスを選択します(親は子供のスコアの1/2を獲得します。それがルート所有プロセスの場合、スコアは4で除算されます。など)。 Linux-MM.org/OOM_Killer

/proc/MySQL_PID/oom_adjファイルを調整することで、OOMスコアに影響を与えることができます。 -17に設定すると、プロセスが強制終了されることはありません。しかし、それを行う前にMySQL構成ファイルを調整する必要があります MySQLのメモリ使用量を制限します。そうしないと、OOMキラーが他のシステムプロセス(SSH、crontabなど)を強制終了し、サーバーが非常に不安定な状態になり、おそらくデータの破損何よりも悪い。

また、より多くのスワップの使用を検討することもできます。

[編集]

これらの2つのsysctlを使用して、オーバーコミット動作を変更することもできます。

vm.overcommit_memory
vm.overcommit_ratio

Kernel Documentation で述べたように

overcommit_memory:

この値には、メモリのオーバーコミットを有効にするフラグが含まれています。

このフラグが0の場合、カーネルは、ユーザー空間がより多くのメモリを要求したときに残っている空きメモリの量を推定しようとします。

このフラグが1の場合、カーネルは、実際にメモリが不足するまで、常に十分なメモリがあるように見せかけます。

このフラグが2の場合、カーネルはメモリのオーバーコミットを防止しようとする「決してオーバーコミットしない」ポリシーを使用します。 user_reserve_kbytesがこのポリシーに影響することに注意してください。

この機能は、大量のメモリを「ジャストインケース」でmalloc()して多く使用しないプログラムが多数あるため、非常に役立ちます。

デフォルト値は0です。

詳細については、Documentation/vm/overcommit-accountingおよびsecurity/commoncap.c :: cap_vm_enough_memory()を参照してください。

overcommit_ratio:

Overcommit_memoryが2に設定されている場合、コミットされたアドレススペースは、スワップとこの割合の物理RAMを超えることはできません。上記を参照。

[/編集]

25
Adrien M.