お元気そうで残念です

仕事とか趣味のメモを残します

MySQL 5.7.23 で Group Replicationを構築しただけ

MySQL InnoDB Cluster 使いたいなー使いたいよね?ということで動作確認しようとしてハマりまくった際のメモ。
MySQL Shellで簡単に設定できませんでした。悲しい。
今回はMySQL Routerの設定はしません。

表記がわかりやすかったので、おおよその表記は「MySQL 8.0.13 で MySQL InnoDB Cluster を構築する」こちらのページを参考にさせていただいています。

環境

今回使用する環境は以下の通りです。

OS アプリ IP ホスト名
CentOS7 MySQL 5.7.23, MySQL Shell 8.0.16 192.168.10.101 node01
CentOS7 MySQL 5.7.23, MySQL Shell 8.0.16 192.168.10.102 node02
CentOS7 MySQL 5.7.23, MySQL Shell 8.0.16 192.168.10.103 node03

host名が[all_server] となっているコマンドはMySQLが動作しているすべてのnodeで実行します。 MySQLが5.7系列だとMySQL Shellはlocal環境で実行しないと設定の永続化が出来ないため、すべてのサーバにMySQL Shellをインストールする必要があります。

手元のPCにMySQL Shellのダウンロード

手元でMySQL Shellを実行したい場合はこの項を参考にしてください。
残念ながらMySQL 5.7系を使っていると手元で実行しても設定の永続化ができないので悲しくなります。

こちらのページ MySQL :: Download MySQL Shell からMySQL Shellをダウンロードして実行可能パスに配置してください。 今回はmacOSでダウンロードしました。

[mysqlsh] $ cd ~/Downloads
[mysqlsh] $ tar -zxvf mysql-shell-8.0.16-macos10.14-x86-64bit.tar.gz
[mysqlsh] $ mv mysql-shell-8.0.16-macos10.14-x86-64bit /usr/local/share/mysql-shell
[mysqlsh] $ ln -s /usr/local/share/mysql-shell/bin/* /usr/local/bin/*
[mysqlsh] $ mysqlsh --version
mysqlsh   Ver 8.0.16 for Darwin on x86_64 - for MySQL 8.0.16 (MySQL Community Server (GPL))

共通の設定

すべてのサーバで実行してください。

SELinuxを無効にします。無効にせずに利用する場合はこちらの記事「Group Replication 環境での SELinux / firewalld | スマートスタイル TECH BLOG|データベース&クラウドの最新技術情報を配信」を参考にしてください。

[all_server] $ sudo setenforce 0
[all_server] $ sudo sed -i -e 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

MySQL 5.7.23をインストールします。

[all_server] $ sudo rpm -ivh http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm
[all_server] $ cd /usr/local/src
[all_server] $ sudo wget https://downloads.mysql.com/archives/get/file/mysql-5.7.23-1.el7.x86_64.rpm-bundle.tar
[all_server] $ sudo tar -xvf mysql-5.7.23-1.el7.x86_64.rpm-bundle.tar
[all_server] $ sudo yum list installed | grep mysql
[all_server] $ sudo yum localinstall mysql-community-server-5.7.23-1.el7.x86_64.rpm \
mysql-community-client-5.7.23-1.el7.x86_64.rpm \
mysql-community-common-5.7.23-1.el7.x86_64.rpm \
mysql-community-devel-5.7.23-1.el7.x86_64.rpm \
mysql-community-libs-5.7.23-1.el7.x86_64.rpm \
mysql-community-libs-compat-5.7.23-1.el7.x86_64.rpm
[all_server] $ sudo yum list installed | grep mysql

バージョンが5.7.23になっていれば成功です。

MySQL Shell をインストールします。

[all_server] $ cd /usr/local/src
[all_server] $ sudo wget https://dev.mysql.com/get/Downloads/MySQL-Shell/mysql-shell-8.0.16-1.el7.x86_64.rpm
[all_server] $ sudo yum localinstall mysql-shell-8.0.16-1.el7.x86_64.rpm
[all_server] $ mysqlsh --version
mysqlsh   Ver 8.0.16 for Linux on x86_64 - for MySQL 8.0.16 (MySQL Community Server (GPL))

ユーザ権限を設定

Group Replicationに使うユーザの権限を設定します。ここではreplユーザを設定します。 すべてのサーバで設定してください。

[all_server] $ sudo systemctl start mysqld
mysql > SET SQL_LOG_BIN=0;
mysql > CREATE USER repl@'%' IDENTIFIED BY 'mysqlrepl';
mysql > SET SQL_LOG_BIN=1;
mysql > CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='mysqlrepl' FOR CHANNEL 'group_replication_recovery';
mysql > GRANT SELECT ON mysql_innodb_cluster_metadata.* TO 'repl'@'%';
mysql > GRANT SELECT ON performance_schema.global_status TO 'repl'@'%';
mysql > GRANT SELECT ON performance_schema.replication_applier_configuration TO 'repl'@'%';
mysql > GRANT SELECT ON performance_schema.replication_applier_status TO 'repl'@'%';
mysql > GRANT SELECT ON performance_schema.replication_applier_status_by_coordinator TO 'repl'@'%';
mysql > GRANT SELECT ON performance_schema.replication_applier_status_by_worker TO 'repl'@'%';
mysql > GRANT SELECT ON performance_schema.replication_connection_configuration TO 'repl'@'%';
mysql > GRANT SELECT ON performance_schema.replication_connection_status TO 'repl'@'%';
mysql > GRANT SELECT ON performance_schema.replication_group_member_stats TO 'repl'@'%';
mysql > GRANT SELECT ON performance_schema.replication_group_members TO 'repl'@'%';
mysql > GRANT SELECT ON performance_schema.threads TO 'repl'@'%' WITH GRANT OPTION;
mysql > FLUSH PRIVILEGES;

Group Replicationの設定

後はGroup ReplicationをStartして、Nodeを追加していくだけです。

1台目(Primary Node)

mysqlshでGroup Replicationの設定をしていきましょう。

[node1] $ mysqlsh --log-level=DEBUG3  --uri repl@node1:3306
 MySQL  node1:3306  JS > var cluster = dba.createCluster('myCluster')
A new InnoDB cluster will be created on instance 'repl@node1:3306'.

Validating instance at node1:3306...

This instance reports its own address as node1

Instance configuration is suitable.
Creating InnoDB cluster 'prodCluster' on 'repl@node1:3306'...

Adding Seed Instance...
WARNING: On instance 'node1:3306' membership change cannot be persisted since MySQL version 5.7.23 does not support the SET PERSIST command (MySQL version >= 8.0.11 required). Please use the <Dba>.configureLocalInstance() command locally to persist the changes.
Cluster successfully created. Use Cluster.addInstance() to add MySQL instances.
At least 3 instances are needed for the cluster to be able to withstand up to
one server failure.

 MySQL  node1:3306  JS > dba.configureLocalInstance()

ここまでで、Group Replicationのclusterを作成し、Primary NodeとなるNode1を登録、設定の永続化ができました。 続いて、2台目と3台目(ともにSecondary Node)を追加していきます。
とここでエラーが。

[node1] $ mysqlsh --log-level=DEBUG3  --uri repl@node1:3306
MySQL  node1:3306  JS > cluster = dba.getCluster()
MySQL  node1:3306  JS > cluster.addInstance('repl@node2:3306')
A new instance will be added to the InnoDB cluster. Depending on the amount of
data on the cluster this might take from a few seconds to several hours.

Adding instance to the cluster ...

Validating instance at node2:3306...

This instance reports its own address as node2

Instance configuration is suitable.
Cluster.addInstance: WARNING: Not running locally on the server and can not access its error log.
ERROR: 
Group Replication join failed.
ERROR: Error joining instance to cluster: 'node2:3306' - Query failed. MySQL Error (3092): ClassicSession.query: The server is not configured properly to be an active member of the group. Please see more details on error log.. Query: START group_replication: MySQL Error (3092): ClassicSession.query: The server is not configured properly to be an active member of the group. Please see more details on error log. (RuntimeError)

node2のmysqlにloginしてreplication状況を確認してみましょう。
START GROUP REPLICATION;していないとここではなんのレコードも出てきません。レコードがあるということはGroup Replicationの設定はできているはずです。

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST| MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+------------+-------------+--------------+
| group_replication_applier | 34ce3aed-a249-11e9-b3e8-fa163e4531c6 | node2 |        3306 | OFFLINE      |
+---------------------------+--------------------------------------+------------+-------------+--------------+

次にnode2でjournalctl -xeでエラーログを見てみましょう。

[node2] $ sudo journalctl -xe
...
... [ERROR] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. Local transactions: 34ce3aed-a249-11e9-b3e8-fa163e4531c6:1-105 > Group transactions: 440dd2c5-a22b-11e9-b851-fa163e47fb1b:1-26,
... [ERROR] Plugin group_replication reported: 'The member contains transactions not present in the group. The member will now exit the group.'
...

なんかtrancastionがあるらしいですね。 ここでnode2でおもむろにRESET MASTER;してみましょう。

[node2] $ sudo mysql -u root
mysql > RESET MASTER;

そして、node1でもう一度node2をaddしてみます。

[node1] $ mysqlsh --log-level=DEBUG3  --uri repl@node1:3306
MySQL  node1:3306  JS > var cluster = dba.getCluster();
MySQL  node1:3306  JS > cluster.addInstance('repl@node2:3306');
A new instance will be added to the InnoDB cluster. Depending on the amount of
data on the cluster this might take from a few seconds to several hours.

Adding instance to the cluster ...

Validating instance at node2:3306...

This instance reports its own address as node2

Instance configuration is suitable.
WARNING: On instance 'node2:3306' membership change cannot be persisted since MySQL version 5.7.23 does not support the SET PERSIST command (MySQL version >= 8.0.11 required). Please use the <Dba>.configureLocalInstance() command locally to persist the changes.
WARNING: On instance 'node2:3306' membership change cannot be persisted since MySQL version 5.7.23 does not support the SET PERSIST command (MySQL version >= 8.0.11 required). Please use the <Dba>.configureLocalInstance() command locally to persist the changes.
The instance 'repl@node2:3306' was successfully added to the cluster.

追加できたっぽいですね。念の為確認しましょう。
追加できているようです。

MySQL  node1:3306  JS > cluster.status()
{
    "clusterName": "myCluster", 
    "defaultReplicaSet": {
        "name": "default", 
        "primary": "node1:3306", 
        "ssl": "DISABLED", 
        "status": "OK_NO_TOLERANCE", 
        "statusText": "Cluster is NOT tolerant to any failures.", 
        "topology": {
            "node1:3306": {
                "address": "node1:3306", 
                "mode": "R/W", 
                "readReplicas": {}, 
                "role": "HA", 
                "status": "ONLINE"
            }, 
            "node2:3306": {
                "address": "node2:3306", 
                "mode": "R/O", 
                "readReplicas": {}, 
                "role": "HA", 
                "status": "ONLINE"
            }
        }, 
        "topologyMode": "Single-Primary"
    }, 
    "groupInformationSourceMember": "node1:3306"
}

このままだとnode2の設定の永続化ができていないのでやっていきます。

[node2] $ mysqlsh --log-level=DEBUG3  --uri repl@node2:3306
 MySQL  node2:3306  JS > dba.configureLocalInstance()
The instance 'node2:3306' belongs to an InnoDB cluster.

Detecting the configuration file...
Found configuration file at standard location: /etc/my.cnf
Do you want to modify this file? [y/N]: y
Persisting the cluster settings...
The instance 'node2:3306' was configured for use in an InnoDB cluster.

The instance cluster settings were successfully persisted.

同様にnode3も設定していきましょう。同じようなエラーに遭遇しても慌てずにいきましょう。

[node1] $ mysqlsh --log-level=DEBUG3  --uri repl@node1:3306
MySQL  node1:3306  JS > cluster = dba.getCluster()
MySQL  node1:3306  JS > cluster.addInstance('repl@node3:3306');

[node3] $ sudo mysql -u root
mysql > RESET MASTER;

[node1] $ mysqlsh --log-level=DEBUG3  --uri repl@node1:3306
MySQL  node1:3306  JS > cluster = dba.getCluster();
MySQL  node1:3306  JS > cluster.addInstance('repl@node3:3306');

[node3] $ mysqlsh --log-level=DEBUG3  --uri repl@node3:3306
MySQL  node3:3306  JS > dba.configureLocalInstance()
The instance 'node3:3306' belongs to an InnoDB cluster.

Detecting the configuration file...
Found configuration file at standard location: /etc/my.cnf
Do you want to modify this file? [y/N]: y
Persisting the cluster settings...
The instance 'node3:3306' was configured for use in an InnoDB cluster.

The instance cluster settings were successfully persisted.

[node1] $ mysqlsh --log-level=DEBUG3  --uri repl@node1:3306
MySQL  node1:3306  JS > cluster = dba.getCluster()
MySQL  node1:3306  JS > cluster.status()
{
    "clusterName": "myCluster", 
    "defaultReplicaSet": {
        "name": "default", 
        "primary": "node1:3306", 
        "ssl": "DISABLED", 
        "status": "OK_NO_TOLERANCE", 
        "statusText": "Cluster is NOT tolerant to any failures.", 
        "topology": {
            "node1:3306": {
                "address": "node1:3306", 
                "mode": "R/W", 
                "readReplicas": {}, 
                "role": "HA", 
                "status": "ONLINE"
            }, 
            "node2:3306": {
                "address": "node2:3306", 
                "mode": "R/O", 
                "readReplicas": {}, 
                "role": "HA", 
                "status": "ONLINE"
            }, 
            "node3:3306": {
                "address": "node3:3306", 
                "mode": "R/O", 
                "readReplicas": {}, 
                "role": "HA", 
                "status": "ONLINE"
            }
        }, 
        "topologyMode": "Single-Primary"
    }, 
    "groupInformationSourceMember": "node1:3306"
}

無事3台でGroup Replicationが構築できました。

次回は、Primary Nodeを止めてちゃんと切り替わるのか?、Primaryが死んだときやSecondaryが死んだときはどう復旧すればいいのかを確認していきます。

参考にしたサイト