mysql复制过滤器参数对比
今天分享一个线上的MySQL复制过滤参数问题。
01
背景介绍
线上业务同学通常都会自己先搭建一套MySQL服务,自己维护,自己折腾,等到项目要上线,或者遇到某种性能瓶颈的时候,就会想到托管给DBA,这几天我们就遇到了这样一个场景。
某个业务同学自建的MySQL数据库数据量达到了1.6T,运维起来有困难,于是托管给我们。这个数据库的基本情况如下:
1、容量:1.6T
2、数据库:10+个
3、每个数据库中的表:200+个
由于业务的MySQL服务是单点的,而且容量比较大,所以这个托管流程需要分为下面几个步骤:
由于数据量比较大,我们给业务同学提了几个建议:
1、先清理部分业务数据,删除表数据,释放表空间,减少总的数据量。
2、只备份那些需要托管的数据库,让备份搭建从库的过程更顺利。
02
复制关系搭建 上述流程中,由于备份数据,只有部分数据库(这个通过xtrabackup的--database参数实现),所以搭建复制关系的时候,需要用到复制过滤器。
假设数据库实例A有a、b、c、d 4个DB,但是备份的时候,只备份了a、b两个数据库,那么在利用备份数据搭建实例B的时候,就会使用到复制过滤器,常见的复制过滤器选项包含:
库级别:
replicate-do-db
replicate-ignore-db
表级别;
replicate-do-table
replicate-ignore-table
replicate-wild-do-table
replicate-wild-ignore-table
这里第一反应会想到库级别的复制过滤器replicate-ignore-db。实际中也是这么操作的,将c、d 两个数据库写入到复制过滤器中,但是遇到了一个问题。
问题:
这个参数replicate-ignore-db有个特性(摘自官方文档)
statement模式的binlog下,它只过滤默认的数据库,也就是你使用use + db命令指定的那个数据库。
这也就意味着,如果你使用:
use a;
update c.table xxxx
这个时候,它认为这是在操作数据库a,而实际上c这个数据库的update操作,是不能被过滤的。由于上述实例B上没有c这个数据库,所以会报错:库表不存在
简言之,statement模式下不允许跨库操作。
row格式下,只会按照binlog内容来,过滤所有的包含这个db的语句。默认的数据库名字没有影响。
简言之,row模式下允许跨库操作。
现状:
恰好,我们的业务的binlog格式就是statement的。由于业务一直在运行,不能停,那么这个问题怎么解决呢?
方案:
使用下面两个过滤器来代替即可。
replicate-wild-ignore-table
这两个参数,从名称中的wild就可以看出来,比较"狂野"。他们没有跨库的限制,官方文档如下(重点看最后一句):
简单看,就是他们支持百分号%和下划线_通配符,然后支持跨库操作。
我们只需要将参数配置成下面的通配符模式即可:
replicate-wild-ignore-table=c.%
replicate-wild-ignore-table=d.%
这样,就能将数据库c和d的所有表的操作都过滤。
03
如何修改复制过滤器?
在MySQL 5.7 之前,不允许手工在线修改复制过滤器,必须修改配置文件,然后重启服务,在MySQL5.7之后,可以手工在线修改。
设想这么一种场景,如果一开始过滤了数据库c和d,后续我们需要将数据库a的操作也过滤掉,那么是不是需要重启实例B呢?MySQL其实为我们考虑了这样的场景,所以有一个语法:
CHANGE REPLICATION FILTER REPLICATE_WILD_IGNORE_TABLE = ('db1.new%', 'db2.new%');
这个特性,之前还有一个文章有些,有兴趣可以去关注下:
MySQL动态修改复制过滤器
总结:
1、MySQL官方文档是个好东西
2、部分参数在特殊场景下,可能有不同的效果,细节部分需要留意
3、动态参数的设置确实能很大程度减少运维的成本
好了,今天内容就这么多了。晚安。