秘伝のバッチが突如悲鳴を上げるということは少なくないと思いますが、自分の知識不足から復旧に時間を要してしまった。
自戒もかねてメモを残す。
やばいクエリによるtimeoutでgone away
“MySQL server has gone away” が発生する原因としては以下の要因が考えられる。
- クエリのサイズがでかすぎ
- 接続のアイドルタイムアウト
前者はmax_packet_sizeの値を調整して解決できる。
が、今回の原因は後者のタイムアウトの秒数だった。
接続が開始されてから、最後にデータベースに問い合わせをした時間から、指定した秒数
たってしまうと、データベースはクライアントとの接続を勝手に切ってしまう。
接続が切れた状態でクエリを送信すると、「おまえの接続はもう切れてるぜ!」となりgone awayとなる。
この指定した秒数
の謎についておいかけていきたいと思います(^O^)/
なぜ原因判明まで時間がかかってしまったのか
そもそも時間がかかりすぎるクエリがよくないのだが、明らかに設定された時間内より早いタイミングで切断されていた。
デフォルトだとおそらく2880秒で設定されている
1 | % mysql -u root |
2880秒もたってないのになぜgone awayになるんだよ。。。
マニュアルに書いてあった。。。
以下公式からの引用
Interactive(対話型)で接続したやつはinteractive_timeoutの秒数をwait_timeoutとして設定しちゃうぜ!
ってことみたいです。
interactive_timeoutの秒数
1 | % mysql -u root |
じゃあ対話型じゃない場合はどうなるかっていうと
1 | % mysql -u root -e "show variables like 'wait_timeout'" |
my.iniで設定されている数字がやっとでてきた。
アプリケーションから接続する際は非対話モード(Interactiveじゃない)になるので、
60秒が設定されていたため、早いタイミングで落ちていたみたいです。
28800秒で設定されるから他に原因があるのかと思い余計な時間をとられてしまった。。。
実験
前提
- mysql 5.6
- php7.1
- pdo
実験1. wait_timeoutを5秒に設定して、DBに接続してからsleepを6秒いれた後、クエリを実行するとgone awayになるか確認。
1 | <?php |
見事gone away!
1 | Warning: PDO::query(): MySQL server has gone away in /src/connect.php on line 11 |
実験2. interactive_timeoutを5秒に設定して、対話接続でクエリ実行後に5秒まち、再度クエリを実行するとgone awayになるか確認。
1 | % mysql -u root |
5秒待って再度クエリ実行
見事gone away!
1 | mysql> SHOW VARIABLES LIKE 'interactive_timeout'; |
テストに使ったコードはこちら
https://github.com/kuniiskywalker/test-mysql-goneaway
まとめ
対話型の場合だけ秒数が別指定が多めにとられてるのは、一旦接続していろいろいじることが前提なので当たり前といえば当たり前。。。