MySQL道普請便り

第88回 スレーブのレプリケーションフィルターについて

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

MySQLのレプリケーションにはフィルター機能が古くから存在しています。特定のデータベースのみやテーブルのみ,または特定のデータベースやテーブルを除外してレプリケーションさせることが可能です。今回はスレーブにおいて設定できるレプリケーションフィルターの注意点や,バージョンによる変更点を紹介します。

レプリケーションフィルターオプション

レプリケーションフィルターを設定するには,以下のオプションをmy.cnfに記述する,またはMySQLを起動する際に引数として記述する必要があります。

  • replicate-do-db=dbname …レプリケーションするデータベースを指定
  • replicate-ignore-db=dbname …レプリケーションを除外するデータベースを指定
  • replicate-do-table=dbname.table …レプリケーションをするテーブルを指定
  • replicate-ignore-table=dbname.table …レプリケーションを除外するテーブルを指定
  • replicate-rewrite-db=from_name->to_namefrom_nameのデータベースをto_nameのデータベースへ書き換えてレプリケーションする
  • replicate-wild-do-table=dbname.table …レプリケーションをするテーブルを%_のワイルドカード文字を含めて指定
  • replicate-wild-ignore-table=dbname.table …レプリケーションを除外するテーブルを%_のワイルドカード文字を含めて指定

レプリケーションタイプによる挙動の注意点

データベース単位でのフィルター

replicate-do-dbやreplicate-ignore-dbは,ステートメントベースレプリケーション(SBR)と行ベースレプリケーション(RBR)によって大きく挙動が変わるため,注意が必要です。

SBRの場合,USE dbnameでデータベースが選択された状態(デフォルトデータベース)でフィルターが機能します。RBRの場合,デフォルトデータベースに依存せずフィルターが機能します。たとえばreplicate-do-db=db1と設定されている状態で,以下に挙げる例のステートメントを実行したとします。

例1

mysql> USE db1;
mysql> UPDATE t0 SET col2=3 WHERE col1=1;
mysql> UPDATE db4.t0 SET col2=3 WHERE col1=1;

例2

mysql> USE db2;
mysql> UPDATE db1.t0 SET col2=3 WHERE col1=1;
mysql> UPDATE db4.t0 SET col2=3 WHERE col1=1;

SBRの場合,例1ではdb1がデフォルトデータベースとなっています。よって,それ以降のすべてのステートメントはレプリケーションされます。フィルターはデフォルトデータベースに依存するため,UPDATE db4.t0といった別のデータベースのテーブルへも更新もレプリケーションされてしまいます。例2においては,デフォルトデータベースがdb2であるため,以降のUPDATE db1.t0を含めたステートメントはレプリケーションされません。

RBRの場合,デフォルトデータベースに依存せず,指定したデータベースに属するテーブルへの更新のみレプリケーションされます。よって,例1ではUPDATE t0 SET col2=3 WHERE col1=1;が,例2ではUPDATE db1.t0 SET col2=3 WHERE col1=1;がレプリケーションされます。

RBRでのフィルターの方が,ユーザが希望している動きになると思います。

テーブル単位でのフィルター

replicate-do-tableやreplicate-ignore-tableのテーブル単位でのフィルターではデータベース単位とは異なり,SBRであってもデフォルトデータベースに依存せず対象のデータベースのテーブルをフィルターします。

replicate-do-table=db1.t0と設定した場合は,SBRとRBR共に例1ではUPDATE t0 SET col2=3 WHERE col1=1;が,例2ではUPDATE db1.t0 SET col2=3 WHERE col1=1;がレプリケーションされます。

データベース単位やテーブル単位のフィルターでの動作に違いがあるため,詳しくは17.1.4.3 レプリケーションスレーブのオプションと変数を参照ください。

フィルター設定方法

フィルターを設定するには,MySQL5.6とそれ以前では前述のようにmy.cnfに記述する,またはMySQLを起動する際に引数として記述する必要がありました。そのため,新たにフィルターの変更をする場合はMySQLの再起動が必要でした。MySQL5.7とそれ以降からは,オンライン(正確にはSQLスレッドの再起動)での設定が可能となりました。CHANGE REPLICATION FILTER コマンド を使用します。

db1データベースのみレプリケーションする設定例

mysql> STOP SLAVE SQL_THREAD;
mysql> CHANGE REPLICATION FILTER replicate_do_db=(db1);
mysql> START SLAVE SQL_THREAD;

しかしながら,注意として,CHANGE REPLICATION FILTER コマンドで設定したフィルターは,MySQLが再起動されるとフィルターもリセットされます。よって,オンラインで変更して以降永続化するためにはmy.cnfに記述する必要があります。

フィルターの設定確認方法

MySQL5.7とそれ以前では,SHOW SLAVE STATUSの項目から確認できます。

mysql> SHOW SLAVE STATUS\G
〈表示一部割愛〉
              Replicate_Do_DB: db1
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:

MySQL8.0からはperformance_schemaのテーブルから確認することもできます。詳しくは後述します。

マルチソースレプリケーションでのフィルター

マルチソースレプリケーション環境によるレプリケーションフィルターは,MySQL5.7ではすべてのチャネルに対してグローバルフィルターであり,個々のチャネルに対して設定はできませんでした。

MySQL8.0からはチャネルごとにフィルターの設定が可能となりました。CHANGE REPLICATION FILTERコマンドにFOR CHANNELでチャネル名を指定することで設定できます。

mysql80> CHANGE REPLICATION FILTER replicate_do_db=(db1) FOR CHANNEL channel;

MySQL8.0では,performance_schemareplication_applier_global_filtersreplication_applier_filtersテーブルが新たに追加され,これらのテーブルからフィルターの設定確認ができるようになっています。

replication_applier_global_filtersテーブル
すべてのレプリケーションチャネルに適用されるグローバルレプリケーションフィルターに関する情報を提供します。
replication_applier_filtersテーブル
特定のレプリケーションチャネルに設定されているレプリケーションフィルターに関する情報を提供します。
mysql80> select * FROM replication_applier_global_filters;
+-----------------+-------------+---------------------------+----------------------------+
| FILTER_NAME     | FILTER_RULE | CONFIGURED_BY             | ACTIVE_SINCE               |
+-----------------+-------------+---------------------------+----------------------------+
| REPLICATE_DO_DB | db1         | CHANGE_REPLICATION_FILTER | 2019-01-04 17:01:29.056613 |
+-----------------+-------------+---------------------------+----------------------------+

まとめ

スレーブにおいて設定できるレプリケーションフィルターを紹介しました。今回は説明はしませんでしたが,マスターでバイナリログを制御してレプリケーションフィルターを設定することも可能です。しかし,これらのレプリケーションフィルターはレプリケーションタイプによる動作の違いなど多用してしまうと運用が複雑になる恐れがあるので,導入する際は注意が必要です。

著者プロフィール

北川健太郎(きたがわけんたろう)

LINE株式会社所属のデータベースエンジニア。担当はMySQLとOracle Database。好きなMySQLの機能はレプリケーションで,好きなOracleDatabaseの機能はログオントリガー。

Twitter:@keny_lala