MySQL InnoDBクラスターは3つのコンポーネントで構成されています:
- MySQLグループレプリケーション(フォールトトレランスを使用して相互にレプリケートするデータベースサーバーのグループ)。
- MySQLルーター(正常なデータベースノードへのルーターのクエリ)
- MySQLシェル(ヘルパー、クライアント、構成ツール)
このウォークスルーの最初の部分では、MySQLInnoDBクラスターをデプロイします。オンラインで利用できる実践的なチュートリアルは多数ありますが、このウォークスルーでは、クラスターを1か所にインストールして実行するために必要なすべての手順/コマンドについて説明します。このブログ投稿の後半では、監視、管理、スケーリングの操作と、MySQLInnoDBクラスターを扱う際のいくつかの落とし穴について説明します。
次の図は、展開後のアーキテクチャを示しています。
合計4つのノードをデプロイします。 3ノードのMySQLグループレプリケーションと1つのMySQLルーターノードがアプリケーションサーバー内に同じ場所に配置されています。すべてのサーバーはUbuntu18.04Bionicで実行されています。
以下のステップは、すべてのデータベース・ノードdb1、db2、およびdb3で実行する必要があります。
まず、ホストマッピングを行う必要があります。これは、ホスト名をInnoDBクラスターのホスト識別子として使用する場合に重要であり、これが推奨される方法です。すべてのホストを/etc/ hosts内で次のようにマップします:
$ vi /etc/hosts
192.168.10.40 router apps
192.168.10.41 db1 db1.local
192.168.10.42 db2 db2.local
192.168.10.43 db3 db3.local
127.0.0.1 localhost localhost.localdomain
AppArmorを停止して無効にします:
$ service apparmor stop
$ service apparmor teardown
$ systemctl disable apparmor
$ wget https://repo.mysql.com/apt/ubuntu/pool/mysql-apt-config/m/mysql-apt-config/mysql-apt-config_0.8.14-1_all.deb
パッケージをインストールし、「mysql-8.0」用に構成します。
$ dpkg -i mysql-apt-config_0.8.14-1_all.deb
GPGキーをインストールします:
$ apt-key adv --recv-keys --keyserver ha.pool.sks-keyservers.net 5072E1F5
リポジトリを更新する:
$ apt-get update
Pythonをインストールし、続いてMySQLサーバーとMySQLシェルをインストールします。
$ apt-get -y install mysql-server mysql-shell
次の構成ウィザードが表示されます。
- rootパスワードを設定する-MySQLrootユーザーの強力なパスワードを指定します。
- 認証方法を設定する-[従来の認証方法を使用する(MySQL 5.xの互換性を維持する)]を選択します
この時点でMySQLがインストールされているはずです。確認方法:
$ systemctl status mysql
「アクティブ(実行中)」状態になっていることを確認してください。
InnoDBクラスター用のサーバーの準備
以下のステップは、すべてのデータベース・ノードdb1、db2、およびdb3で実行する必要があります。
グループレプリケーションをサポートするようにMySQLサーバーを構成します。これを行うための最も簡単で推奨される方法は、新しいMySQLシェルを使用することです。
$ mysqlsh
以下の例に示すように、ローカルrootユーザーとして認証し、それに応じて構成ウィザードに従います。
MySQL JS > dba.configureLocalInstance("[email protected]:3306");
認証されると、次のようないくつかの質問が表示されます。
これらの質問への回答と次の回答:
- アカウント名:[email protected]%
- パスワード:mys3cret &&
- パスワードの確認:mys3cret &&
- 必要な構成変更を実行しますか?:y
- インスタンスを構成した後、インスタンスを再起動しますか?:y
すべてのデータベースノードで上記を繰り返すことを忘れないでください。この時点で、MySQLデーモンはすべてのIPアドレスをリッスンしているはずであり、グループレプリケーションが有効になっています。これで、クラスターの作成に進むことができます。
これで、クラスターを作成する準備が整いました。 db1で、MySQLシェルからクラスター管理者として接続します:
MySQL|JS> shell.connect('[email protected]:3306');
Creating a session to '[email protected]:3306'
Please provide the password for '[email protected]:3306': ***********
Save password for '[email protected]:3306'? [Y]es/[N]o/Ne[v]er (default No): Y
Fetching schema names for autocompletion... Press ^C to stop.
Your MySQL connection id is 9
Server version: 8.0.18 MySQL Community Server - GPL
No default schema selected; type \use <schema> to set one.
<ClassicSession:[email protected]:3306>
[email protected]として接続する必要があります(「>」の前のプロンプト文字列を見るとわかります)。これで、新しいクラスターを作成できます:
MySQL|db1:3306 ssl|JS> cluster = dba.createCluster('my_innodb_cluster');
MySQL|db1:3306 ssl|JS> cluster.status()
{
"clusterName": "my_innodb_cluster",
"defaultReplicaSet": {
"name": "default",
"primary": "db1:3306",
"ssl": "REQUIRED",
"status": "OK_NO_TOLERANCE",
"statusText": "Cluster is NOT tolerant to any failures.",
"topology": {
"db1:3306": {
"address": "db1:3306",
"mode": "R/W",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.18"
}
},
"topologyMode": "Single-Primary"
},
"groupInformationSourceMember": "db1:3306"
}
この時点では、db1のみがクラスターの一部です。デフォルトのトポロジモードはシングルプライマリです。これは、一度に1つのノードのみがライターであるレプリカセットの概念に似ています。クラスター内の残りのノードはリーダーになります。
OK_NO_TOLERANCEと表示されているクラスターのステータスと、statusTextキーの下の詳細な説明に注意してください。レプリカセットの概念では、1つのノードはフォールトトレランスを提供しません。プライマリノードのフェイルオーバーを自動化するには、最低3つのノードが必要です。これについては後で調べます。
次に、2番目のノードdb2を追加し、デフォルトのリカバリー方法「クローン」を受け入れます。
MySQL|db1:3306 ssl|JS> cluster.addInstance('[email protected]:3306');
次のスクリーンショットは、上記のコマンドを実行した後のdb2の初期化の進行状況を示しています。同期操作はMySQLによって自動的に実行されます:
クラスターとdb2の状況を確認してください:
MySQL|db1:3306 ssl|JS> cluster.status()
{
"clusterName": "my_innodb_cluster",
"defaultReplicaSet": {
"name": "default",
"primary": "db1:3306",
"ssl": "REQUIRED",
"status": "OK_NO_TOLERANCE",
"statusText": "Cluster is NOT tolerant to any failures.",
"topology": {
"db1:3306": {
"address": "db1:3306",
"mode": "R/W",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.18"
},
"db2:3306": {
"address": "db2:3306",
"mode": "R/O",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.18"
}
},
"topologyMode": "Single-Primary"
},
"groupInformationSourceMember": "db1:3306"
}
この時点で、クラスターにはdb1とdb2の2つのノードがあります。ステータスはまだOK_NO_TOLERANCEを示しており、statusText値の下にさらに説明があります。上記のように、MySQLグループレプリケーションでは、フォールトトレランスのためにクラスター内に少なくとも3つのノードが必要です。そのため、次に示すように3番目のノードを追加する必要があります。
最後のノードdb3を追加し、db2と同様のデフォルトのリカバリー方法「クローン」を受け入れます。
MySQL|db1:3306 ssl|JS> cluster.addInstance('[email protected]:3306');
次のスクリーンショットは、上記のコマンドを実行した後のdb3の初期化の進行状況を示しています。同期操作はMySQLによって自動的に実行されます:
MySQL|db1:3306 ssl|JS> cluster.status()
{
"clusterName": "my_innodb_cluster",
"defaultReplicaSet": {
"name": "default",
"primary": "db1:3306",
"ssl": "REQUIRED",
"status": "OK",
"statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
"topology": {
"db1:3306": {
"address": "db1:3306",
"mode": "R/W",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.18"
},
"db2:3306": {
"address": "db2:3306",
"mode": "R/O",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.18"
},
"db3:3306": {
"address": "db3:3306",
"mode": "R/O",
"readReplicas": {},
"replicationLag": null,
"role": "HA",
"status": "ONLINE",
"version": "8.0.18"
}
},
"topologyMode": "Single-Primary"
},
"groupInformationSourceMember": "db1:3306"
}
これで、クラスターは良好に見えます。ステータスはOKであり、クラスターは一度に最大1つの障害ノードに耐えることができます。プライマリノードはdb1で、「primary」:「db1:3306」および「mode」:「R / W」を示し、他のノードは「R/O」状態です。 ROノードのread_onlyとsuper_read_onlyの値を確認すると、両方ともtrueとして表示されています。
これで、MySQLグループレプリケーションの展開が完了し、同期されました。
アプリケーションを実行するアプリサーバーで、ホストマッピングが正しいことを確認します。
$ vim /etc/hosts
192.168.10.40 router apps
192.168.10.41 db1 db1.local
192.168.10.42 db2 db2.local
192.168.10.43 db3 db3.local
127.0.0.1 localhost localhost.localdomain
AppArmorを停止して無効にします:
$ service apparmor stop
$ service apparmor teardown
$ systemctl disable apparmor
次に、データベースのインストールを実行するときに行ったのと同様に、MySQLリポジトリパッケージをインストールします。
$ wget https://repo.mysql.com/apt/ubuntu/pool/mysql-apt-config/m/mysql-apt-config/mysql-apt-config_0.8.14-1_all.deb
$ dpkg -i mysql-apt-config_0.8.14-1_all.deb
GPGキーを追加します:
$ apt-key adv --recv-keys --keyserver ha.pool.sks-keyservers.net 5072E1F5
リポジトリリストを更新します:
$ apt-get update
MySQLルーターとクライアントをインストールします:
$ apt-get -y install mysql-router mysql-client
MySQLルーターが/usr/ bin/mysqlrouterの下にインストールされました。 MySQLルーターは、MySQLInnoDBクラスターでルーターの動作を自動的に構成するためのブートストラップフラグを提供します。実行する必要があるのは、データベースノードの1つに文字列URIをInnoDBクラスター管理ユーザー(clusteradmin)として指定することです。
構成を簡素化するために、rootユーザーとしてmysqlrouterプロセスを実行します。
$ mysqlrouter --bootstrap [email protected]:3306 --directory myrouter --user=root
clusteradminユーザーのパスワードを指定した後に取得する必要があるものは次のとおりです。
bootstrapコマンドは、/ root / myrouter/mysqlrouter.confにルーター構成ファイルを生成するのに役立ちます。これで、現在のディレクトリから次のコマンドを使用してmysqlrouterデーモンを起動できます。
$ myrouter/start.sh
予想されるポートが正しくリッスンしているかどうかを確認します。
$ netstat -tulpn | grep mysql
tcp 0 0 0.0.0.0:6446 0.0.0.0:* LISTEN 14726/mysqlrouter
tcp 0 0 0.0.0.0:6447 0.0.0.0:* LISTEN 14726/mysqlrouter
tcp 0 0 0.0.0.0:64470 0.0.0.0:* LISTEN 14726/mysqlrouter
tcp 0 0 0.0.0.0:64460 0.0.0.0:* LISTEN 14726/mysqlrouter
これで、アプリケーションはポート6446を読み取り/書き込みに使用でき、6447を読み取り専用のMySQL接続に使用できます。
マスターノードにデータベースユーザーを作成しましょう。 db1で、MySQLシェルを介してMySQLサーバーに接続します。
$ mysqlsh [email protected]:3306
JavascriptモードからSQLモードに切り替えます:
MySQL|localhost:3306 ssl|JS> \sql
Switching to SQL mode... Commands end with ;
データベースを作成します:
MySQL|localhost:3306 ssl|SQL> CREATE DATABASE sbtest;
データベースユーザーを作成します:
MySQL|localhost:3306 ssl|SQL> CREATE USER [email protected]'%' IDENTIFIED BY 'password';
ユーザーにデータベースへのアクセスを許可します:
MySQL|localhost:3306 ssl|SQL> GRANT ALL PRIVILEGES ON sbtest.* TO [email protected]'%';
これで、データベースとユーザーの準備が整いました。 sysbenchをインストールして、いくつかのテストデータを生成しましょう。アプリサーバーで、次の操作を行います。
$ apt -y install sysbench mysql-client
これで、アプリサーバーでテストして、MySQLルーター経由でMySQLサーバーに接続できます。書き込み接続の場合は、ルーターホストのポート6446に接続します。
$ mysql -usbtest -p -h192.168.10.40 -P6446 -e 'select user(), @@hostname, @@read_only, @@super_read_only'
+---------------+------------+-------------+-------------------+
| user() | @@hostname | @@read_only | @@super_read_only |
+---------------+------------+-------------+-------------------+
| [email protected] | db1 | 0 | 0 |
+---------------+------------+-------------+-------------------+
読み取り専用接続の場合は、ルーターホストのポート6447に接続します。
$ mysql -usbtest -p -h192.168.10.40 -P6447 -e 'select user(), @@hostname, @@read_only, @@super_read_only'
+---------------+------------+-------------+-------------------+
| user() | @@hostname | @@read_only | @@super_read_only |
+---------------+------------+-------------+-------------------+
| [email protected] | db3 | 1 | 1 |
+---------------+------------+-------------+-------------------+
いいね。これで、sysbenchを使用していくつかのテストデータを生成できます。アプリサーバーで、アプリサーバーのポート6446に接続して、テーブルあたり100,000行のテーブルを20個生成します。
$ sysbench \
/usr/share/sysbench/oltp_common.lua \
--db-driver=mysql \
--mysql-user=sbtest \
--mysql-db=sbtest \
--mysql-password=password \
--mysql-port=6446 \
--mysql-host=192.168.10.40 \
--tables=20 \
--table-size=100000 \
prepare
ポート6446で300秒間簡単な読み取り/書き込みテストを実行するには、次のコマンドを実行します。
$ sysbench \
/usr/share/sysbench/oltp_read_write.lua \
--report-interval=2 \
--threads=8 \
--time=300 \
--db-driver=mysql \
--mysql-host=192.168.10.40 \
--mysql-port=6446 \
--mysql-user=sbtest \
--mysql-db=sbtest \
--mysql-password=password \
--tables=20 \
--table-size=100000 \
run
読み取り専用ワークロードの場合、MySQL接続をポート6447に送信できます:
$ sysbench \
/usr/share/sysbench/oltp_read_only.lua \
--report-interval=2 \
--threads=1 \
--time=300 \
--db-driver=mysql \
--mysql-host=192.168.10.40 \
--mysql-port=6447 \
--mysql-user=sbtest \
--mysql-db=sbtest \
--mysql-password=password \
--tables=20 \
--table-size=100000 \
run