CLOVER🍀

That was when it all began.

MySQL 8.0でGroup Replicationを構成してみる

MySQLには、5.7.17からGroup Replicationという機能が追加されています。

Changes in MySQL 5.7.17 (2016-12-12, General Availability)

5.7系のGAリリース後に追加された機能だったはずですが、そのまま試さずに8.0まできてしまったので、ここで1回
触ってみておこうかなぁと思いまして。

Group Replicationとは?

先に書いたように、MySQL 5.7.17で追加された新機能です。

Group Replication

参考)
MySQL Group Replication - MySQL Casual Talk vol.10

OSC 2017 Okinawa MySQL の高可用性構成比較 と新機能 Group Replication

第13回 MySQLグループレプリケーションのご紹介,PostgreSQLセキュリティ問題修正,PostgreSQL9.6Beta3, Beta4リリースのご紹介,Apache Cassandraバージョン3.8のリリース内容が確定:OSSデータベース取り取り時報|gihyo.jp … 技術評論社

MySQLのレプリケーション手法の違い | Yakst

mita2 DB メモ: Group Replication を試す(1) 導入編

ざっくり言うと、こんな感じのものみたいです。

  • MySQLでの高可用性ソリューション
    • ※性能向上は目的ではない
  • 自動リカバリ
  • Nodeの追加、削除が可能
  • 更新可能なNodeをひとつにすることも、複数にすることも可能(マルチマスター)

InnoDB Clusterの基盤にもなっており、ちょっと気になっていた機能なのです。

InnoDB Cluster

Group Replicationの要求事項は、こちらを参照。

Group Replication Requirements

  • InnoDBであること
  • Primary Key必須
  • IPv4のみ
  • 高速なネットワーク環境

あとは、バイナリログやGTIDなどについてが書かれています。

制限事項やよくある質問は、こちらを参照。

Group Replication Limitations

Frequently Asked Questions

ロックに関する注意事項や、Group Replicationは最大9 Nodeであることが書かれていたりします。

とりあえず今回は、環境を構成して軽く動かしてみることを目標にしてみます。

環境

確認環境は、次の通り。

MySQLは、APT Repositoryから、インストールしたものを使用しています。

Download MySQL APT Repository

Group Replicationは、全部で3 NodeのMySQLを使って構成することとしましょう。

Group Replication構成

ドキュメントに沿って設定、手順を踏んでいくと、だいたいOKです。

Deploying Group Replication in Single-Primary Mode

だいたい、と書いたのは、まあハマったこともあるわけですが…。

ドキュメントはSingle Primary Mode(更新可能なNodeがひとつだけ)で書かれていますが、マルチマスターは設定をひとつ変えることで実現できます。
というわけで、まずはSingle Primary Modeで構成してみます。

マルチマスター(Multi Primary Mode)については、また後で。

手順は、最初に起動するNodeと、あとからGroup Replicationに参加するNodeで異なります。

今回は3 Nodeなので、次のようなNode構成でいきます。

  • 初期Node … 172.17.0.2
  • 追加Node 2つ … 172.17.0.2〜3

初期Node

では、まずは最初に起動するNodeから見ていきましょう。

参照するドキュメントは、以下になります。

Configuring an Instance for Group Replication

User Credentials

Launching Group Replication

Group Replicationを構成するのに、最低限必要な情報は以下です(report-host除く)。

## gtid
gtid_mode = on
enforce_gtid_consistency = on

## binary log
binlog_checksum=NONE

## replication
server_id = 1

## group replication
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = "5f0e506a-58f3-4256-ba8b-78101b3b3b39"
loose-group_replication_start_on_boot = off
loose-group_replication_local_address = "172.17.0.2:24901"
loose-group_replication_group_seeds = "172.17.0.2:24901"
loose-group_replication_bootstrap_group = off
report-host = "172.17.0.2"

以下の設定も必要なのですが、MySQL 8.0.3以降はデフォルト値となっているそうな。

log_bin=binlog
log_slave_updates=ON
binlog_format=ROW
master_info_repository=TABLE
relay_log_info_repository=TABLE

いくつかの設定項目に「loose-」というprefixが付与されていますが、これはGroup Replicationのプラグインがロードされていなくても、エラーにならず起動するための
ものです。

The loose- prefix used for the group_replication variables above instructs the server to continue to start if the Group Replication plugin has not been loaded at the time the server is started.

https://dev.mysql.com/doc/refman/8.0/en/group-replication-configuring-instances.html

Group Replication関連の設定は、こちらを参照。

Group Replication System Variables

「group_replication_group_name」は、UUIDで設定する必要があります。今回は、uuidgenコマンドで作ったものを使用しました。この値は、Group Replicatonを
構成するNodeで同じにしておく必要があります。

loose-group_replication_group_name = "5f0e506a-58f3-4256-ba8b-78101b3b3b39"

「group_replication_start_on_boot」はサーバーの起動時にGroup Replicationのプラグインが自動的にレプリケーションを開始するかどうかなのですが、
これは今回は「off」にしています。最初にGroup Replicationの設定をする際には、offにしておく必要があるからです。

loose-group_replication_start_on_boot = off

Group Replicationの設定が済んでいれば、「group_replication_start_on_boot」をonにしておくと自動的にGroup Replicationが開始されます。

「group_replication_local_address」では、Group Replicationが使うアドレスとポートを指定します。ここでのアドレス/ポートの組み合わせは、
SQLアクセスと異なるもの(ポートは通例、3306)以外に設定する必要があります。

loose-group_replication_local_address = "172.17.0.2:24901"

「group_replication_group_seeds」では、Group Replicationのシードなるアドレス/ポートのペアを、「,」区切りで設定します。今回は最初のNode分なので、
自分自身のみにしておきました…。

loose-group_replication_group_seeds = "172.17.0.2:24901"

この設定は起動後にテーブルで管理され、Nodeの追加、削除に合わせて変えられていくので、あくまでGroup Replicationの初期Nodeです。

「group_replication_bootstrap_group」は、Groupの起動有無を設定します。

loose-group_replication_bootstrap_group = off

なんのこと?的な感じですが、Group Replicationのグループ自体を作る時や、Groupに参加しているNodeを全部停止してバックアップを取る時などに使うものの
ようです。Groupを起動するということはGroupを作るということであり、これを複数回実行すると、同じ名前の異なるGroupが複数個できてしまう、という
状態になるようです。

なので、最初の1 Nodeの時に有効化しておき、Groupが起動したらoffにします。この操作は、Group Replication構成時に行います。

「report-host」というのは、必須設定ではありません。performance_schema.replication_group_membersというテーブルでGroup Replicationに参加している
メンバーを確認する際に、デフォルトではホスト名なのですが、これを変更したい場合に使います。

report-host = "172.17.0.2"

今回は、ホスト名がうまく解決できない環境なので、IPアドレスを明示することとしました。

この状態で、MySQLを起動しておきます。

これで、ドキュメントのここまで来たことになります。

Configuring an Instance for Group Replication

続いて、こちら。

User Credentials

レプリケーション用のユーザーを作成。レプリケーション用のユーザーは「rpl_user」、パスワードは「password」とします。

mysql> SET SQL_LOG_BIN=0;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.54 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
Query OK, 0 rows affected (0.12 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

mysql> SET SQL_LOG_BIN=1;
Query OK, 0 rows affected (0.00 sec)

CHANGE MASTER。

mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='password' FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.28 sec)

Note (Code 1759): Sending passwords in plain text without SSL/TLS is extremely insecure.
Note (Code 1760): Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.

SSLTLSを有効にしていないので、ちょっと怒られてますが…ここは、そのままで。

Group Replicationの開始へ。

Launching Group Replication

プラグインのロード。

mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
Query OK, 0 rows affected (0.17 sec)

SHOW PLUGINSで、「group_replication」が追加されていることを確認します。

mysql> SHOW PLUGINS;
+----------------------------+----------+--------------------+----------------------+---------+
| Name                       | Status   | Type               | Library              | License |
+----------------------------+----------+--------------------+----------------------+---------+
| binlog                     | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| mysql_native_password      | ACTIVE   | AUTHENTICATION     | NULL                 | GPL     |
| sha256_password            | ACTIVE   | AUTHENTICATION     | NULL                 | GPL     |
| caching_sha2_password      | ACTIVE   | AUTHENTICATION     | NULL                 | GPL     |
| sha2_cache_cleaner         | ACTIVE   | AUDIT              | NULL                 | GPL     |
| CSV                        | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| MEMORY                     | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| InnoDB                     | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| INNODB_TRX                 | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_CMP                 | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_CMP_RESET           | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_CMPMEM              | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_CMPMEM_RESET        | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_CMP_PER_INDEX       | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_CMP_PER_INDEX_RESET | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_BUFFER_PAGE         | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_BUFFER_PAGE_LRU     | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_BUFFER_POOL_STATS   | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_TEMP_TABLE_INFO     | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_METRICS             | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_FT_DEFAULT_STOPWORD | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_FT_DELETED          | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_FT_BEING_DELETED    | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_FT_CONFIG           | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_FT_INDEX_CACHE      | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_FT_INDEX_TABLE      | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_TABLES              | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_TABLESTATS          | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_INDEXES             | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_TABLESPACES         | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_COLUMNS             | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_VIRTUAL             | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_CACHED_INDEXES      | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| MyISAM                     | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| MRG_MYISAM                 | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| PERFORMANCE_SCHEMA         | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| TempTable                  | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| ARCHIVE                    | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| BLACKHOLE                  | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| FEDERATED                  | DISABLED | STORAGE ENGINE     | NULL                 | GPL     |
| ngram                      | ACTIVE   | FTPARSER           | NULL                 | GPL     |
| mysqlx                     | ACTIVE   | DAEMON             | NULL                 | GPL     |
| mysqlx_cache_cleaner       | ACTIVE   | AUDIT              | NULL                 | GPL     |
| auth_socket                | ACTIVE   | AUTHENTICATION     | auth_socket.so       | GPL     |
| group_replication          | ACTIVE   | GROUP REPLICATION  | group_replication.so | GPL     |
+----------------------------+----------+--------------------+----------------------+---------+
45 rows in set (0.00 sec)

Group Replicationの開始。

mysql> SET GLOBAL group_replication_bootstrap_group=ON;
Query OK, 0 rows affected (0.00 sec)

mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (3.33 sec)

mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
Query OK, 0 rows affected (0.00 sec)

「group_replication_bootstrap_group」は最初に「ON」にして、「START GROUP_REPLICATION」後はすぐ「OFF」にします。

現在のGroup Replication参加Nodeを確認。

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 | c1cfe8f2-8737-11e8-b092-0242ac110002 | 172.17.0.2  |        3306 | ONLINE       | PRIMARY     | 8.0.11         |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
1 row in set (0.00 sec)

これで、Group Replicationが開始されました。

あとは、Nodeを足していけばいいのですが…なぜか、Group Replication用のユーザーで1度ログインしないと、この後のNode追加時に、追加されたNode側が
うまくGroup Replicationに参加できませんでした(「MEMBER_STATE」が「ONLINE」にならず、「RECOVERING」のまま進まない)。

追加Node

続いて、起動したGroup Replicationに対して、Nodeを追加していってみます。

参照するドキュメントは、以下になります。

Adding Instances to the Group

追加するNode、ひとつめ。

## gtid
gtid_mode = on
enforce_gtid_consistency = on

## binary log
binlog_checksum=NONE

## replication
server_id = 2

## group replication
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = "5f0e506a-58f3-4256-ba8b-78101b3b3b39"
loose-group_replication_start_on_boot = off
loose-group_replication_local_address = "172.17.0.3:24901"
loose-group_replication_group_seeds = "172.17.0.2:24901,172.17.0.3:24901,172.17.0.4:24901"
loose-group_replication_bootstrap_group = off
report-host = "172.17.0.3"

2つ目。

## gtid
gtid_mode = on
enforce_gtid_consistency = on

## binary log
binlog_checksum=NONE

## replication
server_id = 3

## group replication
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = "5f0e506a-58f3-4256-ba8b-78101b3b3b39"
loose-group_replication_start_on_boot = off
loose-group_replication_local_address = "172.17.0.4:24901"
loose-group_replication_group_seeds = "172.17.0.2:24901,172.17.0.3:24901,172.17.0.4:24901"
loose-group_replication_bootstrap_group = off
report-host = "172.17.0.4"

違いは、server_id、それから「loose-group_replication_local_address」と「report-host」。

loose-group_replication_local_address = "172.17.0.3:24901"
report-host = "172.17.0.3"

loose-group_replication_local_address = "172.17.0.4:24901"
report-host = "172.17.0.4"

「loose-group_replication_group_seeds」については、同じにしました。

loose-group_replication_group_seeds = "172.17.0.2:24901,172.17.0.3:24901,172.17.0.4:24901"

レプリケーション用のユーザー、「rpl_user」の作成から、CHANGE MASTERまで。

mysql> SET SQL_LOG_BIN=0;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.06 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
Query OK, 0 rows affected (0.02 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

mysql> SET SQL_LOG_BIN=1;
Query OK, 0 rows affected (0.00 sec)

mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='password' FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.19 sec)

Note (Code 1759): Sending passwords in plain text without SSL/TLS is extremely insecure.
Note (Code 1760): Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.

プラグインのロードと、Group Replicationの開始。

mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
Query OK, 0 rows affected (0.10 sec)

mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (4.26 sec)

ひとつ、Nodeを追加後。

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 | a3f74d6a-8c27-11e8-ac1c-0242ac110003 | 172.17.0.3  |        3306 | ONLINE       | SECONDARY   | 8.0.11         |
| group_replication_applier | c1cfe8f2-8737-11e8-b092-0242ac110002 | 172.17.0.2  |        3306 | ONLINE       | PRIMARY     | 8.0.11         |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
2 rows in set (0.00 sec)

2つ目のNodeを追加後。

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 | a3f74d6a-8c27-11e8-ac1c-0242ac110003 | 172.17.0.3  |        3306 | ONLINE       | SECONDARY   | 8.0.11         |
| group_replication_applier | a5f1669f-8c27-11e8-8910-0242ac110004 | 172.17.0.4  |        3306 | ONLINE       | SECONDARY   | 8.0.11         |
| group_replication_applier | c1cfe8f2-8737-11e8-b092-0242ac110002 | 172.17.0.2  |        3306 | ONLINE       | PRIMARY     | 8.0.11         |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
3 rows in set (0.00 sec)

3 NodeでのGroup Replicationとなりました。

Single Primary Modeなので、「MEMBER_ROLE」がひとつだけPRIMARY(最初のNode)で、それ以外は「SECONDARY」ですね。

確認

こちらに沿って、Group Replicationが構成されていることを確認してみましょう。

Launching Group Replication

Primary Nodeで。

mysql> CREATE DATABASE test;
Query OK, 1 row affected (0.03 sec)

mysql> USE test;
Database changed
mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL);
Query OK, 0 rows affected (0.25 sec)

mysql> INSERT INTO t1 VALUES (1, 'Luis');
Query OK, 1 row affected (0.06 sec)

追加されたNodeで確認。

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| test               |
+--------------------+
5 rows in set (0.00 sec)

mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| t1             |
+----------------+
1 row in set (0.00 sec)

mysql> select * from t1;
+----+------+
| c1 | c2   |
+----+------+
|  1 | Luis |
+----+------+
1 row in set (0.00 sec)

OKそうですね。

ちなみに、SECONDARYなROLEのNodeから更新しようとすると、エラーになります。

mysql> CREATE DATABASE test2;
ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement

mysql> INSERT INTO t1 VALUES (2, 'hoge');
ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement

Multi Primary Modeにしてみよう

ここまでで、Group Replicationの最初の第一歩的な確認をしてみましたが、最後にSingle Primary Modeではなく、Multi Primary Modeとして
構成してみます。

Multi-Primary Mode

環境としては、先ほどまでとは別に、再度新しく作りました。

変更するのは、Group Replicationの設定で、各Nodeに以下を追加します。

loose-group_replication_single_primary_mode = off

この値は、デフォルトで「on」なのでSingle Primary Modeになります。

こうすると、「MEMBER_ROLE」がすべて「PRIMARY」となります。

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 | 297582cb-8c2a-11e8-8265-0242ac110003 | 172.17.0.3  |        3306 | ONLINE       | PRIMARY     | 8.0.11         |
| group_replication_applier | 33f1ce00-8c2a-11e8-8a95-0242ac110004 | 172.17.0.4  |        3306 | ONLINE       | PRIMARY     | 8.0.11         |
| group_replication_applier | c1cfe8f2-8737-11e8-b092-0242ac110002 | 172.17.0.2  |        3306 | ONLINE       | PRIMARY     | 8.0.11         |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
3 rows in set (0.00 sec)

この状態では、いずれのNodeからも更新することができます。

とりあえず、構築完了、ということで…。