MySQL Binlog APIを試してみる

MySQL のレプリケーションは素晴らしい仕組みなのですが、ちょっと凝ったことをしようとするには機能が限られています。特に、MySQL の更新を他のデータストアにマイグレーションしたいような時は、Trigger を使って超頑張るのはイマイチで、バイナリログを使ったレプリケーションの仕組みをそのまま拡張してマイグレーションするようなワーカーを書きたくなるものです。

そんな時に使える便利な API として、Binlog API というものがあります。まだ開発途上ではありますが、期待の持てる API です。

試しにどんなもんなのか使ってみました。

追記 2012/07/09

とか言ってたら、さっそく @tokuhirom さんが Perl バインディングを作ってくれました!!!

早速 XS 童貞の私ですがコード読み込んで使ってみようとおもいます!tokuhirom++

各言語のエキスパートのみなさま、引き続き他言語のバインディングもお待ちしています!(ぇ

追記 2012/07/10

antipop さんが Mac での動かし方を紹介してくれています!

準備

CentOS5 系の 64bit で試した手順です。まずビルドに必要なパッケージを入れたいのですが、CentOS の yum レポジトリだと足りないので epel と atrpmas というレポジトリを追加します。

# cat /etc/yum.repos.d/epel.repo
[epel]
name=Extra Packages for Enterprise Linux 5 - $basearch
#baseurl=http://download.fedoraproject.org/pub/epel/5/$basearch
mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=epel-5&arch=$basearch
failovermethod=priority
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL

# cat /etc/yum.repos.d/atrpms.repo
[atrpms]
name=Redhat Enterprise Linux $releasever - $basearch - ATrpms
baseurl=http://dl.atrpms.net/el$releasever-$basearch/atrpms/stable
enabled=0
gpgcheck=1
gpgkey=http://atrpms.net/RPM-GPG-KEY.atrpms

どちらも enabled=0 にしてるので明示的に enabled しないと yum コマンドが検索しないようにしてます。

あとは yum 実行するだけ。bzr はソースのチェックアウト用、cmake はビルドツール、boost は CentOS の 1.33 だとバージョンが古いので atrpms のものを利用。epel に boost141 ってのがあるのでそれでもいけるのかも(未確認)。

# yum --enablerepo=epel install cmake bzr
# yum --disablerepo=* --enablerepo=atrpms install boost*

ちなみに、atrpms の boost-devel と CentOS-Base の boost-devel はファイル被ってるみたいで、atrpms の 64bit のが入った後に CentOS-Base の 32bit のが入るとビルドできなくなる。キモイだけなので 32bit は入れないのが吉。僕が試した環境は最初から入ってなかった。

ビルド&インストール

簡単。

$ bzr branch lp:mysql-replication-listener
$ cd mysql-replication-listener
$ cmake .
$ make
$ sudo make install

これで/usr/local/includeにいくつかのヘッダファイルと、/usr/local/libにライブラリがインストールされます。

example ビルド

ソースの中に example があるのでそれを試してみます。

$ cd example
$ cmake .
$ make

これで basic-[12]を実行したいところなんですが、僕の環境だと実はライブラリのサーチパスに/usr/local/libが入ってなかった。こういう場合は、サーチパスに足すか実行時に指定してあげる。

サーチパス追加の場合

$ sudo echo /usr/local/lib >> /etc/ld.so.conf
$ sudo ldconfig
$ ./basic-1

実行時に指定の場合

$ LD_LIBRARY_PATH=/usr/local/lib ./basic-1
or
$ LD_PRELOAD=/usr/local/lib/libreplication.so ./basic-1

Let’s example

では実際に試してみましょう。おもしろいのは basic-2 で master につないで見るのだと思います。自分はとりあえず MySQL::Sandbox で実験。

$ make_replication_sandbox ~/mysql/mysql-5.1.63-linux-x86_64-glibc23.tar.gz
$ cat ~/sandboxes/rsandbox_mysql-5_1_63/master/my.sandbox.cnf
[client]
user            = msandbox
password        = msandbox
port            = 28888
↑確認
$ ./basic-2 'mysql://msandbox:msandbox@127.0.0.1:28888'
SET PASSWORD FOR 'root''''localhost'='*6C387FC3893DBA1E3BA155E74754DA6682D04747'
grant all on *.* to msandbox'''127.%' identified by 'msandbox'
grant all on *.* to msandbox'''localhost' identified by 'msandbox'
grant SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,ALTER,
    SHOW DATABASES,CREATE TEMPORARY TABLES,LOCK TABLES, EXECUTE
    on *.* to msandbox_rw'''localhost' identified by 'msandbox'
grant SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,ALTER,
    SHOW DATABASES,CREATE TEMPORARY TABLES,LOCK TABLES, EXECUTE
    on *.* to msandbox_rw'''127.%' identified by 'msandbox'
grant SELECT,EXECUTE on *.* to msandbox_ro'''127.%' identified by 'msandbox'
grant SELECT,EXECUTE on *.* to msandbox_ro'''localhost' identified by 'msandbox'
grant REPLICATION SLAVE on *.* to rsandbox'''127.%' identified by 'rsandbox'
delete from user where password=''
delete from db where user=''
flush privileges

おおおおお!!!!普通に binlog が読み込まれて Query が表示されました。しかも、イベントループに入っていて、新しい binlog を待ち構えています。では、別クライアントから更新文を発行してみます。

$ ~/sandboxes/rsandbox_mysql-5_1_63/master/use
> use test
> create table t1 (id int unsigned not null auto_increment, value varchar(255), primary key (id)) engine=InnoDB;
> begin;
> insert into t1 (value) values ("aaaa");
> insert into t1 (value) values ("bbbb");
> commit;

すると、先程の basic-2 の方に DDL が流れてくるのが見えると思います。トランザクションは当然 commit して初めて流れてきます(basic-2 が COMMIT は print してくれてないっぽい)。

create table t1 (id int unsigned not null auto_increment, value varchar(255), primary key (id)) engine=InnoDB
BEGIN
insert into t1 (value) values ("aaaa")
insert into t1 (value) values ("bbbb")

まとめ

というわけで、単に example を動かしてみただけですが、かなり夢が広がりますね。

しかし、C++力がない!願わくは、ワーカーっぽいものは LL で書きたい(既存アプリのライブラリが使えたりするでしょうし)ので、Binlog API の各種 LL へのバインディングが欲しいところです。誰か書いて!もしくは書き方教えて!

あと Mac で boost の使い方がよく分からなかったので、Mac で動いた人いたら動かし方教えてください><

参考

  • とおりすがり 12-07-09 (月) 10:59

    手元だとなぜか examples/CMakeFiles/basic-2.dir/link.txt に -lboost_system を追加しないとうごきませんでした(ubuntu)。

  • riywo 12-07-10 (火) 0:33

    情報ありがとうございます!