MySQL 5.5 の Semi-sync. を Windows 上で試してみた

 MySQL 5.5 話題の機能のひとつ、セミ・シンクロ・レプリケーション。同期と非同期の間の「semi-」シンクロということで、息を大きくすって一息で言うと「マスタの更新がスレーブのDBに反映されるところまでは保証しないのだけどスレーブのDBに反映するために一旦スレーブ側に保存するファイル(リレーログ)に保存されることまでつまりスレーブにデータが渡っているところまでは保証するレプリケーション」ということになります。さて問題です。この文に読点を打ってください(笑)。
 セミシンクロレプについては、漢(オトコ)が詳しく説明してくれています。
http://nippondanji.blogspot.com/2009/03/mysql-ha-semi-synchronous-replication.html


 ということで、どんな動きをするのか興味があったのでさくっと試してみました。最大の懸念は「スレーブのリレーログまで渡ってからようやく結果を返す、ということは、スレーブが落ちたらマスターもろとも無反応? それって要するに障害率が2倍になるって意味じゃないの?」ということでした。
 結果を先に書くと「そんなことはない。とてもよくできてる」です。


Windows 上でのレプ実験の設定

 MySQLが動作していない Windows 上に、以下の手順でレプリケーション実験環境を作ります。
(私は他のバージョンが動作していたので一旦きれいさっぱりご退場いただきました)

(1)MySQL 5.5.0-m2 の noinstaller 版をダウンロード、展開。
(2)2つのディレクトリにコピー(私は C:\usr\mysql550\ と C:\usr\mysql550-2\ にしました)
(3)2つのディレクトリの下にそれぞれ my.ini を作成。下例はスレーブ側として使うつもりの 550-2 ディレクトリのほうの設定(メモリ関係の設定はここでは省略しました)。

[mysqld]
basedir="c:/usr/mysql550-2/"    ←マスタでは550/
datadir="c:/usr/mysql550-2/data/" ←マスタでは550/data/
default-character-set=cp932
server_id=21          ←マスタでは server_id=11 にした
port=3307           ←スレーブのみで指定
log-bin

[mysql]
default-character-set=cp932
port=3307           ←スレーブのみで指定
no-beep


(4)コマンドプロンプトの窓を4つ開く。左側をマスタ(3306ポートで動作)、右側をスレーブ(3307で動作)として作業することにします。それぞれ、c:\usr\mysql550\, c\usr\mysql550-2\ 下に移動して bin\mysqld --defaults-file=my.ini としてサーバを起動します。(キャプチャの左上の画面では my.ini を指定していませんが、実は windows ディレクトリ下にある my.ini を読ませています)


(5)下部2枚のウィンドウで、bin\mysql -uroot と、bin\mysql -uroot -P3307 として接続します。status 文などでそれぞれ目的のサーバにつながっていることを確認するといいでしょう。


(6)私はサーバを落とすためにもう一枚、窓を開けています。ここで2つのサーバを落としています

レプリケーションの設定

 スレーブ側の接続で、以下のコマンドを発行してマスタを指定します。

mysql> CHANGE MASTER TO MASTER_HOST='localhost', MASTER_PORT=3306, MASTER_USER='root';


 あとは START SLAVE / STOP SLAVE したり、セミシンクロに関するパラメタをいじったりして遊ぶだけです。

セミシンクロレプの準備

 マスタスレーブともに

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.dll';
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.dll';

 を実行して、セミシンクプラグインを読み込む。マスタはマスタ用のだけ、スレーブはスレーブ用のだけでいいのですが、両方使用可能にしておくほうが(運用をするときには)いいんじゃないかな、と個人的に思っています。今は遊びなので正直言うと「なんとなく両方しました」。

セミシンクロレプの動作

マスタで

mysql> SET GLOBAL rpl_semi_sync_master_enabled=1;

スレーブで

mysql> SET GLOBAL rpl_semi_sync_slave_enabled=1;

を実行。スレーブから START SLAVE 文でレプリケーションを開始します(すでに開始されている場合は一旦 STOP SLAVE してから START SLAVE)。

mysql> SHOW STATUS LIKE "rpl%";

 でセミシンクロレプの状態を見ることができます。
以下の値が ON になっていたり OFF になっていたりで、セミシンクロでレプリケーションが動作中かどうかが判ります。

| Rpl_semi_sync_master_status                | ON     |
| Rpl_semi_sync_slave_status                 | OFF    |

わかったこと

・スレーブが落ちているとマスタでは自動でセミシンクロのレプリケーションから非同期の(通常の)レプリケーションへと切り替わる
・切り替わるまでには、rpl_semi_sync_master_timeout 値の設定に従った時間(デフォルト10秒)だけ待つ。スレーブが落ちたときにこの時間だけはすべての更新が止まる(待ちになる)と思って良い
・非同期レプに切り替わってしまったことは、マスタの Rpl_semi_sync_master_status ステータス値が OFF になることで検出可能。また、セミシンクロ時は更新時にステータス値 Rpl_semi_sync_master_yes_tx がインクリメントされるのに対し、非同期時には Rpl_semi_sync_master_no_tx がインクリメントされていくことから、その増分でも判るかもしれない(ただし、スレーブが複数で、そのうちの1台だけをセミシンクロにする場合にどう増えるか未確認。もしかしたら監視用途には使えない(混在してしまう)かもしれない)
・停止していたスレーブが改めてマスタに接続しなおした際には、マスタの Rpl_semi_sync_master_status も自動で ON になる。
・スレーブのサーバ自体を再起動した際には、(今回は my.cnf に rpl_semi_sync_slave_enabled=1 を記述していないので オフになっているため)通常のレプとして再開してしまう。レプリケーション自体は自動で開始されるから。 my.cnf に書けば安全だと思われるが、スレーブ再起動時には一応「セミシンクロのつもりだったのに普通に非同期だった」ということがないよう注意が必要。
・もっともこれらはともかく、マスタの Rpl_semi_sync_master_status=ON を監視していれば問題にはならないと思う。

・rpl_semi_sync_master_wait_no_slave 値(デフォルト ON)を OFF にしてみたが、何が変わったのかわからなかった。ドキュメント読んでみないと。。。(スレーブ停止時に、10秒待つことや、その後セミシンクロが OFF になることなど、特に何も変わらなかった)



 監視方法や運用方法など、ムラムラと妄想を掻き立てられる楽しい機能ですね。今回とりあえず2台での動作確認をしてみたところですが、3台以上の実運用環境でどう扱うのがもっとも良さそうなのか、色々思考実験してみたいと思います。
 と言っても私の会社でこの環境を必要とするようなサービスをやっていないので、この仕組みに興味のある会社さん、一緒にやりましょう。上記通り私も現在試行錯誤の段階ですが、お力になれると思います(^^)。ご連絡お待ちしています:-)



.