OOM Killerとは、Linuxでメモリが枯渇したときに召喚される死神です。OOM Killerが召喚されると、重要度が低いプロセスの中で、メモリを多く消費しているプロセスが殺されます。重要度は、プロセス毎に指定されているoom_score_adjという値によって決まり、小さな物ほど重要なプロセスとして扱われます。oom_score_adjのデフォルト値は0で、-1000から1000の値をとります。sshdなどの重要なプロセスは-1000が指定されているため殺されません。
以下のスクリプトを実行すると、oom_score_adjが0以外のプロセスを表示します。
for dir in /proc/[0-9]*; do
if [ "`cat $dir/oom_score_adj`" != 0 ]; then
echo "`cat $dir/comm` : `cat $dir/oom_score_adj`"
fi
done | sort | uniq
if [ "`cat $dir/oom_score_adj`" != 0 ]; then
echo "`cat $dir/comm` : `cat $dir/oom_score_adj`"
fi
done | sort | uniq
私の環境では以下のようなプロセスが0以外に設定されていました。
auditd : -1000
sshd : -1000
udevd : -1000
sshd : -1000
udevd : -1000
この環境で、mysqldの優先度を上げてみます。(Apacheがメモリを食ったときにmysqldが殺されるとヤッカイなことになります。Apacheはどんどんプロセスを作っているので殺されてもあまり問題ないですが、mysqldが殺されると死んだままになります)
mysqldの優先度を、手動で毎回書き換えるのは現実的ではないので、init.dにあるmysqldの起動スクリプトを書き換えました。
/etc/init.d/mysqld
if [ $ret -eq 0 ]; then
action $"Starting $prog: " /bin/true
touch $lockfile
echo '-100' > "/proc/`cat $mypidfile`/oom_score_adj"
else
action $"Starting $prog: " /bin/false
fi
action $"Starting $prog: " /bin/true
touch $lockfile
echo '-100' > "/proc/`cat $mypidfile`/oom_score_adj"
else
action $"Starting $prog: " /bin/false
fi
mysqldを再起動し、プロセスの優先度を確認すると、以下のようになっていました。
auditd : -1000
mysqld : -100
sshd : -1000
udevd : -1000
mysqld : -100
sshd : -1000
udevd : -1000
これでhttpdがメモリを食った結果、mysqldが殺されるということは防げそうです。