MySQL server has gone away

ステージング環境の挙動がおかしいので調べてみると、"MySQL server has gone away"というエラーが発生していました。どうやらクローズされたコネクション上でクエリを実行しようとすると、このエラーが発生するようです。もう少し詳しく調べてみました。

A.2.2. MySQL server has gone away エラー


このセクションでは、関連する Lost connection to server during query エラーもカバーしています。

MySQL server has gone away エラーの最も一般的な原因は、サーバがタイムアウトして接続がクローズしたことです。デフォルトでは、何も起きない状態が 8 時間続くと、サーバは接続をクローズします。この時間は、mysqld 開始時に wait_timeout 変数を設定することで変更できます。

MySQL server has gone away エラーが発生する一般的なもう一つの原因としては、MySQL とのコネクション上で ``close'' を発行し、クローズしたコネクションでクエリを実行しようとしたことが考えられます。

スクリプトがある場合は、クライアントが自動再接続を実行するためのクエリを再発行するだけで解決します。

今回は夜のうちにサーバーがタイムアウトして、コネクションがクローズされたと思われます。解決策として、mysql_retry_lost_connectionというRubyGemを使うことで、コネクションがクローズされた場合、自動的に再接続を試みるようにActiveRecordの挙動を修正することが出来るようです。

インストール

# sudo gem install mysql_retry_lost_connection

config/environment.rb

require 'mysql_retry_lost_connection'

なお、間違ったクエリか大きすぎるクエリを発行した場合も、このエラーが発生する可能性があります。mysqldは大きすぎるか異常のあるパケットを取得すると、クライアントに何か問題が発生したとみなし、接続をクローズするためです。

A.2.9. Packet too large エラー


MySQL クライアントまたは mysqld サーバが max_allowed_packet バイトより大きいパケットを受け取った場合、Packet too large エラーが発生し、接続がクローズされます。

MySQL 3.23 で使用できる最も大きなパケットは 16M です(クライアントおよびサーバプロトコルの制限によります)。MySQL 4.01 以上では、パケットの大きさは、サーバ上のメモリ容量でのみ制限されます(理論上は最大 2G)。

1 つの通信パケットは、MySQL サーバに送信される単一の SQL ステートメントか、クライアントに送信される単一行です。

MySQL クライアントまたは mysqld サーバが max_allowed_packet バイトより大きいパケットを受け取った場合は、Packet too largeエラーが発生し、接続がクローズされます。クライアントの中には、通信パケットが大きすぎると Lost connection to MySQL server during query エラーを発生するものもあります。