06 FebMySQL のコネクションタイムアウトと削除されたプロセスのコネクションの残留

だいぶ前にロプローから MySQL データベースのコネクションの生存期間について聞かれてたんですが、返事するの忘れてたので今頃ブログ書いてます。どっちかって言うと忘れてたというよりは、手元の環境で問題が再現できないので放置してた感じですがw

まず MySQL コネクションはデフォルト 8 時間でタイムアウトします。

関係しているシステムパラメータは wait_timeout か interactive_timeout のいずれかです。CGI の場合は通常 wait_timeout が関係します。詳細は http://dev.mysql.com/doc/refman/5.1/ja/server-system-variables.html をご覧ください。

システムパラメータの確認は SHOW VARIABLES コマンドで行えます。以下はポックン家のテスト用環境の値です。

mysql> SHOW VARIABLES LIKE '%_timeout';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| connect_timeout            | 10    |
| delayed_insert_timeout     | 300   |
| innodb_lock_wait_timeout   | 50    |
| innodb_rollback_on_timeout | OFF   |
| interactive_timeout        | 28800 |
| net_read_timeout           | 30    |
| net_write_timeout          | 60    |
| slave_net_timeout          | 3600  |
| table_lock_wait_timeout    | 50    |
| wait_timeout               | 28800 |
+----------------------------+-------+
10 rows in set (0.00 sec)

28800 秒なので 8 時間です。

元々聞かれていたのは、「CGI プロセスをkill した際にデータベースコネクションが残ったままになることがあるか?」というような内容だったのですが、以下の手順で似たような現象を確認できます。(MySQL 5.0.67)

  1. あるプロセスがテーブルをロックしたままの状態になる
  2. 他のプロセスがロックされたテーブルを参照しようとし、1. のロックが解除されるのを待つ状態となる
  3. 2 のプロセスを kill -9 するとプロセスは消えるが、データベースコネクションはロック待ちの状態のまま残る

ロック待ちのまま残ったコネクションは、1. のテーブルのロックが解除されると切断されます。ロック待ちのコネクションが切断されるまでの間、各コネクションはサーバのコネクションプールを消費します。従って、2. と同じ処理を行うプロセスが増えるとすべてロック待ちとなり、最終的に max_connections を越えるとデータベースに接続できなくなります。

他の原因により同様の事象が発生するかを確認してませんのでもうちょっと調べた方が良いような気もしますが、kill してもコネクションが残る状態自体は発生し得るようでしたのでとりあえずご報告ということで。(テーブルのロックは LOCK TABLE WRITE コマンドで発生させたのですが、MyISAM を使用している場合、テーブルロックを長時間持続させることはレアケースだとと思いますので、もうちょっと一般的な状況で発生させる方法が無いか調べた方が良いという感じです。)

ちなみに MySQL の接続中のコネクションは SHOW PROCESSLIST コマンドで、ロック中のテーブルは SHOW OPEN TABLES コマンドで確認できます。

05 FebサラッとjQueryプラグインを書けると(・∀・)イイ!!感じ

某サイトにて、type=”text” の input 要素を、こんな感じで jQuery を使って無効にしていたのですが、

function disable_enter(e) {
    if (e.which == 13) {
       return false;
    }
    return true;
}

$(function() {
    $('.noEnter').keypress(disable_enter);
});

同じ機能を他でも使うことになって、いちいち keypress(disable_enter) 呼び出すのもうっとおしいなと思って、試しに jQuery プラグインにしてみたところ、応用範囲が超スゲー感じだったのでお伝えしたいと思います。

とりま上のをプラグインにするとこんな感じ。

(function($) {
    $.fn.extend({
        disableEnter: function() {
            this.keypress(function(e) {
                return (e.which != 13);
            });
        }
    });
})(jQuery);

$(function() {
    $('.noEnter').disableEnter();
});

呼び出し側のコードが、超簡単になったのがお分かり頂けるでしょうか?

jQuery プラグインの作り方は、プラグイン関数をメンバに持つオブジェクトを引数に渡すだけです。プラグイン関数内では、this は呼び出しに使用された jQuery オブジェクト(上の例なら $(‘.noEnter’) が返すオブジェクト)になってますので、元々 jQuery 用に書かれたコードならだいたいそのまま動きます。

元のコードでは「disable_enter を keypress イベントハンドラにセットするとエンター入力でフォームがサブミットされなくなります」という感じで、処理の概要の説明が若干まだるっこしいですが、プラグインにすると「disablEnter() を呼び出すとエンター入力でフォームがサブミットされなくなります」とう感じで、超スッキリします。

ちなみに $.fn.extend ではなく $.extend を使用すると、jQuery そのものの機能を拡張できるのですが、今日はメンドイので説明省略w

jQuery にはプラグインディレクトリ もありますので(たぶんエンターを無効にするプラグインはここにありそうw)、これ超イケテルプラグインができたらうpしたら良いと思うのですが、それほど大したものじゃなくても、jQuery の処理をプラグインにしてパッケージングしておくと再利用性がぐーんと広がるような気がします。

ぜひお試しあれw

02 Feb02月02日のココロ日記(BlogPet)

さくらさんが好きな物は改行っていうんですけど、そんなの売ってないですよぅ……

*このエントリは、ブログペットのココロが書いてます♪

26 Jan01月26日のココロ日記(BlogPet)

いい刻印を抱き枕にしたら気持ちいいですかねぇ……

*このエントリは、ブログペットのココロが書いてます♪