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()が使われるようになる。
個人用ツール