Help us understand the problem. What is going on with this article?

MySQL でメモリ不足が発生したときのパラメータチューニング

More than 1 year has passed since last update.
$ mysql
Can't create a new thread (errno 11); if you are not out of available memory, you can consult the manual for a possible OS-dependent bug

上記のエラーが発生して MySQL に接続できなくなった場合、MySQL がメモリ不足となっている可能性があります。

メモリ使用量の計算

MySQL のメモリ使用量は、以下のような計算式で調べることができます。

メモリ使用量 = グローバルバッファ + (スレッドバッファ * コネクション数)

このメモリ使用量が物理メモリサイズを超えると、メモリ不足が発生する可能性が高まるので、
物理メモリサイズを超えないように、バッファサイズとコネクション数を調整します。

グローバルバッファの設定

MySQL のバッファには、グローバルとスレッドの2種類があります。

グローバルバッファは MySQL 全体で1つ確保されます。
グローバルバッファサイズに関連するパラメータは下記のとおりです。

  • key_buffer_size
    • MyISAM で使用するバッファサイズ
    • MyISAM を利用してなければ小さくてもOK
  • innodb_buffer_pool_size
    • InnoDB で使用するバッファサイズ
    • 搭載メモリの80%程度
  • innodb_log_buffer_size
    • InnoDB で使用するログバッファサイズ
    • innodb_buffer_pool_sizeの25%程度(最大でも64MB)
  • net_buffer_length
    • 送受信するパケットを格納するパケットメッセージバッファサイズの初期値

スレッドバッファの設定

スレッドバッファはスレッド (コネクション) 毎に確保されます。
スレッドバッファに多くのメモリを割り当てると、コネクションが増えた際にすぐメモリ不足になってしまうので注意が必要です。
スレッドバッファサイズに関連するパラメータは下記のとおりです。

  • sort_buffer_size
    • ソート処理に利用される
  • read_buffer_size
    • インデックスを使わないテーブルフルスキャン時に利用される
  • read_rnd_buffer_size
    • インデックスを利用したソートに利用される
  • join_buffer_size
    • インデックスを使わない結合に利用される
  • myisam_sort_buffer_size
    • MyISAM テーブルのインデックス作成に利用される

コネクション数

  • max_connections
    • 最大コネクション数

確認方法

以上を踏まえた計算式で、現在の設定を確認するクエリがこちらになります。

mysql> select
  @@global.key_buffer_size + @@global.innodb_buffer_pool_size + @@global.innodb_log_buffer_size + @@global.net_buffer_length as global_buffer_size,
  @@global.sort_buffer_size + @@global.myisam_sort_buffer_size + @@global.read_buffer_size + @@global.join_buffer_size + @@global.read_rnd_buffer_size as thread_buffer_size,
  @@global.key_buffer_size + @@global.innodb_buffer_pool_size + @@global.innodb_log_buffer_size + @@global.net_buffer_length
  + (@@global.sort_buffer_size + @@global.myisam_sort_buffer_size + @@global.read_buffer_size + @@global.join_buffer_size + @@global.read_rnd_buffer_size) * @@global.max_connections as total_memory_size;
+--------------------+--------------------+-------------------+
| global_buffer_size | thread_buffer_size | total_memory_size |
+--------------------+--------------------+-------------------+
|          159399936 |            9306112 |        1564622848 |
+--------------------+--------------------+-------------------+
1 row in set (0.00 sec)

この場合、total_memory_size は 1564622848 / (1024 * 1024 * 1024) で約 1.45 GB となります。
例えば RDS の db.t2.micro だと、物理メモリサイズは 1 GiB = 1073741824 bytes で約 1.07 GB であるため、最大コネクション数までコネクションが増えた場合にメモリ不足になる可能性が高くなります。

参考

gaiax
人と人をつなげる Empowering the people to connect.
http://www.gaiax.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away