2005年03月31日
Sledge + MySQL4.1でセッションを保存できない
Sledge+MySQL4.1な環境でセッションを保存できないという状況に陥りました。
現象としては、セッションIDは保存されているのに、セッションデータ(a_session)だけが保存されないという状況です。どうやらTEXT型のフィールドにStorableモジュールでnfreezeしたデータを入れることができないみたいなので、原因を調べてみました。。
MySQL リファレンスマニュアル :: 2.5.1 バージョン 4.0 から 4.1 へのアップグレードによると、
すべてのテーブルと文字列カラムがキャラクタセットを持つようになった。 See 章 9. 各国キャラクタセットと Unicode。 キャラクタセット情報は、SHOW CREATE TABLE と mysqldump によって表示される (MySQL バージョン 4.0.6 以降は、新しいダンプファイルを読み取ることはできる。これより前のバージョンは、新しいダンプファイルを読み取ることはできない)。
ということで、4.1からはTEXT型がキャラクタセットを持つようになったようです。試しにshow create talbe sessionsを実行すると以下のように、CHARSET=ujisがついていました。
CREATE TABLE `sessions` ( `id` varchar(32) NOT NULL default '', `a_session` mediumtext, `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=ujis
このことから、ujis(EUC)のキャラクタセットをもつTEXTフィールドにnfreezeしたujis以外の文字コードを含んだデータをインサートしようとしたため、データが空になってしまうのではと予想しました。
そこでSledge::Session::Pgにならって、nfreezeしたものをbase64エンコードして、ujisの文字コード内で表現できるデータにしてからインサートするようにしたところ、うまくデータを保存できるようになりました。実際には以下のようなSledge::Session::MySQLのサブクラスを作って、替わりにcreate_sessionにセットしてあげました。
package Sledge::Session::MySQL41;
use strict;
use base qw(Sledge::Session::MySQL);
use MIME::Base64;
sub _serialize {
my($self, $data) = @_;
return encode_base64(Storable::freeze($data));
}
sub _deserialize {
my($self, $data) = @_;
return Storable::thaw(decode_base64($data));
}
1;
Continuing the discussion...
このエントリーのトラックバックURL:
http://hori-uchi.com/mt/trackback/312
Comments
ボクは、textじゃなくて、longblobを使うようにしてました。
MLに投げようとおもって忘れてた。
Posted by きむら at 2005年04月01日 10:52
きむらさんこんにちは。
なるほど、セッションデータ自体がバイナリであること考えると、型をlongblob型などに変える方が自然ですね。
Posted by hori-uchi at 2005年04月01日 17:52
あいらも同じはまりをして base64で逃げましたw。
my.cnfでdefault-charsetを binary にっていう人もいましたけど。。。
(変換しないという意味で)
Posted by max at 2005年04月08日 03:42
binaryにっていうのはちょっと強引な気もしますね。
やはり、きむらさんのa_sessionの型をblogにするというのが、お手軽だし、まっとうな方法ですかねー。
Posted by hori-uchi at 2005年04月08日 10:11
