在上一篇文章《深入了解MySQL多源复制》中,介绍了MySQL多源复制的相关内容,本文将继续讲解MySQL多源复制,主要内容是过滤复制以及在已有复制过滤配置中新增复制对象;
首先,来看一下MySQL 复制中复制过滤器CHANGE REPLICATION FILTER 的语法,从语法上看, 5.7 和 8.0版本基本一样,但是细心的读者可能会发现,其实在语法上一个非常不同的差异,8.0的语法支持[FOR CHANNEL channel]通道语法,而5.7版本其实是不支持的;详细的语法如下所示:
5.7版本:
CHANGE REPLICATION FILTER filter[, filter][, ...]
filter: {
REPLICATE_DO_DB = (db_list)
| REPLICATE_IGNORE_DB = (db_list)
| REPLICATE_DO_TABLE = (tbl_list)
| REPLICATE_IGNORE_TABLE = (tbl_list)
| REPLICATE_WILD_DO_TABLE = (wild_tbl_list)
| REPLICATE_WILD_IGNORE_TABLE = (wild_tbl_list)
| REPLICATE_REWRITE_DB = (db_pair_list)
}
db_list:
db_name[, db_name][, ...]
tbl_list:
db_name.table_name[, db_table_name][, ...]
wild_tbl_list:
'db_pattern.table_pattern'[, 'db_pattern.table_pattern'][, ...]
db_pair_list:
(db_pair)[, (db_pair)][, ...]
db_pair:
from_db, to_db
8.0版本:
CHANGE REPLICATION FILTER filter[, filter]
[, ...] [FOR CHANNEL channel]
filter: {
REPLICATE_DO_DB = (db_list)
| REPLICATE_IGNORE_DB = (db_list)
| REPLICATE_DO_TABLE = (tbl_list)
| REPLICATE_IGNORE_TABLE = (tbl_list)
| REPLICATE_WILD_DO_TABLE = (wild_tbl_list)
| REPLICATE_WILD_IGNORE_TABLE = (wild_tbl_list)
| REPLICATE_REWRITE_DB = (db_pair_list)
}
db_list:
db_name[, db_name][, ...]
tbl_list:
db_name.table_name[, db_name.table_name][, ...]
wild_tbl_list:
'db_pattern.table_pattern'[, 'db_pattern.table_pattern'][, ...]
db_pair_list:
(db_pair)[, (db_pair)][, ...]
db_pair:
from_db, to_db
下面来看一下具体的实现
##指定数据库db1,db2 CHANGE REPLICATION FILTER REPLICATE_DO_DB=(db1, db2) ##指定表db1.t7 ,忽略表db2.t7 CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = (‘db1.t7’), REPLICATE_WILD_IGNORE_TABLE = (‘db2.t7’); ##忽略表t1,t2开头的表 CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = (‘db2.t1%’,’db2.t2%’); ##下面的语句重写发生在主数据库db1上的语句到从数据库db2上 CHANGE REPLICATION FILTER REPLICATE_REWRITE_DB = ((db1, db2)); CHANGE REPLICATION FILTER REPLICATE_REWRITE_DB = ((dbA, dbB), (dbC, dbD)); ###清空 CHANGE REPLICATION FILTER REPLICATE_DO_DB=(); CHANGE REPLICATION FILTER REPLICATE_DO_TABLE=(); CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE=(); CHANGE REPLICATION FILTER Replicate_Ignore_DB=(); CHANGE REPLICATION FILTER Replicate_Wild_Ignore_Table=();
5.7和8.0的区别就在于,8.0支持FOR CHANNEL channel语法,而5.7不支持,下面的语法在8.0的实例上可以成功执行,而在5.7的实例上支持,会包语法的错误;
CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = ('wjqtest.src_bill','wjqtest.src_bug_list','wjqtest.src_group') for channel 'wjqtest_10.30.124.186_4306';
那么,你可能会问“FOR CHANNEL channel”和5.7有什么区别呢?区别就在于,在多源复制的情况,可以为单独的复制通道配置复制过滤,而在8.0之前的版本是无法做到的
如果是在5.7环境中执行下面的语法
CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = ('wjqtest.src_bill','wjqtest.src_bug_list','wjqtest.src_group');
会将所有的复制通道全部都设置成上述的过滤器配置,如果是多个数据源的话,就需要在把多个源需要过滤的库表进行进行配置;这样是不是就不如8.0支持FOR CHANNEL channel更方便一些了呢;
上面说完了多源复制中的复制过滤的相关内容,那么在实际的生产中有如下的需求:
如果是对其中一个或多个实例进行过滤复制,并且运行一段时间后,想在这个源上再增加一个或多个库或表复制,该怎么实现呢?可以思考一下
.
.
.
.
.
实际需求:
主1:10.30.124.186 4306 db1 db2
主2:10.30.124.186 4307 db3
从:10.30.124.187 4306
假如之前实现的是过滤复制,复制的是主1的db1 和 主2的db3,已经运行一段时间了。现在想增加主1上的db2,该如何实现?
具体实现方法如下: 1. 使用mysqldump 导出 db2(记录pos1),并导入多源从库。 2. 停止多源从库的sql线程(STOP SLAVE SQL_THREAD ),并记录此刻同步到主1的位置pos2。 3. 使用mysqlbinlog 将pos1 到 pos2 的变更应用到从库。(mysqlbinlog –start-position=pos1 –stop-position=pos2 -d db2 mysqlbin.001769 | mysql -u -p -h -P ) 4. 在线修改多源从库的过滤条件(CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = (‘db1.%’,’db2.%’,’db3.%’);) 5.启动sql_thread线程,检查主从复制状态
参考链接:
https://dev.mysql.com/doc/refman/8.0/en/change-replication-filter.html