読者です 読者をやめる 読者になる 読者になる

Studio3104::BLOG.new

uninitialized constant Studio3104 (NameError)

mysqldのファイルディスクリプタ数


新規のMySQLサーバの設定をしていて、弊社に伝わる秘伝のタレ的なマニュアルを見ていたらこんな記述があった。

/etc/security/limits.conf編集
 以下を追記
 「* soft nofile 8000」
 「* soft nofile 8000」

コレって意味あるのかなぁとふと思ったので調べてみましたのでまとめ。
(ほとんど教えてもらった。@++ @++ @++ @++)
結論から言うと、rootがmysqld_safeでmysqldを起動させる場合は意味をなさないということがわかりました。
もうこのマニュアルは捨てちゃおうと思いました。ひどい!

※本エントリは、MySQL5.5(InnoDB)、CentOS5.8環境下において検証しております。お使いの環境によってはオプション名などがそのまま当てはまらないことがありますのでご注意ください。

ファイルディスクリプタ

ファイルディスクリプタとは、OSがファイルに入出力を行うための識別子です。

linuxにおいて、ファイルディスクリプタに関する設定項目は2つ。(数字はサンプルです)

システム全体で同時に扱えるファイルディスクリプタ数の設定。変更するには以下のいずれかの方法で。

・/proc/sys/fs/file-max の値を書き換える
・/etc/sysctl.conf に 'fs.file-max = 10000' などと追記し、sysctl -p で反映

1つのプロセスが同時に扱えるファイルディスクリプタ数の設定。変更するには以下のいずれかの方法で。

・ulimit -n で一時的に設定
・limits.conf に設定を記述(反映はpam認証時)

他にもカーネルのリビルドなどによって設定を変更することも出来ますが、日常的な運用でそういった変更はあまりしないので割愛。

limits.conf

limits.confにはどのユーザがどれだけのファイルディスクリプタ数を同時に扱えるかということを記述します。
しかし、limits.confの記述内容は、PAM認証を経由する場合にのみ適用されます。
ttyを持たないsystemユーザの権限で動作するデーモンプロセスに適用させるためには別にいくつかの設定をする必要があります。
参考: ulimitが効かない不安を無くす設定 | 外道父の匠

mysqld起動時の挙動

my.cnfに以下のような設定をしておくと、mysqld起動時に、mysqldが扱えるファイルディスクリプタ数の上限が8192に設定されます。

[mysqld_safe]
open_files_limit = 8192

rootがmysqld_safe経由でmysqldを起動する場合、mysqld_safeがmy.cnfを読んでulimit -n するためにこのようになります。
よって、冒頭で述べたとおりlimits.confへの設定は無意味なのです。

mysqldの扱うファイルディスクリプタ

では、my.cnfにこのように記述されていたとしたら、mysqldの扱えるファイルディスクリプタ数はどのようになるでしょうか。

max_connections = 1800
table_open_cache = 256

[mysqld_safe]
open_files_limit = 8192

open_files_limit = 8192 となっているので、8192になりそうですが、この場合は9000になります。

open_files_limitの最終的な値は、以下の3つのうちで1番大きな値が選択されます。※()は例のmy.cnfの値を当てはめた場合

  • open_files_limit (8192)
  • max_connections * 5 (9000)
  • table_open_cache * 2 + max_connections + 10 (2322)

よって、9000となります。

注意点

稼働中にmax_connectionsを変更した場合

WEBサーバのスケールアウトなどで、「too many connections」エラーが出てしまった場合、メモリなどに余裕があればmax_connectionsを増やしてみるなどすることもあると思います。

前項のmy.cnfを喰って起動しているMySQLサーバでこういうオペレーションをしたとします。
max_connectionsを増やしていますが、(起動時に設定されるので当然ですが)open_files_limitの値は増えません。
コネクション数の上限をオンラインで変更する際は、スレッドバッファの他にもこういうところに注意しないと、今度は「Too many open files」が発生してしまうこともあるかも知れません。

root@db01 Mst_(none) >show global variables like  "open_files_limit";
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| open_files_limit | 9000  |
+------------------+-------+
1 row in set (0.00 sec)

root@db01 Mst_(none) >show global variables like  "max_connections";
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 1800  |
+-----------------+-------+
1 row in set (0.00 sec)

root@db01 Mst_(none) >set global max_connections = 2000;
Query OK, 0 rows affected (0.00 sec)

root@db01 Mst_(none) >show global variables like  "max_connections";
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 2000  |
+-----------------+-------+
1 row in set (0.00 sec)

root@db01 Mst_(none) >show global variables like  "open_files_limit";
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| open_files_limit | 9000  |
+------------------+-------+
1 row in set (0.00 sec)

root@db01 Mst_(none) >

limits.confの影響を受ける場合

mysqld_safeを経由せず、daemontoolsなどを用いて起動させる場合はこのlimits.confの影響を受ける場合もあるそうです。

open_files_limit = 8192

色々なところでopen_files_limit = 8192という設定例を見かけますが、この数値の根拠はなんなんでしょう?わかる方教えてくださいい><
これが起源では?という情報もいただきましたが根拠がよくわかりません。

ちなみに、HandlerSocketのサンプル設定ファイルでは、上限の65535を推奨していますね。