dshimizu/blog

アルファ版

Ubuntu 16.04 LTSでMulti-PrimaryなMySQL Group Replication構築手順メモ

MySQLレプリケーションは、あるMySQLデータベースから、別のMySQLデータベースへデータや操作(DDL)を反映して複製を作成します。

従来のレプリケーションはプライマリ・セカンダリの構成となり、特定の1つのMySQLデータベースサーバ(マスター)のデータを、1つまたは複数のMySQLデータベースサーバー(スレーブ)に複製することでした。データは非同期、または準同期でマスターからスレーブへコピーされます。通常、マスターとなるデータベースサーバは読み取り書き込み操作を行うことができ、スレーブとなるデータベースサーバは読み取りのみで通常はデータ書き込みを実行できませんでした。マスターは1つのみとなるため、マスターの冗長化を行う場合にはクラスタリングソフトウェアを使うなどのアプローチが必要でした。

MySQL 5.7.17 で取り入れられた Group Replication は、より柔軟で可用性の高いレプリケーション構成するためのMySQLプラグインで、Group ReplicationはMySQL5.7.12で取り入れられた「Rapidプラグイン(新機能をプラグインとして提供するMySQL5.7.12からの仕組み)」として提供されているようです。 マスターデータベースの冗長化を目的とした機能で、マルチマスターのレプリケーション構成を行うための仕組みがMySQLの機能として実装されています。

グループ内で実行されたトランザクションを識別するためにGTIDを用いており、さらにXCOMと呼ばれる、Paxosという合意アルゴリズムをベースとした仕組みを用いて、グループ内のメンバーへのトランザクションのブロードキャストやメンバー間の認証の管理が行われているようです。

以下ではマルチマスタなGroupReplicationを構成するための基本的な手順を記載します。

構築手順

環境

OS Ubuntu 16.04 LTS
MySQL 5.7.18 (Oracle社オフィシャルパッケージ)

構成

1つのホストOS内に、複数のMySQLプロセスを異なるポート/データディレクトリで起動して、それらでGroup Replicationを構成します。

MySQL MySQLポート グループレプリケーション用ポート データディレクト
MySQL#01 24801 24901 /var/lib/mysql-01/
MySQL#02 24802 24902 /var/lib/mysql-02/
MySQL#03 24803 24903 /var/lib/mysql-03/

図で表すと以下のようになります。

MySQLのインストール

Ubuntu公式リポジトリMySQLパッケージではGroup Replicationが使えませんでしたので、MySQL公式ソフトウェアリポジトリからMySQL Community Server / Client の最新版を取得してインストールします。

以下から、MySQL公式APTリポジトリ設定用のパッケージを取得してそこからインストールするか、直接MySQLサーバ/クライアントパッケージを取得してインストールします。

MySQL公式APTリポジトリ設定用のパッケージを取得してインストールするには以下のコマンドを実行します。

# curl -OL https://dev.mysql.com/get/mysql-apt-config_0.8.6-1_all.deb

MySQL公式APTリポジトリ設定用のパッケージをインストールします。

# dpkg -i mysql-apt-config*

以下のような設定画面が出ますが、デフォルトのままOKを選択します。(後での変更も可能)

パッケージの設定
 lqqqqqqqqqqqqqqqqqqqu mysql-apt-config を設定しています tqqqqqqqqqqqqqqqqqqqk
 x MySQL APT Repo features MySQL Server along with a variety of MySQL        x
 x components. You may select the appropriate product to choose the version  x
 x that you wish to receive.                                                 x
 x                                                                           x
 x Once you are satisfied with the configuration then select last option     x
 x 'Apply' to save the configuration. Advanced users can always change the   x
 x configurations later, depending on their own needs.                       x
 x                                                                           x
 x Which MySQL product do you wish to configure?                             x
 x                                                                           x
 x          MySQL Server (Currently selected: mysql-5.7)                     x
 x          MySQL Tools & Connectors (Currently selected: Enabled)           x
 x          MySQL Preview Packages (Currently selected: Disabled)            x
 x          Ok                                                               x
 x                                                                           x
 x                                                                           x
 x                                  <Ok>                                     x
 x                                                                           x
 mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj

パッケージリストを更新します。

# apt update

MySQLのパッケージをインストールします。

# apt install mysql-server mysql-community-server

rootパスワードの入力を求められるので入力して設定します。

パッケージの設定

                                                                                
  lqqqqqqqqqqqqqqqu mysql-community-server を設定しています tqqqqqqqqqqqqqqqqk
  x Please provide a strong password that will be set for the root account   x
  x of your MySQL database. Leave it blank to enable password less login     x
  x using UNIX socket based authentication.                                  x
  x                                                                          x
  x Enter root password:                                                     x
  x                                                                          x
  x ________________________________________________________________________ x
  x                                                                          x
  x                                  <了解>                                  x
  x                                                                          x
  mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj

再度rootパスワードの入力を求められるので入力して設定します。

パッケージの設定
                                                                                
                                                                                
    lqqqqqqqqqqqqqu mysql-community-server を設定しています tqqqqqqqqqqqqqqk
    x Now that you have selected a password for the root account, please   x
    x confirm by typing it again. Do not share the password with anyone.   x
    x                                                                      x
    x Re-enter root password:                                              x
    x                                                                      x
    x ____________________________________________________________________ x
    x                                                                      x
    x                                <了解>                                x
    x                                                                      x
    mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj

以下のパッケージがインストールされていることを確認します。

# dpkg -l | grep mysql
ii  mysql-apt-config                   0.8.6-1                            all          Auto configuration for MySQL APT Repo.
ii  mysql-client                       5.7.18-1ubuntu16.04                amd64        MySQL Client meta package depending on latest version
ii  mysql-common                       5.7.18-1ubuntu16.04                amd64        MySQL Common
ii  mysql-community-client             5.7.18-1ubuntu16.04                amd64        MySQL Client
ii  mysql-community-server             5.7.18-1ubuntu16.04                amd64        MySQL Server
ii  mysql-server                       5.7.18-1ubuntu16.04                amd64        MySQL Server meta package depending on latest version

設定ファイル準備

MySQLをインストールしたら、以下のような3つの設定ファイルを準備します。 loose-group_replication_group_name には各サーバで一意な値 uuid を設定します。uuidgenコマンド等で作成したものを記載します。 もし、Single-Primaryモード(1台のサーバのみ書き込み可能で、その他は読み取り専用)で稼働させたい場合は loose-group_replication_single_primary_mode = OFF, loose-group_replication_enforce_update_everywhere_checks = ON の設定を削除 or コメントアウトします。

MySQL#01の設定ファイル(/etc/mysql/mysqld-01.cnf)

[mysqld_safe]
socket          = /tmp/mysqld-01.sock
nice            = 0

[mysqld]
#
# * Basic Settings
#
server_id = 100001
user            = mysql
pid-file        = /tmp/mysqld-01.pid
socket          = /tmp/mysqld-01.sock
port            = 24801
basedir         = /usr
datadir         = /var/lib/mysql-01/
tmpdir          = /tmp
skip-external-locking
slow_query_log          = 1
slow_query_log_file     = /var/log/mysql/mysql-01-slow.log
log-error       = /var/log/mysql/mysql-01-error.log
log_timestamps = SYSTEM
explicit_defaults_for_timestamp = true
#
# * Binary-log setting
#
log_bin = /var/log/mysql/gr-mysql-01-bin.log
binlog_format = ROW
#
# * General replication settings
#
gtid_mode = ON
enforce_gtid_consistency = ON
master_info_repository = TABLE
relay_log_info_repository = TABLE
binlog_checksum = NONE
log_slave_updates = ON
transaction_write_set_extraction = XXHASH64
loose-group_replication_bootstrap_group = OFF
loose-group_replication_start_on_boot = OFF
loose-group_replication_ssl_mode = DISABLED
loose-group_replication_recovery_use_ssl = 0
#
# * Replication group settings
#
loose-group_replication_group_name = "********-****-****-****-************"
loose-group_replication_ip_whitelist = "127.0.0.1"
loose-group_replication_group_seeds= "127.0.0.1:24901,127.0.0.1:24902,127.0.0.1:24903"
#
# * Multi-primary mode settings
#
loose-group_replication_single_primary_mode = OFF
loose-group_replication_enforce_update_everywhere_checks = ON
#
# * Host specific replication configuration
#
report_host = "127.0.0.1"
loose-group_replication_local_address= "127.0.0.1:24901"

MySQL#02の設定ファイル(/etc/mysql/mysqld-02.cnf)

[mysqld_safe]
socket          = /tmp/mysqld-02.sock
nice            = 0

[mysqld]
#
# * Basic Settings
#
server_id = 100002
user            = mysql
pid-file        = /tmp/mysqld-02.pid
socket          = /tmp/mysqld-02.sock
port            = 24802
basedir         = /usr
datadir         = /var/lib/mysql-02/
tmpdir          = /tmp
skip-external-locking
slow_query_log          = 1
slow_query_log_file     = /var/log/mysql/mysql-02-slow.log
log-error       = /var/log/mysql/mysql-02-error.log
log_timestamps = SYSTEM
explicit_defaults_for_timestamp = true
#
# * Binary-log setting
#
log_bin = /var/log/mysql/gr-mysql-02-bin.log
binlog_format = ROW
#
# * General replication settings
#
gtid_mode = ON
enforce_gtid_consistency = ON
master_info_repository = TABLE
relay_log_info_repository = TABLE
binlog_checksum = NONE
log_slave_updates = ON
transaction_write_set_extraction = XXHASH64
loose-group_replication_bootstrap_group = OFF
loose-group_replication_start_on_boot = OFF
loose-group_replication_ssl_mode = DISABLED
loose-group_replication_recovery_use_ssl = 0
#
# * Replication group settings
#
loose-group_replication_group_name = "********-****-****-****-************"
loose-group_replication_ip_whitelist = "127.0.0.1"
loose-group_replication_group_seeds= "127.0.0.1:24901,127.0.0.1:24902,127.0.0.1:24903"
#
# * Multi-primary mode settings
#
loose-group_replication_single_primary_mode = OFF
loose-group_replication_enforce_update_everywhere_checks = ON
#
# * Host specific replication configuration
#
report_host = "127.0.0.1"
loose-group_replication_local_address= "127.0.0.1:24902"

MySQL#03の設定ファイル(/etc/mysql/mysqld-03.cnf)

[mysqld_safe]
socket          = /tmp/mysqld-03.sock
nice            = 0

[mysqld]
#
# * Basic Settings
#
server_id = 100003
user            = mysql
pid-file        = /tmp/mysqld-03.pid
socket          = /tmp/mysqld-03.sock
port            = 24803
basedir         = /usr
datadir         = /var/lib/mysql-01/
tmpdir          = /tmp
skip-external-locking
slow_query_log          = 1
slow_query_log_file     = /var/log/mysql/mysql-03-slow.log
log-error       = /var/log/mysql/mysql-03-error.log
log_timestamps = SYSTEM
explicit_defaults_for_timestamp = true
#
# * Binary-log setting
#
log_bin = /var/log/mysql/gr-mysql-03-bin.log
binlog_format = ROW
#
# * General replication settings
#
gtid_mode = ON
enforce_gtid_consistency = ON
master_info_repository = TABLE
relay_log_info_repository = TABLE
binlog_checksum = NONE
log_slave_updates = ON
transaction_write_set_extraction = XXHASH64
loose-group_replication_bootstrap_group = OFF
loose-group_replication_start_on_boot = OFF
loose-group_replication_ssl_mode = DISABLED
loose-group_replication_recovery_use_ssl = 0
#
# * Replication group settings
#
loose-group_replication_group_name = "********-****-****-****-************"
loose-group_replication_ip_whitelist = "127.0.0.1"
loose-group_replication_group_seeds= "127.0.0.1:24901,127.0.0.1:24902,127.0.0.1:24903"
#
# * Multi-primary mode settings
#
loose-group_replication_single_primary_mode = OFF
loose-group_replication_enforce_update_everywhere_checks = ON
#
# * Host specific replication configuration
#
report_host = "127.0.0.1"
loose-group_replication_local_address= "127.0.0.1:24903"

MySQLデータディレクトリ初期化

単一ホスト内に異なるMySQLを起動する必要があるため、データディレクトリを分けます。 ここでは /var/lib/mysql-{01,02,03} としていますが、UbuntuではAppArmorによって/var/lib/mysql以外をデータディレクトリとて初期化しようとするとエラーになります。 まずは /etc/apparmor.d/usr.sbin.mysqld/var/lib/mysql-{01,02,03} をデータディレクトリとして扱えるように許可設定を行います。

# diff -u /etc/apparmor.d/usr.sbin.mysqld{.org,}
--- /etc/apparmor.d/usr.sbin.mysqld.org YYYY-MM-DD hh:mm:ss.000000000 +0900
+++ /etc/apparmor.d/usr.sbin.mysqld     YYYY-MM-DD hh:mm:ss.********* +0900
@@ -48,6 +48,10 @@
 # Allow data dir access
   /var/lib/mysql/ r,
   /var/lib/mysql/** rwk,
+  /var/lib/mysql-01/ r,
+  /var/lib/mysql-01/** rwk,
+  /var/lib/mysql-02/ r,
+  /var/lib/mysql-02/** rwk,
+  /var/lib/mysql-03/ r,
+  /var/lib/mysql-03/** rwk,

設定を反映します。

# apparmor_parser -r /etc/apparmor.d/usr.sbin.mysqld

MySQL#01のデータディレクトリを初期化します。

# install -d -o mysql -g mysql -m 700 /var/lib/mysql-01
# mysqld --defaults-file=/etc/mysql/mysqld-01.cnf --initialize --user=mysql --explicit_defaults_for_timestamp
(ログファイルにテンポラリパスワードが記録されているのでメモ)

MySQL#02のデータディレクトリを初期化します。

# install -d -o mysql -g mysql -m 700 /var/lib/mysql-02
# mysqld --defaults-file=/etc/mysql/mysqld-02.cnf --initialize --user=mysql --explicit_defaults_for_timestamp
(ログファイルにテンポラリパスワードが記録されているのでメモ)

MySQL#03のデータディレクトリを初期化します。

# install -d -o mysql -g mysql -m 700 /var/lib/mysql-03
# mysqld --defaults-file=/etc/mysql/mysqld-03.cnf --initialize --user=mysql --explicit_defaults_for_timestamp
(ログファイルにテンポラリパスワードが記録されているのでメモ)

MySQL起動

MySQL#01を起動します。

# mysqld --defaults-file=/etc/mysql/mysqld-01.cnf --user=mysql &

MySQL#02を起動します。

# mysqld --defaults-file=/etc/mysql/mysqld-02.cnf --user=mysql &

MySQL#03を起動します。

# mysqld --defaults-file=/etc/mysql/mysqld-03.cnf --user=mysql &

MySQL rootパスワード再設定

MySQL#01のrootパスワードを再設定します。

# mysql -u root -P 24801 --protocol=tcp -h localhost -p

mysql#01> set password for root@localhost=password('********');
Query OK, 0 rows affected, 1 warning (0.01 sec)

MySQL#02のrootパスワードを再設定します。

# mysql -u root -P 24802 --protocol=tcp -h localhost -p

mysql#02> set password for root@localhost=password('********');
Query OK, 0 rows affected, 1 warning (0.01 sec)

MySQL#03のrootパスワードを再設定します。

# mysql -u root -P 24803 --protocol=tcp -h localhost -p

mysql#03> set password for root@localhost=password('********');
Query OK, 0 rows affected, 1 warning (0.01 sec)

MySQL レプリケーション用ユーザ作成

MySQL#01にレプリケーション用のユーザを作成します。

mysql#01> SET SQL_LOG_BIN=0;

mysql#01> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%' IDENTIFIED BY '********';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql#01> SET SQL_LOG_BIN=1;

MySQL#02にレプリケーション用のユーザを作成します。

mysql#02> SET SQL_LOG_BIN=0;

mysql#02> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%' IDENTIFIED BY '********';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql#02> SET SQL_LOG_BIN=1;

MySQL#03にレプリケーション用のユーザを作成します。

mysql#03> SET SQL_LOG_BIN=0;

mysql#03> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%' IDENTIFIED BY '********';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql#03> SET SQL_LOG_BIN=1;

レプリケーション接続用パラメータ設定

MySQL#01にレプリケーション接続用の設定を行います。

mysql#01> RESET MASTER;

mysql#01> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='********' FOR CHANNEL 'group_replication_recovery';

※マニュアルでは以下の実行は必要とありますが、2台目、3台目はやらなくてもレプリケーション構成は組めました

mysql#02> RESET MASTER;

mysql#02> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='********' FOR CHANNEL 'group_replication_recovery';
mysql#03> RESET MASTER;

mysql#03> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='********' FOR CHANNEL 'group_replication_recovery';

Group Replicationプラグインの有効化

MySQL#01のGroup Replicationプラグインを有効化します。

mysql#01> select * from information_schema.plugins where plugin_name='group_replication'\G
Empty set (0.00 sec)

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

mysql#01> select * from information_schema.plugins where plugin_name='group_replication'\G
*************************** 1. row ***************************
           PLUGIN_NAME: group_replication
        PLUGIN_VERSION: 1.0
         PLUGIN_STATUS: ACTIVE
           PLUGIN_TYPE: GROUP REPLICATION
   PLUGIN_TYPE_VERSION: 1.1
        PLUGIN_LIBRARY: group_replication.so
PLUGIN_LIBRARY_VERSION: 1.7
         PLUGIN_AUTHOR: ORACLE
    PLUGIN_DESCRIPTION: Group Replication (1.0.0)
        PLUGIN_LICENSE: GPL
           LOAD_OPTION: ON
1 row in set (0.00 sec)

MySQL#02のGroup Replicationプラグインを有効化します。

mysql#02> select * from information_schema.plugins where plugin_name='group_replication'\G
Empty set (0.00 sec)

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

mysql#02> select * from information_schema.plugins where plugin_name='group_replication'\G
*************************** 1. row ***************************
           PLUGIN_NAME: group_replication
        PLUGIN_VERSION: 1.0
         PLUGIN_STATUS: ACTIVE
           PLUGIN_TYPE: GROUP REPLICATION
   PLUGIN_TYPE_VERSION: 1.1
        PLUGIN_LIBRARY: group_replication.so
PLUGIN_LIBRARY_VERSION: 1.7
         PLUGIN_AUTHOR: ORACLE
    PLUGIN_DESCRIPTION: Group Replication (1.0.0)
        PLUGIN_LICENSE: GPL
           LOAD_OPTION: ON
1 row in set (0.00 sec)

MySQL#03のGroup Replicationプラグインを有効化します。

mysql#03> select * from information_schema.plugins where plugin_name='group_replication'\G
Empty set (0.00 sec)

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

mysql#03> select * from information_schema.plugins where plugin_name='group_replication'\G
*************************** 1. row ***************************
           PLUGIN_NAME: group_replication
        PLUGIN_VERSION: 1.0
         PLUGIN_STATUS: ACTIVE
           PLUGIN_TYPE: GROUP REPLICATION
   PLUGIN_TYPE_VERSION: 1.1
        PLUGIN_LIBRARY: group_replication.so
PLUGIN_LIBRARY_VERSION: 1.7
         PLUGIN_AUTHOR: ORACLE
    PLUGIN_DESCRIPTION: Group Replication (1.0.0)
        PLUGIN_LICENSE: GPL
           LOAD_OPTION: ON
1 row in set (0.00 sec)

Group Replicationの開始

MySQL#01 で以下を実行します。 Group Replicationを起動する最初の1台目のみ、Group Replicationの開始前にgroup_replication_bootstrap_groupを有効化する必要があります。 (これをしないと、Group内のほかのサーバに接続しに行こうとして接続できずエラーとなり失敗します。)

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

mysql#01> START GROUP_REPLICATION;
Query OK, 0 rows affected (0.00 sec)

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

mysql#01> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24801 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
1 row in set (0.00 sec)

MySQL#01 へテスト用のデータベースを作成します。

mysql#01> CREATE DATABASE playground;
Query OK, 1 row affected (0.01 sec)

mysql#01> CREATE TABLE playground.equipment ( id INT NOT NULL AUTO_INCREMENT, type VARCHAR(50), quant INT, color VARCHAR(25), PRIMARY KEY(id));
Query OK, 0 rows affected (0.02 sec)

mysql#01> INSERT INTO playground.equipment (type, quant, color) VALUES ("slide", 2, "blue");
Query OK, 1 row affected (0.01 sec)

mysql#01> SELECT * FROM playground.equipment;
+----+-------+-------+-------+
| id | type  | quant | color |
+----+-------+-------+-------+
|  1 | slide |     2 | blue  |
+----+-------+-------+-------+
1 row in set (0.00 sec)

MySQL#02, MySQL#03 でも Group Replicationを開始します。 Group Replicationが正常に開始されたらMySQL#01で作成したテスト用のDBが存在することを確認します。

mysql#02> RESET MASTER;
Query OK, 1 row affected (0.01 sec)

mysql#02> START GROUP_REPLICATION;
Query OK, 0 rows affected (1.06 sec)

mysql#02> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24801 | ONLINE       |
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24802 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
2 rows in set (0.00 sec)

mysql#02> SELECT * FROM playground.equipment;
+----+-------+-------+-------+
| id | type  | quant | color |
+----+-------+-------+-------+
|  1 | slide |     2 | blue  |
+----+-------+-------+-------+
1 row in set (0.00 sec)
mysql#03> RESET MASTER;
Query OK, 1 row affected (0.01 sec)

mysql#03> start group_replication;
Query OK, 0 rows affected (1.88 sec)

mysql#03> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24801 | ONLINE       |
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24802 | ONLINE       |
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24803 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)

mysql#03> SELECT * FROM playground.equipment;
+----+-------+-------+-------+
| id | type  | quant | color |
+----+-------+-------+-------+
|  1 | slide |     2 | blue  |
+----+-------+-------+-------+
1 row in set (0.00 sec)

マルチマスタでの更新確認

マルチマスタであることを確認するためにMySQL#02での更新後に、他のサーバに更新データが反映されるかを試します。

mysql#02> CREATE DATABASE test;
Query OK, 1 row affected (0,00 sec)

mysql#02> use test
Database changed

mysql#02> CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL);
Query OK, 0 rows affected (0,00 sec)

mysql#02> INSERT INTO t1 VALUES (1, 'Luis');
Query OK, 1 row affected (0,01 sec)

mysql#02> SELECT * FROM test.t1;
+----+------+
| c1 | c2   |
+----+------+
|  1 | Luis |
+----+------+
1 row in set (0,00 sec)

ほかのサーバからも確認します。

mysql#03> SELECT * FROM test.t1;
+----+------+
| c1 | c2   |
+----+------+
|  1 | Luis |
+----+------+
1 row in set (0,00 sec)

これでGroup Replication環境を構築できました。

Group Replicationの停止

以下のコマンドで停止できます。

mysql#01> stop group_replication;
Query OK, 0 rows affected (0.01 sec)

Group Replicationの再開

停止中のマスターでトランザクションが実行されておらず、GTIDを追えれば以下で再度Groupに組み込まれます。

mysql#01> START GROUP_REPLICATION;
Query OK, 0 rows affected (1.06 sec)

Group Replicationの停止から再開まで

MySQL#01のレプリケーションを止めてみます。 止める前の状態は以下です。

mysql#01> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24801 | ONLINE       |
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24802 | ONLINE       |
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24803 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)

mysql#01> show global variables like 'GTID%';
+----------------------------------+---------------------------------------------------------------------------+
| Variable_name                    | Value                                                                     |
+----------------------------------+---------------------------------------------------------------------------+
| gtid_executed                    | ********-****-****-****-************:1-40:1000003-1000004:2000003-2000104 |
| gtid_executed_compression_period | 1000                                                                      |
| gtid_mode                        | ON                                                                        |
| gtid_owned                       |                                                                           |
| gtid_purged                      |                                                                           |
+----------------------------------+---------------------------------------------------------------------------+
5 rows in set (0.01 sec)

MySQL#01のレプリケーションを止めます。

mysql#01> stop group_replication;
Query OK, 0 rows affected (8.53 sec)
mysql> show global variables like 'GTID%';
+----------------------------------+---------------------------------------------------------------------------+
| Variable_name                    | Value                                                                     |
+----------------------------------+---------------------------------------------------------------------------+
| gtid_executed                    | ********-****-****-****-************:1-40:1000003-1000004:2000003-2000104 |
| gtid_executed_compression_period | 1000                                                                      |
| gtid_mode                        | ON                                                                        |
| gtid_owned                       |                                                                           |
| gtid_purged                      |                                                                           |
+----------------------------------+---------------------------------------------------------------------------+
5 rows in set (0.01 sec)

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24801 | OFFLINE      |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
1 row in set (0.00 sec)

稼働中のマスターに対して更新をかけます。 GTIDが更新(ここでは40->74)されています。

mysql#02> show global variables like 'GTID%';
+----------------------------------+---------------------------------------------------------------------------+
| Variable_name                    | Value                                                                     |
+----------------------------------+---------------------------------------------------------------------------+
| gtid_executed                    | ********-****-****-****-************:1-74:1000003-1000004:2000003-2000104 |
| gtid_executed_compression_period | 1000                                                                      |
| gtid_mode                        | ON                                                                        |
| gtid_owned                       |                                                                           |
| gtid_purged                      |                                                                           |
+----------------------------------+---------------------------------------------------------------------------+
5 rows in set (0.00 sec)

停止していたMySQL#01のグループレプリケーションを開始します。

mysql#01> start group_replication;
Query OK, 0 rows affected (2.36 sec)

mysql#01> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24801 | ONLINE       |
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24802 | ONLINE       |
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24803 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)

グループレプリケーションが開始されたことで、GTIDがさらに進み(74->75)ました。

mysql#01> show global variables like 'GTID%';
+----------------------------------+---------------------------------------------------------------------------+
| Variable_name                    | Value                                                                     |
+----------------------------------+---------------------------------------------------------------------------+
| gtid_executed                    | ********-****-****-****-************:1-75:1000003-1000004:2000003-2000104 |
| gtid_executed_compression_period | 1000                                                                      |
| gtid_mode                        | ON                                                                        |
| gtid_owned                       |                                                                           |
| gtid_purged                      |                                                                           |
+----------------------------------+---------------------------------------------------------------------------+
5 rows in set (0.01 sec)

ほかのマスターでも同一のGTIDになっていることを確認します。

mysql#02> show global variables like 'GTID%';
+----------------------------------+---------------------------------------------------------------------------+
| Variable_name                    | Value                                                                     |
+----------------------------------+---------------------------------------------------------------------------+
| gtid_executed                    | ********-****-****-****-************:1-75:1000003-1000004:2000003-2000104 |
| gtid_executed_compression_period | 1000                                                                      |
| gtid_mode                        | ON                                                                        |
| gtid_owned                       |                                                                           |
| gtid_purged                      |                                                                           |
+----------------------------------+---------------------------------------------------------------------------+
5 rows in set (0.01 sec)

Group Replicationの復旧

データが壊れてしまっていたような場合だと上記の手順ではGroup Replicationを再開できずエラーになってしまいます。その場合は、生きているマスターからdumpを取得 or バックアップのdumpを使って、停止しているマスターにデータを投入してGroup Replicationを再開します。

MySQL#01が障害発生中として、MySQL#03からmysqldumpでダンプ取得します。

# mysqldump --all-databases --lock-all-tables -uroot --triggers --routines --events -p -P 24803 --protocol=tcp > /tmp/dump.`date +%Y%m%d`.sql

従来のマスタースレーブ形式のレプリケーションだと復旧にはバイナリログのポジションを使っていましたが、マルチマスターのGroup ReplicationではダンプファイルにGTIDが記録されており、ダンプファイルに記録されているこれがリストア時に対象サーバに記録されて復旧に用いられます。

# grep GTID_PURGED /tmp/dump.sql
SET @@GLOBAL.GTID_PURGED='********-****-****-****-************:*-***'

MySQL#01を復旧させるしていると想定して、/tmp/dump.sqlを使ってリストアします。

mysql#01> stop group_replication;
Query OK, 0 rows affected (8.32 sec)

mysql#01> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24801 | OFFLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+

mysql#01> reset master;
Query OK, 0 rows affected (0.02 sec)
 
mysql#01> source /tmp/dump.sql
 
mysql#01> start group_replication;
Query OK, 0 rows affected (2.13 sec)

mysql#01> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24801 | ONLINE       |
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24802 | ONLINE       |
| group_replication_applier | ********-****-****-****-************ | 127.0.0.1   |       24803 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)

まとめ

マルチマスターでのGroup Replicationの構築手順を書きました。 Group Replicationを構成することで、MySQLの可用性をこれまで以上に高めることができそうなので、アーキテクチャの選択肢が増えたと思います。MySQLの標準機能としての高可用性機能が取り入れられたのはうれしいところです。MySQL Fabricみたいなことに(ry

参考