MySQL client ran out of memory
提供:MySQL Practice Wiki
エラー概要
| MySQLエラー番号 | 2008 |
| SQLSTATE | N/A |
| エラー名 | CR_OUT_OF_MEMORY |
| メッセージ | MySQL client ran out of memory |
| 障害部位 | libmysqlclient, Connector/J |
| 該当バージョン | any |
| エラーの原因 | 下記参照。 |
| 対策 | 下記参照。 |
| 備考 |
説明
クライアント側でメモリを使い切ってしまった時にこのエラーが出力される。クエリを発行した後にデフォルトではサーバーから結果セットが全てクライアントに送られて、クライアントのメモリ上に保持される。膨大な数の行を取り出すクエリ、例えば大きなテーブルのスキャンやテーブルスキャンを伴うJOINなどを行った場合には、結果セットが膨大なサイズとなる。膨大なサイズの結果セットを保持するには膨大なメモリが必要となり、特に32ビット環境ではこのエラーに陥りやすい。
対策
まずは上記のようなクエリを行わないようにしよう。以下のことに注意して、クエリの変更を検討しよう。
- 本当にそれだけの行が必要か?
- もしアプリケーション側で利用しない行までSELECTしているようであれば、WHEREやHAVINGを使って不要な行をSELECTしないようにすること。選択された内容に従って、アプリケーション側のコードで何らかの判定を行うようなことは避ける。
- 不必要なカラムを含んではいないか?
- SELECT * などのようにしてはいけない。必要なカラムだけを選択するようにすれば、クライアントのメモリだけでなくネットワークの帯域も節約することが出来る。
- LIMITの利用
- もしどうしてもたくさんの行が必要なのであれば、LIMIT節を用いて反復を行うようにしよう。範囲検索を行う時には必ずLIMIT節の使用を検討されたい。
どうしてもアプリケーションのコードを変更出来ない場合は、次の対策を検討して欲しい。ただしいずれの対策も性能の劣化が起きてしまうので注意すること。
- JDBC
- 接続オプションでuseCursorFetchとdefaultFetchSizeを指定しよう。そうすることによりdefaultFetchSizeで指定された行数だけしかクライアント側に保持されないようになる。後からsetFetchSize()を使って行数を変更することも可能だ。
- ODBC
- WindowsならコントロールパネルからODBCの設定で「Don't Cache Result (forward only cursors)」オプションを指定しよう。そうするとODBCから呼び出されるMySQLのクライアントライブラリが内部的にmysql_store_result()ではなくmysql_use_result()を使用するようになる。
- mysql CLI/PHP/Perl
- my.cnfの[client]セクションにおいてquickオプションを指定しよう。またはCLIであればコマンドラインオプションで--quickを指定しても良い。そうすることでmysql_store_result()ではなくmysql_use_result()が使われるようになる。