アドウェイズエンジニアの波切です、こんにちは。
すでにタイトルでネタばれしちゃってますが、
最近はまったMySQLのトラブルで、WebからMySQLへの接続で、
「Can't create a new thread (errno 11)」
というエラーが出るという問題があったので、それについて書こうかと思います。
上記のエラーについてググってみたところ、
http://mysqlpracticewiki.com/index.php/Can%27t_create_a_new_thread_%28errno_11%29
スレッドの作成に失敗した時に発生するエラーで
メモリが足りなくなったか、もしくはスレッドの作成数の限界に達したという問題でした。
そこで、どちらが問題になったのかを切り分けるため、Cactiを見てみることにしました。
まずは、Cacti!!
Cactiを見てみると、メモリに関してはスワップを使っている様子もなく
問題なさそう。
MySQLへの接続数を見てみると、エラーが発生した前後でスレッド数が
跳ね上がっている様子が見られました。
そこで、疑わしいOSのスレッド数の限界値についてを調べてみることにしました。
OSの制限値の見方、Linuxのスレッド数の制限はどうなってるの?
まずは、問題となっているMySQLのプロセスにかけられている制限値を、
下記のコマンドで確認してみます。
cat /proc/`pidof mysqld`/limits
すると、
Max Processes のSoft limit値が1024に制限されているようです。
これは、怪しい!
MySQLは、コネクションごとにスレッドを作るため、
Max Processesの制限値がプロセスだけではなく、スレッド数にも影響を与えるとすると、
この制限に引っかかったのではないかと、推測されます。
そこで、下記のような何も行わないLinuxのスレッド&プロセスを作るサンプルプログラムを
作って、Max Processesの限界値付近で、どんな挙動をするのか検証を行ってみます。
すると、
↑こんな感じになりました。
Max processes近辺で問題のerrno=11が出ちゃってますね。
また、MaxProcessは、プロセス数だけではなく、プロセス数+スレッド数の合計に対しての
制限値であるらしいと分かりました。
CentOS 6系のスレッドの上限値に注意!
ここまで調べて、CentOSのバージョン6.0からMax Processesがデフォルトで
1024に制限されていたという事実に気づかされました。やられた…。
普段、OSの制限値を意識する機会は、あまりないため、
CentOS6系でサーバの同時接続数を多く設定している場合は、要注意です!!。
[CentOS6で制限されているプロセス最大数を制限解除する]
http://d.hatena.ne.jp/akuwano/20120413/1334312849
[ulimitが効かない不安を無くす設定]
http://blog.father.gedow.net/2012/08/08/ulimit-configuration/
対応方法
MySQLの起動ファイルの先頭に、下記の記述を加え、
ulimit -u 4096
デーモンの再起動を行うことで無事対応を終えました。
みなさんも同じ罠にハマらないようにご注意を…。
[今回のソース]
https://github.com/fugafigs/linux_thread_test