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
# 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 (ログファイルにテンポラリパスワードが記録されているのでメモ)
# 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 (ログファイルにテンポラリパスワードが記録されているのでメモ)
# 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> 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> 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> 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> 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> 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
参考
- How To Configure MySQL Group Replication on Ubuntu 16.04 | DigitalOcean
- mita2 DB メモ: Group Replication を試す(4) リカバリ
- MySQL Group Replication - MySQL Casual Talk vol.10
- MySQL :: MySQL 5.7 Reference Manual :: 18 Group Replication
- MySQL :: MySQL 5.7 Reference Manual :: 18 Group Replication
- Paxosアルゴリズム - Wikipedia
- The Writings of Leslie Lamport
- paxos-code.html