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