Oracle Open World 2016で、MySQLの新しい製品が紹介されました。
InnoDB Clusterです。
これは、MySQLの高可用性ソリューションと言え、
レプリケーション構成されているMySQLサーバー群を1つのクラスターと捉えて
MySQL Routerがアプリケーションからの接続を受け持つことで、
アプリケーション側からはデータベースの冗長構成を隠蔽します。
一方、クラスター内では1つのPRIMARYサーバ(≒マスター)が
原則更新を受け付けていますが、
PRIMARYサーバに障害があってダウンすると、
自動で残りのSECONDARYサーバにフェールオーバーし、
アプリケーション側には何事もなかったかのように振舞います。
また、mysqlfailoverと違い、
復旧したサーバのクラスタへの再加入が非常に簡単化されています。
InnoDB Clusterはこれから発展させていく、
とOracle社が明言していて、
今は全4Step中、第2Stepだそうです。
最終的にはシャーディングもサポートするとのことなので、
書き込み負荷分散も期待できそうです。
そんなInnoDB Clusterですが、
今はまだlabs版しかありません・・・。
でも、もうがまんできないので、早速使ってみました笑
なお、InnoDB Clusterの理解には、
MySQL Shellが使えること
グループレプリケーションを理解していること
MySQL Routerを理解していること
などが必要です。
グループレプリケーションについてはこちら、
MySQL Routerについてはこちらに記事を書いたので、よろしければどうぞ。
以下、インストールと簡単なテストの手順です。
かなり細かく書きました。
どのくらい細かいかというと、
このまんま上から実行すればOK、というくらいです。
他バージョンのMySQLが入っていないことが前提です。
実行環境は、CentOS 7.1です。
○参考ドキュメント
https://dev.mysql.com/doc/mysql-innodb-cluster/en/mysql-innodb-cluster.html
http://mysqlserverteam.com/introducing-mysql-innodb-cluster-a-hands-on-tutorial/
○MySQL本体導入
https://labs.mysql.com/
より、下記パッケージをダウンロード
mysql-innodb-cluster-labs201609-el7-x86_64.rpm.tar.gz
# tar xvzf mysql-innodb-cluster-labs201609-el7-x86_64.rpm.tar.gz
下記パッケージが展開される。
mysql-shell-1.0.5-0.1-labs-el7-x86_64.rpm-bundle.tar
mysql-router-2.1.0-0.1-labs-el7-x86_64.rpm-bundle.tar
mysql-5.7.15-labs-gr090-el7-x86_64.rpm-bundle.tar
# tar xvf mysql-5.7.15-labs-gr090-el7-x86_64.rpm-bundle.tar
下記パッケージが展開される。
mysql-community-client-5.7.15-1.labs_gr090.el7.x86_64.rpm
mysql-community-common-5.7.15-1.labs_gr090.el7.x86_64.rpm
mysql-community-devel-5.7.15-1.labs_gr090.el7.x86_64.rpm
mysql-community-embedded-5.7.15-1.labs_gr090.el7.x86_64.rpm
mysql-community-embedded-compat-5.7.15-1.labs_gr090.el7.x86_64.rpm
mysql-community-embedded-devel-5.7.15-1.labs_gr090.el7.x86_64.rpm
mysql-community-libs-5.7.15-1.labs_gr090.el7.x86_64.rpm
mysql-community-libs-compat-5.7.15-1.labs_gr090.el7.x86_64.rpm
mysql-community-server-5.7.15-1.labs_gr090.el7.x86_64.rpm
mysql-community-test-5.7.15-1.labs_gr090.el7.x86_64.rpm
MySQL本体インストール
# rpm -Uvh mysql-community-libs-5.7.15-1.labs_gr090.el7.x86_64.rpm mysql-community-libs-compat-5.7.15-1.labs_gr090.el7.x86_64.rpm mysql-community-common-5.7.15-1.labs_gr090.el7.x86_64.rpm # rpm -ivh mysql-community-client-5.7.15-1.labs_gr090.el7.x86_64.rpm # rpm -ivh mysql-community-server-5.7.15-1.labs_gr090.el7.x86_64.rpm
動作確認
# systemctl start mysqld.service # cat /var/log/mysqld.log | grep 'temporary password' # mysql -uroot -p (PW入力) mysql> set password for root@localhost='MySQL5.7'; mysql> uninstall plugin validate_password; mysql> set password for root@localhost='root'; mysql> exit
○グループレプリケーションインストール
# systemctl stop mysqld.service # vi /etc/my.cnf (以下を追記) log_bin server_id=1 binlog_format=ROW gtid_mode=on enforce_gtid_consistency log_slave_updates master_info_repository=TABLE relay_log_info_repository=TABLE transaction_write_set_extraction=MURMUR32 binlog_checksum=NONE # systemctl start mysqld.service # mysql -uroot -proot mysql> install plugin group_replication soname 'group_replication.so'; mysql> show plugins; #####group_replicationプラグインがあることを確認 mysql> exit
○MySQL Routerインストール
# tar xvf mysql-router-2.1.0-0.1-labs-el7-x86_64.rpm-bundle.tar # rpm -ivh mysql-router-2.1.0-0.1.labs.el7.x86_64.rpm # which mysqlrouter #####mysqlrouterコマンドが存在し、パスが通っていることを確認
○MySQL Shellインストール
# tar xvf mysql-shell-1.0.5-0.1-labs-el7-x86_64.rpm-bundle.tar # rpm -ivh mysql-shell-1.0.5-0.1.labs.el7.x86_64.rpm # which mysqlsh #####mysqlshコマンドが存在し、パスが通っていることを確認
○MySQL InnoDB Cluster利用テスト
https://dev.mysql.com/doc/mysql-innodb-cluster/en/mysql-innodb-cluster-getting-started.html
の記載に沿って実施していく。
・MySQL Shell用OSユーザ作成
※MySQL ShellでのSandBOXのインスタンスはrootユーザでは作成できないため
# useradd user # visudo 下記エントリを最下部に追加 user ALL=(ALL) NOPASSWD: ALL # su - user
・SandBOXでのインスタンス作成
$ mysqlsh mysql-js> dba.deployLocalInstance(3310) Please enter a MySQL root password for the new instance:(PWを入力) mysql-js> dba.deployLocalInstance(3320) Please enter a MySQL root password for the new instance:(PWを入力、上と同じである必要あり) mysql-js> dba.deployLocalInstance(3330) Please enter a MySQL root password for the new instance:(PWを入力、上と同じである必要あり)
・InnoDB Clusterノード立ち上げ
3310番ノードに接続
mysql-js> \connect root@localhost:3310 Enter password:(rootユーザのPWを入力)
クラスター作成
mysql-js> mycluster = dba.createCluster('UCOcluster') Please specify an administrative MASTER key for the cluster 'UCOcluster':(UCOclusterクラスターのMASTER KEYを指定) mysql-js> mycluster.status() #####"status": "Cluster is NOT tolerant to any failures.",となっていることを確認 mysql-js> cluster.addInstance('root@localhost:3320') Please provide the password for 'root@localhost:3320':(rootユーザのPWを入力) mysql-js> cluster.addInstance('root@localhost:3330') Please provide the password for 'root@localhost:3320':(rootユーザのPWを入力) mysql-js> mycluster.status() #####3310がR/W、3320と3330がR/Oモードでクラスターに加入していることを確認 mysql-js> \exit
○MySQL Routerセットアップ
$ sudo mysqlrouter --bootstrap localhost:3310 Please enter the administrative MASTER key for the MySQL InnoDB cluster:(UCOclusterのMaster keyを入力)
注意:私、一度ここでMaster keyを「UCOcluster」としたのですが、
これでは下のmysqlrouterの起動が上手くいきませんでした。
原因は/etc/mysqlrouter/mysqlrouter.confに書かれる、
ハッシュ化されたパスワードがエスケープされていなかったからのようです。
Configuration syntax error: Only alphanumeric characters in variable names allowed. Saw ‘kYb=’
などと出たら、Master keyを変えてみてください。
#####Classic MySQL protocol connections to cluster 'UCOcluster': #####- Read/Write Connections: localhost:6446 #####- Read/Only Connections: localhost:6447 #####と出力されることを確認 $ sudo -u mysql mysqlrouter & #####デフォルトでは/var/log/mysqlrouterディレクトリに書き込み権限がないためmysqlユーザを指定してsudo #####マニュアルには記載なし $ mysqlsh --uri root@localhost:6446 Enter password:(rootユーザのパスワードを入力) mysql-js> \sql mysql-sql> select @@port; #####3310ポートであることを確認 mysql-sql> \exit
ここまででセットアップは完了です。
○動作確認
・状態確認
$ mysqlsh mysql-js> \connect root@localhost:3310 Enter password:(rootユーザのPWを入力) mysql-js> mycluster = dba.getCluster() #####PRIMARYのインスタンスにconnectしていないと成功しないので注意 Please specify the administrative MASTER key for the default cluster:(Master keyを入力) mysql-js> mycluster.status() #####"status": "Cluster tolerant to up to ONE failure.",となっていることを確認 mysql-js> \exit
・障害模擬
$ mysqlsh mysql-js> \connect root@localhost:6446 Enter password:(rootユーザのPW) mysql-js> \sql mysql-sql> select @@port; #####3310であることを確認 mysql-sql> \js mysql-js> dba.killLocalInstance(3310) mysql-js> \sql mysql-sql> select @@port; #####ERROR: 2013 (HY000): Lost connection to MySQL server during query #####The global session got disconnected. #####Attempting to reconnect to 'root@localhost:6446'... #####The global session was successfully reconnected. #####と表示されることを確認 mysql-sql> select @@port; #####3320(3330の可能性もある)であることを確認 mysql-sql> \js mysql-js> mycluster = dba.getCluster() Please specify the administrative MASTER key for the default cluster:(MASTER keyを入力) mysql-js> mycluster.status() #####3320がONLINEでR/Wモード、3330がONLINEでR/Oモード、3310がOFFLINEであることを確認
・復旧
mysql-js> dba.startLocalInstance(3310) mysql-js> mycluster.rejoinInstance('root@localhost:3310') Please provide the password for 'root@localhost:3310':(rootユーザのPWを入力) mysql-js> mycluster.status() #####全てONLINEで、3320がR/W、3310と3330がR/Oであることを確認 mysql-js> \exit
・障害⇒更新⇒復旧テスト
復旧したインスタンスに更新が伝播するかどうか見る。
$ mysqlsh mysql-js> dba.killLocalInstance(3320) mysql-js> \exit $ mysqlsh mysql-js> \connect root@localhost:3310 #####3310であるかどうかはわからない。次のgetClusterが成功するかどうかで判断。 Enter password: mysql-js> mycluster = dba.getCluster() Please specify the administrative MASTER key for the default cluster:(Master keyを入力) mysql-js> mycluster.status() #####3320がOFFLINEになっていること、3310がONLINEでR/Wになっていることを確認 mysql-js> \sql mysql-sql> create database test; mysql-sql> create table test.t1 ( id int primary key auto_increment, com varchar(50)); mysql-sql> insert into test.t1 values (null, "from 3310"); mysql-sql> insert into test.t1 values (null, "from 3310"); mysql-sql> select * from test.t1; #####| 4 | from 3310 | #####| 11 | from 3310 | #####と出力。auto incrementの値がいきなり4な理由は不明。 #####increment幅が7なのは、group_replication_auto_increment_incrementが7であるためと思われる。 mysql-sql> \js mysql-js> dba.startLocalInstance(3320) mysql-js> mycluster.rejoinInstance('root@localhost:3320') Please provide the password for 'root@localhost:3320':(rootユーザのPWを入力) mysql-js> mycluster.status() #####全インスタンスがONLINEであり、3310がR/W、3320と3330がR/Oであることを確認 mysql-js> \connect root@localhost:3320 Enter password:(rootユーザのPWを入力) mysql-js> \sql mysql-sql> select * from test.t1; #####| 4 | from 3310 | #####| 11 | from 3310 | #####が存在することを確認
ここまでで動作確認は完了です。
・・・とこんな感じです。
mysqlrouterコマンドに–bootstrapオプションがついて、
InnoDB Clusterのルーティング先を自動でmysqlrouter.confに
登録してくれるのは手間が省けて助かりますね。
一方で、
PRIMARYがダウンした際、
dba.getCluster().status()関数が、
PRIMARYでしか使えないため、PRIMARYがダウンした場合に
どこに繋げばよいのかはあてずっぽうになってしまう、
という欠点もありました。
どこかしらで確認する方法があるのでしょうか。
というわけで、とりあえずInnoDB Clusterを使ってみました。
今後のGA版のリリースやシャーディングのサポートが待ち遠しいですね。
では。