MySQLには「mysql server has gone away」という見慣れないエラーがあります。
恐らくシステム開発に携わっていない方は見たことのないエラーではないでしょうか?
かくいう私もまだ一度も見たことはありませんが、今回はこの珍しいエラーでもあるmysql server has gone awayについて色々と解説してみたいと思います。
目次
mysql server has gone awayとは
mysql server has gone awayとはサーバーがタイムアウトして接続がクローズした場合に起きるエラーです。
デフォルトでは無動作状態が8時間程度続くとサーバーは自動的に接続をクローズします。
mysql server has gone awayとなる原因
ではこのエラーは一体どのような場合に起こり得るのでしょうか?
最も多い原因となるのは、非常に膨大な量のクエリを発行した場合です。
これはPCの環境にも依存するのですが、あまりにも膨大な量のクエリを処理しようとすると、メモリやパケットがパンクしてしまいます。
こうなるとフリーズ状態となるため、結果としてサーバータイムアウトとなり、このエラーが起こります。
また別の原因としては、MySQLコネクション上で意図的に”close”を発行し、コネクションクローズさせた状態のまま新たに別のクエリを実行した場合にも同じように当エラーが返ってきます。
通常MySQLは自動でクローズ処理を完結するため、明示的にクローズ処理をするケースは減ってきましたが、セキュリティ上の問題や開発の仕方によっては明示的にクローズを発行するため、このようなケースに陥ることがあります。
mysql server has gone awayを防ぐ方法
エラーとしてはあまりメジャーなものではないため必須というわけではないかもしれませんが、MySQLの学習をしていく中でエラーの回避方法は覚えておいて損はないと思います。
ここではこの「mysql server has gone away」を回避する方法についていくつか挙げていきたいと思います。
パケットサイズの拡張
クエリを発行する際にあまり大きなクエリというのはないかもしれませんが、もし万が一そういったクエリを発行するケースがあるなら、まずは構成ファイル内の設定を見直す必要があります。
構成ファイルとは「my.ini」を指します。
この中にある”max_allowed_packet”の値を拡張することで未然に防げる場合があります。
“max_allowed_packet”は以下の場所にあります。
# The MySQL server
default-character-set=utf8
[mysqld]
port=3306
socket=”C:/mysql/mysql.sock”
basedir=”C:/mysql”
tmpdir=”C:/tmp”
datadir=”C:/mysql/data”
pid_file=”mysql.pid”
# enable-named-pipe
key_buffer=16M
max_allowed_packet=1M
sort_buffer_size=512K
net_buffer_length=8K
read_buffer_size=256K
read_rnd_buffer_size=512K
myisam_sort_buffer_size=8M
log_error=”mysql_error.log”
[mysqld]の項目内にある”max_allowed_packet”は、環境にもよりますがMySQLインストール時に変更を加えていなければ恐らくデフォルトは1Mとなっています。
クエリ実行時に頻繁にタイムアウトやバッファオーバーフローが起こるようであれば、まずこの数値を大きくすべきです。
目安としては20MB以上にしていれば大規模なクエリを実行した場合でも対応できると思います。
タイムアウトの時間設定を変更する
クエリにも問題がなく、記述ミスも見られないのになぜかタイムアウトを頻発する場合には別の対処法もあります。
それが二つ目の対処法でもあるwait_timeoutという設定項目を追加する方法です。
MySQLの初期設定では8時間となっているので設定を変更していないのであれば問題はありませんが、開発時に何かしらの要因で変更している可能性がある方は一度確認しても良いでしょう。
my.iniで設定変更する場合には[mysqld]より下の行へ以下のように追記します。
wait_timeout = 60
また、シェルコマンドで変更する場合には、次のように記述します。
set global wait_timeout = タイムアウトさせる時間(秒);
なお、現在の設定を調べる場合には以下のコマンドを実行すれば確認することが出来ます。
MariaDB [sample_db]> show global variables like '%wait%'; +---------------------------------------------------+--------------+ | Variable_name | Value | +---------------------------------------------------+--------------+ | binlog_commit_wait_count | 0 | | binlog_commit_wait_usec | 100000 | | innodb_fatal_semaphore_wait_threshold | 600 | | innodb_lock_wait_timeout | 50 | | innodb_spin_wait_delay | 4 | | lock_wait_timeout | 86400 | | performance_schema_events_waits_history_long_size | -1 | | performance_schema_events_waits_history_size | -1 | | rpl_semi_sync_master_wait_no_slave | ON | | rpl_semi_sync_master_wait_point | AFTER_COMMIT | | wait_timeout | 28800 | +---------------------------------------------------+--------------+ 11 rows in set (0.001 sec)
一番下に”wait_timeout”という項目があることが確認できます。
因みにこの例では初期設定のままなので28800秒(8時間)となっています。
まとめ
いかがでしたか?
今回は”MySQL server has gone away”エラーについて原因や回避方法などを解説してみました。
学習時に最もよくあるケースとして、PCでコマンドラインを開いた状態のまま放置しタイムアウトの設定時間を過ぎてしまい、それに気づかずそのままクエリを実行するとエラーが出るということがあります。
まず放置しないことが一番良いのですが、どうしても何かしらの原因でコマンドラインを閉じることが出来ない場合には同じクエリを2回実行してみると2回目にはエラーが出なくなったりしますので、色々なケースを試してみましょう。
わざとエラーを出してみるというのも勉強になりますので、そういったケースを一度経験することも大切に思います。