MySQL wait_timeoutの挙動

アイドル状態(最後の実行から何もしていない)がN秒続くとMySQLが勝手に接続を切るらしい。
このN秒を設定するのがwait_timeoutである。
まず、デフォルト設定を確認してみる。

mysql -uroot -e'show variables' | egrep '(wait)';
--------
wait_timeout    28800

ということで、28800秒=8時間がデフォルトの模様。
http://dev.mysql.com/doc/refman/4.1/ja/gone-away.htmlにも書いてある。


次にwait_timeoutを10秒に変更してみる。
/etc/my.cnfに以下を追加。

[mysqld]
wait_timeout=10


これで準備はOKなので、テストしてみる。

my $dbh = &get_handle
my $sth = $dbh->prepare(<<'SQL');
select * from data limit 1;
SQL
$sth->execute;

my $cnt = 0;
while(1) {
    sleep(1);
    $cnt++; print "$cnt\n";
    last if ($cnt > 9);
}
$sth->execute;

実行すると期待通りエラーになる。

1
2
3
4
5
6
7
8
9
10
DBD::mysql::st execute failed: MySQL server has gone away at connection.pl line 20.


ちなみにハンドルを取得してからの時間が問題になるので、
以下のケースでもエラーになる。

my $dbh = &get_handle
my $sth = $dbh->prepare(<<'SQL');
select * from data limit 1;
SQL

#ハンドル取得後に時間経つ
my $cnt = 0;
while(1) {
    sleep(1);
    $cnt++; print "$cnt\n";
    last if ($cnt > 9);
}
$sth->execute;
まとめ

アイドル状態のコネクションをMySQLが切断するまでの時間はwait_timeoutで設定できる。
プログラムでもwait_timeout値を意識し、処理フローの組み立てに気を使う必要がある。
ハンドル取得から処理まで長い時間を置かない、置くならハンドル再取得等。

追記(2014.08.27)

検索で上位に表示されてることにビビったので。。。

「wait_timeoutを延ばしておけば安心だよ」と言いたいのではなく、むしろ「timeout しないよう、気をつけてコーディング必要だよね。特に長めの処理をする batchなどは、集計等してる間にうっかり timeout しないよう利用するサーバの設定確認しておくべし」という趣旨です。

当時書いた文章からは全く伝わらないけども、そういう背景でありました。。。