MySQL道普請便り

第83回 マルチソースレプリケーション

この記事を読むのに必要な時間:およそ 4 分

MySQLはバージョン5.7とそれ以降で,マルチソースレプリケーションができるようになりました。マルチソースレプリケーションを利用することで,複数のデータベースをマスターとしてレプリケーションを構築することが可能となります。過去にシャーディングしていたデータの再統合や集約データベースの作成など,構成次第でさまざまなデータベースを作成することができます。

今回はそんなマルチソースレプリケーションについて紹介します。

マルチソースレプリケーションのイメージ

マルチソースレプリケーションのイメージ

マルチソースレプリケーションの準備

統合するスレーブ側でマルチソースレプリケーションを有効にするためには,master_info_repositoryとrelay_log_info_repositoryのtypeをTABLEとする必要があります。

スレーブ側が持つリレーログの情報は,mysql.slave_relay_log_infoに挿入されます。バージョン8.0.2とそれ以降のバージョンでは,master_info_repositoryとrelay_log_info_repositoryはデフォルトでTABLEに変更されました。slave_relay_log_infoの詳細については第53回 リレーログファイルについてをご確認ください。

続いて,スレーブ側に統合するデータベースを作成します。データの投入については,各マスターとなるデータベースからmysqldumpコマンドなどを用いてデータを取得し,スレーブ側に投入します。

最後に,マスター情報をスレーブ側に提供するCHANGE MASTER TO構文を実施します。マルチソースレプリケーションを実施する時は,CHANGE MASTER TO構文にFOR CHANNEL チャネル名をつけて実施します。このCHANNELは各マスターとの通信するchannel名で,各マスターそれぞれに違う名前をつけて実施します。

各masterにchennel名をmydatabase1~3と名付けてCHANGE MASTER TO構文を実施する

mysql> CHANGE MASTER TO master_host='127.0.0.1',
    -> master_port= 3306,
    -> master_user='repl',
    -> master_password='repl',
    -> master_log_file='mysql-bin.000022',
    -> master_log_pos=195
    -> FOR CHANNEL 'mydatabase1';
Query OK, 0 rows affected, 2 warnings (0.28 sec)

mysql> CHANGE MASTER TO master_host='127.0.0.1',
    -> master_port= 3308,
    -> master_user='repl',
    -> master_password='repl',
    -> master_log_file='mysql-bin.000003',
    -> master_log_pos=195
    -> FOR CHANNEL 'mydatabase2';
Query OK, 0 rows affected, 2 warnings (0.28 sec)

mysql> CHANGE MASTER TO master_host='127.0.0.1',
    -> master_port= 3310,
    -> master_user='repl',
    -> master_password='repl',
    -> master_log_file='mysql-bin.000010',
    -> master_log_pos=195
    -> FOR CHANNEL 'mydatabase3';
Query OK, 0 rows affected, 2 warnings (0.28 sec)

マルチソースレプリケーションの運用

今,CHANGE MASTER TO構文を利用して3つのMySQL(ポートが3306,3308,3310)をmydatabase1~3というチャネル名にしてマルチソースレプリケーション構成にしました。

では実際にmydatabase1にd1スキーマ,mydatabase2にd2スキーマを作ってスレーブ側でSHOW DATABASES構文を実施してみます。なお,下記プロンプト名はそれぞれのデータベースを指します。

slave> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.09 sec)

mydatabase1> CREATE DATABASE d1;
Query OK, 1 row affected (0.14 sec)

mydatabase2> CREATE DATABASE d2;
Query OK, 1 row affected (0.22 sec)

slave> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| d1                 |
| d2                 |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
6 rows in set (0.13 sec)

マルチソースレプリケーションを介してslave側にはd1,d2スキーマが作成されました。もちろんmydatabase1にはd2スキーマはありませんし,mydatabase2にはd1スキーマはありません。

各チャネルのレプリケーションステータスを確認するには,SHOW SLAVE STATUS FOR CHANNEL channel名を実施します。

SLAVE> SHOW SLAVE STATUS FOR CHANNEL 'mydatabase1'\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 127.0.0.1
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000023
          Read_Master_Log_Pos: 368
               Relay_Log_File: mysql-relay-mydatabase1.000003
                Relay_Log_Pos: 495
        Relay_Master_Log_File: mysql-bin.000023
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
(中略)
                 Channel_Name: mydatabase1
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 0
1 row in set (0.00 sec)

channel名を指定せず,従来通りSHOW SLAVE STATUSを実施すると,すべてのCAHNNELのレプリケーションステータスが表示されます。また,上記情報はperfomance_schemaにあるreplication_applier_*とreplication_connection_*で確認することができます。

各テーブルの項目に関してはMySQL公式ドキュメントのPerformance Schema Replication Tablesをご確認ください。

IOスレッドをperfomance_schemaを使って確認する例

SLAVE> SHOW TABLES LIKE 'replication%';
+---------------------------------------------+
| Tables_in_performance_schema (replication%) |
+---------------------------------------------+
| replication_applier_configuration           |
| replication_applier_filters                 |
| replication_applier_global_filters          |
| replication_applier_status                  |
| replication_applier_status_by_coordinator   |
| replication_applier_status_by_worker        |
| replication_connection_configuration        |
| replication_connection_status               |
| replication_group_member_stats              |
| replication_group_members                   |
+---------------------------------------------+
10 rows in set (0.00 sec)

SLAVE> SELECT rcc.CHANNEL_NAME, HOST, PORT, USER, LAST_ERROR_NUMBER, LAST_ERROR_MESSAGE FROM replication_connection_configuration as rcc INNER JOIN replication_connection_status as rsc ON rcc.CHANNEL_NAME = rsc.CHANNEL_NAME;
+--------------+-----------+------+------+-------------------+--------------------+
| CHANNEL_NAME | HOST      | PORT | USER | LAST_ERROR_NUMBER | LAST_ERROR_MESSAGE |
+--------------+-----------+------+------+-------------------+--------------------+
| mydatabase1  | 127.0.0.1 | 3306 | repl |                 0 |                    |
| mydatabase2  | 127.0.0.1 | 3308 | repl |                 0 |                    |
| mydatabase3  | 127.0.0.1 | 3310 | repl |                 0 |                    |
+--------------+-----------+------+------+-------------------+--------------------+
3 rows in set (0.02 sec)

マルチソースレプリケーションを利用する際の注意点

マルチソースレプリケーションを利用する際には,各マスターで同じスキーマやテーブルを更新しないように運用する必要があります。

同じスキーマ,テーブルでもマルチソースレプリケーションを利用することは可能ですが,運用が複雑になってしまいます。各マスターで挿入するデータがプライマリーキー成約やユニーク成約を持っているデータをスレーブ側では重複エラーになってしまったり,同じスキーマのテーブルを更新するようなSQLを実行してしまった場合はマスターとスレーブ間でデータの差異が生じます。

たとえば,mydatabase1であるテーブルのデータをWHERE c1 >= 10という条件で更新したあとに同じスキーマのテーブルをmydatabase2でWHERE c1 >= 20というような条件で更新してしまうと,mydatabase1と統合データベース上ではc1 >= 20のデータに差異が生まれてしまいます。

もし,テーブルの統合などで同じスキーマのテーブルを更新するマルチソースレプリケーションを実施する場合は,ROW_FORMATをRBRにしたり,各CHANNELで同じデータを更新しないような工夫をする必要があります。

とはいえ,ユーザー管理テーブル(mysql.user)などは各マスターでCREATE USER構文を同じユーザー名で実施すると,重複エラーになってしまいます。そういうときは,SQL_LOG_BIN = 0にしてバイナリログに吐かないようにして各マスター,スレーブに実施するか,CREATE USER IF NOT EXISTSを利用して重複エラーにならないようにしましょう。

まとめ

今回はマルチソースレプリケーションについて説明しました。データベースの再統合をする際などには非常に便利な機能ですが,注意点に記載した通り,同じデータを更新するような構成は運用が大変です。可能であれば,各マスターで違うスキーマを更新するような構成で組んで,安全に運用していく必要があります。

著者プロフィール

深町日出海(ふかまちひでみ)

GMOメディア株式会社のデータベースエンジニア。主にOracleとMySQLを担当。得意なプログラム言語はJava。MySQLの好きなところはTABLEやINDEXの識別子に64byteまで使えるところ。

Twitter:@lhfukamachi

コメント

コメントの記入