MySQL で BLOB を扱うためのストレージエンジン "BLOB Streaming Engine"
こんにちは。
ガルーン開発グループの米川です。
4/14 ~ 4/17 に、サンタクララで開催された MySQL Conference & Expo に参加してきました。 今回の記事では、その中で聞いた "BLOB Streaming Engine" というものについてご紹介します。
MySQL と BLOB データ
Web アプリケーションを開発していると、BLOB データ ( ※注 1 ) を扱う場面がよくあると思います。 一般的に BLOB データはデータサイズが大きく、扱いが困難なことが多いです。
MySQL には BLOB 型というデータ型が用意されていますが、実体はただのテキストデータで、バイナリ文字列をそのまま格納しているのとほぼ同じです。
通常、バイナリデータはサイズが大きいため、普通に文字列として扱っていてはテーブルやカラムのデータが肥大化していきます。 また、バイナリデータをストリームとして扱うことができないため、メモリの限界が格納できるサイズの限界になってしまいます。
解決策として、ファイルの実体はファイルシステムへ書き出し、テーブルには参照のみを持つというアプローチが考えられると思います。しかしこの方式にもデメリットはあって、ファイルへの書き込みがトランザクションの外になってしまい、MySQL のレコードとファイルシステム上のファイルとの一貫性が保てなくなる可能性があります。
こういった問題は、MySQL がもっと BLOB データを賢く扱ってくれれば解決するはずです。 そのために開発されたストレージエンジンが BLOB Streaming Engine です。
※注 1 : ここで言う BLOB データとは画像ファイルや MP3、動画ファイルのようなバイナリデータのことを指します
BLOB Streaming Engine とは
BLOB Streaming Engine は、PrimeBase という企業が開発した MySQL のプラガブルストレージエンジンです。 以下のような目的を実現するために開発が進められています。
- BLOB データを直接 MySQL データベースへストリーミングする
- あらゆるサイズの BLOB データをデータベースへ格納する
- そのためのスケーラブルなバックエンドシステム
- 全てのストレージエンジンで使えるオープンなシステム
- 既存の MySQL クライアントのための拡張を提供する
通常のストレージエンジンと違い、BLOB Streaming Engine はかなり特殊なアーキテクチャで作られています。 特徴的なのは以下の 2 つです。
- 組み込みの HTTP サーバー
- BLOB Repository
BLOB Streaming Engine は、クライアントとのやり取りに HTTP ベースのプロトコルを使います。 それを扱うために、HTTP サーバーを内包しています。
そして BLOB Streaming Engine の中核を担うのが、"BLOB Repository" です。
BLOB Repository は、BLOB データの実体とリファレンスを管理するシステムテーブルです。
このシステムテーブルと、BLOB Streaming に対応したストレージエンジンがやり取りすることで、
各ストレージエンジンで BLOB データを柔軟に扱うことができます。
インストール
BLOB Streaming Engine のインストール方法は通常のプラガブルストレージエンジンと同じです。
以下の URL からソースをダウンロードし、解凍してコンパイルします。
この記事を書いている時点での最新バージョンは、mybs-0.5.04-alpha.tar.gz でした。
http://www.blobstreaming.org/download/
# tar zxvf mybs-0.5.04-alpha.tar.gz # cd mybs-0.5.04-alpha # ./configure --libdir=/path/to/mysql/lib/mysql/plugin --with-mysql=/path/to/mysql-src-dir # make # make install
MySQL のバージョンは5.1で、執筆時点で最新の 5.1.24-rc を使用しました。
http://dev.mysql.com/downloads/mysql/5.1.html
MySQL クライアントで、プラグインをインストールします。
プラグインの一覧の中に MyBS というストレージエンジンがあったらインストールに成功しています。 また、エラーログを見てみると以下のようなログが出ているはずです。
080519 10:41:15 [Note] startup: BLOB Streaming engine 0.5.04-alpha listening on port 8080
これは、BLOB Streaming Engine に内包された HTTP サーバーが起動したことを意味します。
デフォルトでは 8080 番ポートを listen します。 BLOB Streaming Engine をインストールすると、MySQL 起動時にこの HTTP サーバーも起動するようになります。
BLOB データを格納してみる
BLOB Streaming Engine を使用するためには、まず最初にシステムテーブル ( BLOB Repository ) を作成する必要があります。 将来的にはこのシステムテーブルは自動で作られるようになるのかもしれませんが、 現状では手動で以下のクエリを実行する必要があります。
CREATE TABLE mybs_repository ( Repository_id INT COMMENT 'The repository file number', Repo_blob_offset BIGINT COMMENT 'The offset of the BLOB in the repository file', Blob_size BIGINT COMMENT 'The size of the BLOB in bytes', Head_size SMALLINT UNSIGNED COMMENT 'The size of the BLOB header - proceeds the BLOB data', Access_code INT COMMENT 'The 4-byte authorisation code required to access the BLOB - part of the BLOB URL', Creation_time TIMESTAMP COMMENT 'The time the BLOB was created', Last_ref_time TIMESTAMP COMMENT 'The last time the BLOB was referenced', Last_access_time TIMESTAMP COMMENT 'The last time the BLOB was accessed (read)', Content_type CHAR(128) COMMENT 'The content type of the BLOB - returned by HTTP GET calls', Blob_data LONGBLOB COMMENT 'The data of this BLOB' ) ENGINE=MyBS; CREATE TABLE mybs_reference ( Table_name CHAR(64) COMMENT 'The name of the referencing table', Blob_id BIGINT COMMENT 'The BLOB reference number - part of the BLOB URL', Column_name CHAR(64) COMMENT 'The column name of the referencing field', Row_condition VARCHAR(255) COMMENT 'This condition identifies the row in the table', Blob_url VARCHAR(200) COMMENT 'The BLOB URL for HTTP GET access', Repository_id INT COMMENT 'The repository file number of the BLOB', Repo_blob_offset BIGINT COMMENT 'The offset in the repository file', Blob_size BIGINT COMMENT 'The size of the BLOB in bytes', Deletion_time TIMESTAMP COMMENT 'The time the BLOB was deleted', Remove_in INT COMMENT 'The number of seconds before the reference/BLOB is removed perminently', Temp_log_id INT COMMENT 'Temporary log number of the referencing deletion entry', Temp_log_offset BIGINT COMMENT 'Temporary log offset of the referencing deletion entry' ) ENGINE=MyBS;
ENGINE が MyBS なことに注目してください。 これにより、BLOB データを管理するためのシステムテーブルが作成されます。
では実際に BLOB データを BLOB Repository に格納してみます。 HTTP プロトコルを使っているので、curl を使ってアップロードすることができます。
# curl -T logo_cybozu.gif http://localhost:8080/database_name
curl で例のようなリクエストを送ると、以下のような文字列が返ってきます。
~*database/_1-248-5843b202-0
これが BLOB Repository 上の BLOB データへのリファレンスです。 ちなみに HTTP サーバーを内包しているので、このリファレンスを使ってブラウザからアップロードした ファイルを見ることができます。 BLOB データの参照を行う際も、このようにリファレンスを組み込み HTTP サーバーに渡して実データを受け取ることになります。
http://localhost:8080/~*test/_1-248-5843b202-0
このリファレンスが、普段使用するテーブルの BLOB カラムと BLOB Repository 内の実データを繋ぐものです。 BLOB Streaming Engine に対応しているストレージエンジンは、このリファレンスが BLOB カラム ( ※注 2 ) に格納されたときに、 サーバーサイドの API を使って BLOB Repository のデータとテーブルに格納されたリファレンスを関連付けます。 関連付けが行われると、mybs_reference テーブルの中身は以下の画面のようになります。
該当の BLOB データを関連付けたテーブルの情報が格納され、一時ファイル用のカラムが NULL になります。 これにより、テーブルに格納されたリファレンスから 実際の BLOB データを取得することが可能になります。
※ 2 : 現状では LONGBLOB カラムでないとサーバーサイド API による関連付けが実行されないようです
クライアントライブラリの対応
上記のように、自分で BLOB Streaming Engine へのアクセスを実装することも可能ですが、 このプロジェクトは、既存のクライアントにおける BLOB Streaming 対応のための拡張も視野に入れられています。 では、現状の対応状況はどのようになっているのでしょうか?
JDBC に関しては、既に他 DBMS において対応しているのもあり、透過的に BLOB データを格納するためのドライバが 既に公開されています。 setBinaryStream のような関数を使うことで、BLOB Repository へのデータ格納と、 BLOB カラムへのリファレンスの格納を同時にやってくれます。
こちらから BLOB Streaming 可能な MySQL Driver がダウンロードできます。
http://www.blobstreaming.org/download/
また、PHP 用のコネクタの開発もプロジェクトが発足しています。
現在はまだ実装は公開されていないようです。
http://forge.mysql.com/wiki/BLOB_Streaming_For_PHP
その他の言語用のライブラリや、libmysqlclient については未対応となっています。 今後対応されていくことになるでしょう。
BLOB Streaming Engine の今後
Web アプリケーション開発において、BLOB データを扱うことはもはや必須要件になっていると思います。
BLOB Streaming Engine によって、MySQL でも柔軟に BLOB データを扱うことができるようになるのではないかと期待しています。 しかし、現状では対応しているエンジンが PrimeBase が開発している PBXT というストレージエンジンしかありません。 今後、ぜひ他のエンジンでも対応していってほしいと思います。
BLOB Streaming Engine 自体も、レプリケーション対応や分散 BLOB Repository など、 よりスケーラブルにするための仕組みが実装されていくと聞いているので、 今後も注目していきたいと思います。
|
関連するエントリー
MySQL 5.1 のプラガブルストレージエンジンでオリジナルのストレージエンジンを作ろう (2007-07-03)
