MySQL8.0.14 で、MySQL Shell を使用してオンラインで MySQL InnoDB Cluster の構成を変更できるようになりました。
(本記事の公開時点の最新バージョンは8.0.15です。)
今回は、構成変更する為の3機能について確認したいと思います。
概要
1. シングル・プライマリモードで稼働しているプライマリ・メンバーを切り替え
<cluster>.setPrimaryInstance()
2. シングル・プライマリモードからマルチ・プライマリモードに切り替え
<cluster>.switchToMultiPrimaryMode()
3. マルチ・プライマリモードからシングル・プライマリモードに切り替え
<cluster>.switchToSinglePrimaryMode()
※<cluster>は dba.getCluster()
で取得したオブジェクト
同様の機能で Group Replication の UDF で操作する機能が MySQL8.0.13 で追加されており、以下の弊社のブログでご紹介しております。
・ MySQL 8.0.13 で追加された、 Group Replication の UDF を使ってみる その1
・ MySQL 8.0.13 で追加された、 Group Replication の UDF を使ってみる その2
構成
VirtualBox+Vagrantを使用し、MySQL Router と MySQL Shell は同一サーバにインストールしています。
マシン | IP | ホスト名 |
---|---|---|
MySQL Router MySQL Shell |
192.168.33.10 | mysqlrouter8014 |
MySQL Server 1 | 192.168.33.11 | node8014-1 |
MySQL Server 2 | 192.168.33.12 | node8014-2 |
MySQL Server 3 | 192.168.33.13 | node8014-3 |
構成の状態確認
以下のように node8014-1 ~ node8014-3 のシングル・プライマリモードの3台構成で、 node8014-1 がプライマリの状態です。
1 2 3 4 5 6 7 8 9 |
mysql> SELECT * FROM performance_schema.replication_group_members; +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ | group_replication_applier | 38307911-1ede-11e9-a34a-0800278bc93f | node8014-2 | 3306 | ONLINE | SECONDARY | 8.0.14 | | group_replication_applier | 387754dc-1ede-11e9-bd4c-0800278bc93f | node8014-3 | 3306 | ONLINE | SECONDARY | 8.0.14 | | group_replication_applier | 3879d92a-1ede-11e9-af11-0800278bc93f | node8014-1 | 3306 | ONLINE | PRIMARY | 8.0.14 | +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ 3 rows in set (0.00 sec) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
MySQL node8014-1:33060+ ssl JS > cluster.status() { "clusterName": "mycluster", "defaultReplicaSet": { "name": "default", "primary": "node8014-1:3306", "ssl": "REQUIRED", "status": "OK", "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", "topology": { "node8014-1:3306": { "address": "node8014-1:3306", "mode": "R/W", "readReplicas": {}, "role": "HA", "status": "ONLINE" }, "node8014-2:3306": { "address": "node8014-2:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "ONLINE" }, "node8014-3:3306": { "address": "node8014-3:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "ONLINE" } }, "topologyMode": "Single-Primary" }, "groupInformationSourceMember": "node8014-1:3306" } |
1. シングル・プライマリモードで稼働しているプライマリ・メンバーを切り替え
[1.実行]
MySQL Shell で cluster.setPrimaryInstance()
を実行します。
引数には、同様機能となる Group Replication の UDF、group_replication_set_as_primary()
では MEMBER_ID(server_uuid)を指定する必要がありましたが、サーバ名もしくはIPアドレス+ポート番号の指定となります。
今回はプライマリにするメンバーとして node8014-2 を指定しています。
1 2 3 4 5 6 7 8 9 10 |
MySQL node8014-1:33060+ ssl JS > cluster.setPrimaryInstance('node8014-2:3306') Setting instance 'node8014-2:3306' as the primary instance of cluster 'mycluster'... Instance 'node8014-2:3306' was switched from SECONDARY to PRIMARY. Instance 'node8014-3:3306' remains SECONDARY. Instance 'node8014-1:3306' was switched from PRIMARY to SECONDARY. WARNING: The cluster internal session is not the primary member anymore. For cluster management operations please obtain a fresh cluster handle using <Dba>.getCluster(). The instance 'node8014-2:3306' was successfully elected as primary. |
(MySQL Shell で接続しているメンバーがプライマリでなくなった場合に、上記のような dba.getCluster() で cluster オブジェクトの再作成を促す、WARNINGメッセージが表示されるようです。)
[2.実行後]
1 2 3 4 5 6 7 8 9 |
mysql> SELECT * FROM performance_schema.replication_group_members; +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ | group_replication_applier | 38307911-1ede-11e9-a34a-0800278bc93f | node8014-2 | 3306 | ONLINE | PRIMARY | 8.0.14 | | group_replication_applier | 387754dc-1ede-11e9-bd4c-0800278bc93f | node8014-3 | 3306 | ONLINE | SECONDARY | 8.0.14 | | group_replication_applier | 3879d92a-1ede-11e9-af11-0800278bc93f | node8014-1 | 3306 | ONLINE | SECONDARY | 8.0.14 | +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ 3 rows in set (0.00 sec) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
MySQL node8014-1:33060+ ssl JS > cluster.status() { "clusterName": "mycluster", "defaultReplicaSet": { "name": "default", "primary": "node8014-2:3306", "ssl": "REQUIRED", "status": "OK", "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", "topology": { "node8014-1:3306": { "address": "node8014-1:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "ONLINE" }, "node8014-2:3306": { "address": "node8014-2:3306", "mode": "R/W", "readReplicas": {}, "role": "HA", "status": "ONLINE" }, "node8014-3:3306": { "address": "node8014-3:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "ONLINE" } }, "topologyMode": "Single-Primary" }, "groupInformationSourceMember": "node8014-1:3306" } |
指定したメンバー(node8014-2)がプライマリに変更されていることが確認できます。
[3.実行時点で接続されているセッションは?]
実行前から MySQL Router の R/W(プライマリへルーティング), R/O(セカンダリへルーティング)の Port を通して各メンバーに接続していると、セカンダリからプライマリになるメンバー(node8014-2)ではエラーも発生せず処理を継続できました。
しかし、プライマリからセカンダリになるメンバー(node8014-1)は接続が切られてしまいました。
・node8014-1への接続
1 2 3 4 5 6 7 8 9 10 11 |
mysql> show variables like 'hostname'; +---------------+------------+ | Variable_name | Value | +---------------+------------+ | hostname | node8014-1 | +---------------+------------+ 1 row in set (0.00 sec) mysql> show variables like 'hostname'; ERROR 2013 (HY000): Lost connection to MySQL server during query mysql> |
2. シングル・プライマリモードからマルチ・プライマリモードに切り替え
[1.実行]
MySQL Shell で cluster.switchToMultiPrimaryMode()
を実行し、マルチ・プライマリモードに変更してみます。
1 2 3 4 5 6 7 8 |
MySQL node8014-1:33060+ ssl JS > cluster.switchToMultiPrimaryMode() Switching cluster 'mycluster' to Multi-Primary mode... Instance 'node8014-2:3306' remains PRIMARY. Instance 'node8014-3:3306' was switched from SECONDARY to PRIMARY. Instance 'node8014-1:3306' was switched from SECONDARY to PRIMARY. The cluster successfully switched to Multi-Primary mode. |
[2.実行後]
1 2 3 4 5 6 7 8 9 |
mysql> SELECT * FROM performance_schema.replication_group_members; +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ | group_replication_applier | 38307911-1ede-11e9-a34a-0800278bc93f | node8014-2 | 3306 | ONLINE | PRIMARY | 8.0.14 | | group_replication_applier | 387754dc-1ede-11e9-bd4c-0800278bc93f | node8014-3 | 3306 | ONLINE | PRIMARY | 8.0.14 | | group_replication_applier | 3879d92a-1ede-11e9-af11-0800278bc93f | node8014-1 | 3306 | ONLINE | PRIMARY | 8.0.14 | +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ 3 rows in set (0.00 sec) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
MySQL node8014-1:33060+ ssl JS > cluster.status() { "clusterName": "mycluster", "defaultReplicaSet": { "name": "default", "ssl": "REQUIRED", "status": "OK", "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", "topology": { "node8014-1:3306": { "address": "node8014-1:3306", "mode": "R/W", "readReplicas": {}, "role": "HA", "status": "ONLINE" }, "node8014-2:3306": { "address": "node8014-2:3306", "mode": "R/W", "readReplicas": {}, "role": "HA", "status": "ONLINE" }, "node8014-3:3306": { "address": "node8014-3:3306", "mode": "R/W", "readReplicas": {}, "role": "HA", "status": "ONLINE" } }, "topologyMode": "Multi-Primary" }, "groupInformationSourceMember": "node8014-1:3306" } |
全てのメンバーがプライマリに変更されていることが確認できます。
1 2 3 4 5 6 7 |
mysql> SELECT topology_type FROM mysql_innodb_cluster_metadata.replicasets; +---------------+ | topology_type | +---------------+ | mm | +---------------+ 1 row in set (0.00 sec) |
InnoDB Cluster のメタ情報内にあるトポロジも変更されています。
※topology_type が pm
はシングルプライマリ・モード、mm
なら、マルチプライマリ・モードとなります。
[3.実行時点で接続されているセッションは?]
実行前から MySQL Router の R/W, R/O の Port を通して各メンバーに接続していると、全てのメンバーでエラーは発生せず処理を継続できました。
3. マルチ・プライマリモードからシングル・プライマリモードに切り替え
[1.実行]
MySQL Shell で cluster.switchToSinglePrimaryMode()
を実行し、シングル・プライマリモードに戻します。
引数には、cluster.setPrimaryInstance()
同様に、プライマリとするサーバ名もしくはIPアドレス+ポート番号を指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
MySQL node8014-1:33060+ ssl JS > cluster.switchToSinglePrimaryMode('node8014-2:3306') Switching cluster 'mycluster' to Single-Primary mode... Instance 'node8014-2:3306' remains PRIMARY. Instance 'node8014-3:3306' was switched from PRIMARY to SECONDARY. Instance 'node8014-1:3306' was switched from PRIMARY to SECONDARY. WARNING: The cluster internal session is not the primary member anymore. For cluster management operations please obtain a fresh cluster handle using <Dba>.getCluster(). WARNING: Existing connections that expected a R/W connection must be disconnected, i.e. instances that became SECONDARY. The cluster successfully switched to Single-Primary mode. MySQL node8014-1:33060+ ssl JS > |
(cluster.setPrimaryInstance()
同様に、dba.getCluster() で cluster オブジェクトの再作成を促すメッセージと、セカンダリになるメンバーへの接続が切られる旨のWARNINGメッセージが表示されます。)
[2.実行後]
1 2 3 4 5 6 7 8 9 |
mysql> SELECT * FROM performance_schema.replication_group_members; +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ | group_replication_applier | 38307911-1ede-11e9-a34a-0800278bc93f | node8014-2 | 3306 | ONLINE | PRIMARY | 8.0.14 | | group_replication_applier | 387754dc-1ede-11e9-bd4c-0800278bc93f | node8014-3 | 3306 | ONLINE | SECONDARY | 8.0.14 | | group_replication_applier | 3879d92a-1ede-11e9-af11-0800278bc93f | node8014-1 | 3306 | ONLINE | SECONDARY | 8.0.14 | +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ 3 rows in set (0.00 sec) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
MySQL node8014-1:33060+ ssl JS > cluster.status() { "clusterName": "mycluster", "defaultReplicaSet": { "name": "default", "primary": "node8014-2:3306", "ssl": "REQUIRED", "status": "OK", "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", "topology": { "node8014-1:3306": { "address": "node8014-1:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "ONLINE" }, "node8014-2:3306": { "address": "node8014-2:3306", "mode": "R/W", "readReplicas": {}, "role": "HA", "status": "ONLINE" }, "node8014-3:3306": { "address": "node8014-3:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "ONLINE" } }, "topologyMode": "Single-Primary" }, "groupInformationSourceMember": "node8014-1:3306" } |
1 2 3 4 5 6 7 |
mysql> SELECT topology_type FROM mysql_innodb_cluster_metadata.replicasets; +---------------+ | topology_type | +---------------+ | pm | +---------------+ 1 row in set (0.00 sec) |
シングル・プライマリモードに変更され、指定したメンバー(node8014-2)がプライマリとなっています。
[3.実行時点で接続されているセッションは?]
実行前から MySQL Router の R/W の Port を通して各メンバーに接続していると、プライマリからセカンダリになるメンバー(node8014-1, node8014-3)のみ接続が切られてしまいました。
・node8014-1への接続
1 2 3 4 5 6 7 8 9 10 |
mysql> show variables like 'hostname'; +---------------+------------+ | Variable_name | Value | +---------------+------------+ | hostname | node8014-1 | +---------------+------------+ 1 row in set (0.01 sec) mysql> show variables like 'hostname'; ERROR 2013 (HY000): Lost connection to MySQL server during query |
・node8014-3への接続
1 2 3 4 5 6 7 8 9 10 |
mysql> show variables like 'hostname'; +---------------+------------+ | Variable_name | Value | +---------------+------------+ | hostname | node8014-3 | +---------------+------------+ 1 row in set (0.00 sec) mysql> show variables like 'hostname'; ERROR 2013 (HY000): Lost connection to MySQL server during query |
まとめ
今回確認した機能は MySQL Shell 8.0.14 からの新機能となりますが、MySQL Server は、同機能のUDFが追加された 8.0.13 以上でないと使用できないようです。
試しに MySQL Shell のみを 8.0.14 とし、グループレプリケーションの MySQL Server を 8.0.12 とした場合、以下のようなエラーが発生しました。
1 2 |
MySQL 192.168.33.16:33060+ ssl JS > cluster.setPrimaryInstance('192.168.33.17:3306') Cluster.setPrimaryInstance: Operation not supported on target server version: '8.0.12' (RuntimeError) |
(MySQL Server を8.0.13にした場合は、正常に使用できました。)
確認結果を踏まえて、実行時に各メンバーで処理が行われていた場合には、以下のように処理が継続できない場合もあるので、注意が必要になります。
実行 | 切り替え実行時の挙動 |
---|---|
1.プライマリ・メンバーを切り替え cluster.setPrimaryInstance() |
プライマリからセカンダリに変更されるメンバーのみエラーが発生。セカンダリからプライマリに変更されるメンバーは処理を継続することが可能。 |
2.マルチ・プライマリモードに切り替え cluster.switchToMultiPrimaryMode() |
全てのメンバーが処理を継続することが可能。 |
3.シングル・プライマリモードに切り替え cluster.switchToSinglePrimaryMode() |
プライマリからセカンダリに変更されるメンバーのみエラーが発生。 |
とはいえ、InnoDB Cluster を気軽に構成を変更して検証できるのはうれしいですね。
マイナーバージョンアップにおいてもメンテナンスが入り、これからも機能追加や改善が進んでいくことを期待したいと思います。