[MySQL][Rails] Lost connection to MySQL server during query
こんにちわ。ばたっちです。
Railsのユニットテスト中にタイトルのエラーが出ることがあります。
調べてみたら、結構話題になってるみたいですね。
http://d.hatena.ne.jp/Rommy/20070814/p1
http://idm.s9.xrea.com/ratio/2006/04/08/000406.html
ユニットテストのエラーを見てると、
「Message: ActiveRecord::StatementInvalid: Mysql::Error: Lost connection to MySQL server during query」
と、
「Message: Errno::ECONNREFUSED: Connection refused - /tmp/mysql.sock」
が交互に出ている。
DB接続が切断(mysqld再起動?)→DB接続失敗を繰り返しているみたいですね。
MySQLのマニュアルを見てみると、どうやら MySQLクライアント―サーバ間で大きなサイズの
パケットが送られると接続が切れるそうです。
MySQL 4.1 リファレンスマニュアル :: A.2.9. Packet too large エラー
http://dev.mysql.com/doc/refman/4.1/ja/packet-too-large.html
my.cnfの [mysqld]セクションの max_allowed_packet を 1M→16Mに変更してみたらビンゴ。
[mysqld] : max_allowed_packet = 16M :
/etc/init.d/mysql restart でMySQL再起動したら、ユニットテストが通るようになりました。
よかったよかった。A^^;
(追記)
一時的にうまくいっていたようで問題が再発。。orz
mysqld.logを見てみると「mysqld got signal 11」が始まるログが吐かれていて、
thd->query at 0xXXXXXXXX = DELETE FROM table1
というように、DELETE文実行時にエラーになっている模様。
MySQL+Senna(Tritonn)の全文検索を使っているのですが、下記のバージョンで修正された
「条件無しdeleteを実行するとインデックスのフラグ情報が欠けてしまう問題」というのが怪しそう。
http://qwik.jp/tritonn/ChangeLog.html#mysql-5_0_45-tritonn-1_0_7
MySQLのバージョンは変更できないので、条件なしDELETEにならない方法を考えることにしました。
エラーが発生しているのはユニットテストで、FULLTEXT INDEXを設定したテーブルに対する fixtureのロード中。
なので、test_helper.rbで fixtureロード中の DELETE文で WHERE句を追加するようにしてみました。
test/test_helper.rb ---- +class Fixtures < YAML::Omap + FULLTEXT_TABLES = ["table1"] + def delete_existing_fixtures + where = (FULLTEXT_TABLES.include?(@table_name)) ? "WHERE id>0" : "" + @connection.delete "DELETE FROM #{@table_name} #{where}", 'Fixture Delete' + end +end
ファイルの最後に追加すればOKです。
FULLTEXT_TABLESに FULLTEXT INDEXを設定してあるテーブルを追加すれば、DELETE文に「WHERE id>0」を挿入します。
idフィールドがない(Railsで作ったテーブルなら通常はありますが)場合は、ここでテーブル毎の SQLを作るようにします。
(ちなみに「WHERE 1=1」みたいなのはダメみたい)
これでユニットテストのエラーが発生しなくなりました♪(^^)v