在搭建复制中,经常会有复制过滤的需求,通常做法是在配置文件添加下面参数,然后达到复制过滤的效果。
[mysqld]
#方法1:指定过滤的库、表
replicate-wild-ignore-table = information_schema.%
replicate-wild-ignore-table = performance_schema.%
replicate-wild-ignore-table = mysql.%
replicate-wild-ignore-table = sys.%
#方法2:指定同步的库、表
replicate-wild-do-table = 'db1.%'
replicate-wild-do-table = 'db2.%'
由于配置文件my.cnf是全局的,导致过滤规则在所有复制通道生效。所以在一些复杂的同步场景中,很多人会选择CHANGE REPLICATION FILTER配置过滤。
语法:
# 1> 执行同步的库、表
CHANGE REPLICATION FILTER
REPLICATE_WILD_DO_TABLE = ('db1.%');
# 2> 指定过滤的库、表
CHANGE REPLICATION FILTER
REPLICATE_WILD_IGNORE_TABLE = ('db1.%', 'db2.%');
第1个坑:复制过滤重启失效
在mysql5.7和mysql8.0中,使用CHANGE REPLICATION FILTER语法配置的过滤规则无法持久化,即重启失效。下面是官方描述:

下面案例中,复制线程只同步了db1,同时在salve节点db2可以读写。当配置文件没有skip-slave-start时,实例重启后复制线程会自动拉起,然后CHANGE REPLICATION FILTER失效。所以此时db1和db2都会同步,由于在slave节点db2可以读写,所以同步线程很容易引发数据冲突报错。

规避方法:配置文件添加skip-slave-start参数,实例重启后先执行CHANGE REPLICATION FILTER,然后start slave,建议脚本实现。
第2个坑:mysql5.7中复制过滤影响mgr同步
mysql5.7配置过滤会导致mgr从节点过滤,引发数据不一致。
测试
1、先在mgr从节点配置复制过滤,只同步test2库。
CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = ('test2.%');
2、然后在mgr主节点test1库新增数据,可以观察到新增的数据没有同步到从库,说明复制过滤影响了mgr同步(该问题在mysql8.0不存在,应该是修复了)。反复测试执行start/stop group_replication,发现虽然数据不一致,但是mgr同步不受影响。
主节点:

从节点:

下面场景中,复制过滤就有潜在风险。
mgr的primary节点配置了复制过滤,当主库发生切换后,旧主以secodary身份加入集群,此时旧主的复制过滤依然有效,就会导致新主与旧主数据同步受到影响。

总结
1、change replication filter过滤配置无法持久化,重启实例失效;
2、在mysql5.7版本中,change replication filter过滤影响mgr集群内部同步。




