前回の記事で、InnoDB Clusterの基本的な挙動を確認しました。
今度は障害時の挙動を見てみましょう。
現在の状態はこんな感じ。
mysql-js> cluster.status() { "clusterName": "UCO_Cluster", "defaultReplicaSet": { "name": "default", "primary": "192.168.2.224:3306", "status": "OK", "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", "topology": { "192.168.2.224:3306": { "address": "192.168.2.224:3306", "mode": "R/W", "readReplicas": {}, "role": "HA", "status": "ONLINE" }, "192.168.2.225:3306": { "address": "192.168.2.225:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "ONLINE" }, "192.168.2.226:3306": { "address": "192.168.2.226:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "ONLINE" } } } }
なお、いちいちIPアドレスやホスト名を書くのも分かりづらいので、
192.168.2.224から順に1号機~3号機、と呼ぶことにしましょう。
さて、R/Wになっている1号機をダウンさせます。
[root@innodb-cluster1 ~]# systemctl stop mysqld.service
2号機で状態を見てみましょう。
mysql-js> cluster.status() { "clusterName": "UCO_Cluster", "defaultReplicaSet": { "name": "default", "primary": "192.168.2.226:3306", "status": "OK_NO_TOLERANCE", "statusText": "Cluster is NOT tolerant to any failures. 1 member is not active", "topology": { "192.168.2.224:3306": { "address": "192.168.2.224:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "(MISSING)" }, "192.168.2.225:3306": { "address": "192.168.2.225:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "ONLINE" }, "192.168.2.226:3306": { "address": "192.168.2.226:3306", "mode": "R/W", "readReplicas": {}, "role": "HA", "status": "ONLINE" } } } }
勘悪く、R/Oの方にアクセスしてしまったようですね。
ダウンさせた1号機が(MISSING)となり、
代わりに3号機がR/Wになってます。
ここでルーター経由で更新をかけましょう。
(1号機が起動した時にそれも実行してくれるかどうか確かめるため)
[root@cent7-mysql57-1 ~]# mysql -uadmin -p -h192.168.2.221 -P6446 -e"insert into UCO.t1 values(null, now())" Enter password:
成功したか確認。
[root@innodb-cluster2 ~]# mysql -uadmin -padmin -e'select * from UCO.t1' mysql: [Warning] Using a password on the command line interface can be insecure. +----+---------------------+ | id | comment | +----+---------------------+ | 11 | 2017-04-23 06:44:41 | +----+---------------------+
無事入りましたね。
さあでは1号機を起動しましょう。
[root@innodb-cluster1 ~]# systemctl start mysqld.service
R/Wになっている3号機で状態確認。
mysql-js> cluster.status(); { "clusterName": "UCO_Cluster", "defaultReplicaSet": { "name": "default", "primary": "192.168.2.226:3306", "status": "OK_NO_TOLERANCE", "statusText": "Cluster is NOT tolerant to any failures. 1 member is not active", "topology": { "192.168.2.224:3306": { "address": "192.168.2.224:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "(MISSING)" }, "192.168.2.225:3306": { "address": "192.168.2.225:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "ONLINE" }, "192.168.2.226:3306": { "address": "192.168.2.226:3306", "mode": "R/W", "readReplicas": {}, "role": "HA", "status": "ONLINE" } } } }
どうやら勝手に起動したらクラスタにJOINするわけではないようですね。
cluster.help()とたたいてみたところでは、
rejoinInstanceというのがあるので、
これを使ってみましょう。
これはマニュアルの一番下にも記載がありますね。
mysql-js> cluster.rejoinInstance('icroot@192.168.2.224') Rejoining the instance to the InnoDB cluster. Depending on the original problem that made the instance unavailable, the rejoin operation might not be successful and further manual steps will be needed to fix the underlying problem. Please monitor the output of the rejoin operation and take necessary action if the instance cannot rejoin. Please provide the password for 'icroot@192.168.2.224': Rejoining instance to the cluster ... Cluster.rejoinInstance: Access denied for user 'root'@'innodb-cluster3' (using password: YES) (MySQL Error 1045) mysql-js>
・・・?。
Access denied for user ‘root‘@’innodb-cluster3’
とはどういうことだ。
そもそも自分でicrootユーザのパスワード聞いてきたじゃないか。
調べてみると、これは既知のバグでした。
https://bugs.mysql.com/bug.php?id=85567
しかも、Suggested fixを見ると、
「The node should be able to rejoin.」
・・・これは絶望的かもしれない。
やり取り用のユーザをrootにしておけばいいのかもしれないけど、
そこから作り直すのはイヤだ。
なんとかならんか・・・?
ヘルプを見ると、パスワードはrejoinInstanceのオプションで渡すこともできるとのこと。
(cluster.help(‘rejoinInstance’)でみれます)
これでいけるかもしれない!!!
mysql-js> cluster.rejoinInstance('icroot@192.168.2.224', {password: 'icroot'}) Rejoining the instance to the InnoDB cluster. Depending on the original problem that made the instance unavailable, the rejoin operation might not be successful and further manual steps will be needed to fix the underlying problem. Please monitor the output of the rejoin operation and take necessary action if the instance cannot rejoin. Rejoining instance to the cluster ... Cluster.rejoinInstance: Access denied for user 'root'@'innodb-cluster3' (using password: YES) (MySQL Error 1045) mysql-js>
短けえ夢だったなぁ・・・。
あきらめて作り直すか・・・。
(略) mysql-js> dba.configureLocalInstance(); Please provide the password for 'root@localhost:3306': Detecting the configuration file... Found configuration file at standard location: /etc/my.cnf Do you want to modify this file? [Y|n]: Y MySQL user 'root' cannot be verified to have access to other hosts in the network. 1) Create root@% with necessary grants 2) Create account with different name 3) Continue without creating account 4) Cancel Please select an option [1]: 1 Password for new account: Confirm password: Validating instance... (略)
ここをrootにしときゃ文句ないだろ?
さあ、同じところまでやり直して、もう一度試してみよう!
(やりなおしたら今度は2号機がR/Wになってました)
mysql-js> cluster.rejoinInstance('root@192.168.2.224') Rejoining the instance to the InnoDB cluster. Depending on the original problem that made the instance unavailable, the rejoin operation might not be successful and further manual steps will be needed to fix the underlying problem. Please monitor the output of the rejoin operation and take necessary action if the instance cannot rejoin. Please provide the password for 'root@192.168.2.224': Rejoining instance to the cluster ... The instance 'root@192.168.2.224:3306' was successfully rejoined on the cluster. The instance '192.168.2.224:3306' was successfully added to the MySQL Cluster. mysql-js> cluster.status() { "clusterName": "UCO_Cluster", "defaultReplicaSet": { "name": "default", "primary": "192.168.2.225:3306", "status": "OK", "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", "topology": { "192.168.2.224:3306": { "address": "192.168.2.224:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "ONLINE" }, "192.168.2.225:3306": { "address": "192.168.2.225:3306", "mode": "R/W", "readReplicas": {}, "role": "HA", "status": "ONLINE" }, "192.168.2.226:3306": { "address": "192.168.2.226:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "ONLINE" } } } }
よし!!!成功!!!
ちゃんと1号機に伝播したのか・・・?
[root@innodb-cluster1 ~]# mysql -uadmin -padmin -e'select * from UCO.t1' mysql: [Warning] Using a password on the command line interface can be insecure. +----+---------------------+ | id | comment | +----+---------------------+ | 3 | 2017-04-23 07:23:59 | +----+---------------------+
よしよし。
これで
1.R/Wサーバの障害
2.RouterによるR/W処理の引継ぎ
3.障害サーバ復旧後の再JOIN
まで確認できたわけだ。
基本的な挙動はこれでOKですね。
では更新中だとどうか?
こんなシェルを用意してみた。
i=1 ret=1 while [ ${i} -le 10000 ] do mysql -uadmin -padmin -h192.168.2.221 -P6446 -e"insert into UCO.t1 values(null, concat(@@hostname, ' ', now()))" ret=`echo $?` if test ${ret} -ne 0 then sleep 1 else i=`expr ${i} + 1` fi done
要はINSERTを続けるだけ。
さて、やってみますか。
[root@cent7-mysql57-1 ~]# sh -x insert_innodb_cluster.sh (実行中に) [root@innodb-cluster2 ~]# systemctl stop mysqld
さあどうなったか。
APサーバをながめていた感じ、
数秒止まって処理は再開したようにみえたが。
[root@innodb-cluster3 ~]# mysql -uadmin -padmin -e'select * from UCO.t1 order by id limit 2000' (略) | 12736 | innodb-cluster2 2017-04-23 08:19:56 | | 12743 | innodb-cluster2 2017-04-23 08:19:56 | | 12744 | innodb-cluster3 2017-04-23 08:19:59 | | 12751 | innodb-cluster3 2017-04-23 08:19:59 | (略)
狙い通り。
ホスト名をみても、autoincrementのidカラムをみても、
2号機から3号機に処理を引き継いでいることが分かる。
また、時刻を見ると、フェイルオーバーにわずか3秒しかかかっていないことが分かる。
もちろん、他に巨大なトランザクションを実行中だったりすると
もっとかかるケースもあるんだろうけど、
mysqlfailoverでは無風状態でも30秒くらいはかかってたから、
大分早くなってる。
これだけ早いと気になるのは誤検知に過敏すぎることですが、
これはハートビートの仕組みがわからないことにはなんとも言えない。
次はそのへんを調べてみたいところですね。
まあともあれ、これで簡単な挙動確認は一通りおしまいです。
あとは、死活監視の仕組みが気になります。
MHAやmysqlfailoverのように、単純にクエリを実行しているわけでもないようなので、
調べるのは大変かも知れないですが。
今日はここまで!
ありがとうございました!