天天看点

MySQL 复制过滤详解

如果有这样的一个需求:master 有3个库a,b,c ,d,由于某种原因,现在需要将其中2个库b,c单独拆分出来,单独一个实例。 如果是你,打算怎么做呢? 常见的做法就是,单独搭建一个只有b,c库的实例,然后只复制master的b,c库,过滤掉a,d库。那么复制过滤就应运而生了,replicate-*-do-db/table 等。

为了搭建这一套环境(只复制master的b,c库),部分人会在my.cnf中这样配置:

当然,按照大家的惯性思维,认为这样是没有错的。不幸的是,灾难已经来临。

官方文档:

mysql 会认为<code>b,c</code> 为一个库名,而不是2个库。

然而,这里不仅仅有一个复制过滤参数,一共包括:

这里面可以随意组合,且不同组合有不同的含义,为了彻底搞清楚他们直接的关系,下面我们一起来一窥究竟。

注意1:库级别的规则,只针对binlog_format='statement or mixed‘ 注意2:如果是binlog_format=‘row’,不受库级别规则限制,只受表级别规则限制。
MySQL 复制过滤详解
MySQL 复制过滤详解
注意: 以下测试和结论,前提都是row_format='mixed'

在db level 中,当binlog-format=statement 时,过滤以use db为主(不允许跨库)。为rows模式是:不以use db为主(允许跨库)

不管binlog格式是statement,还是rows模式,table level的判断都是 不以use db为主(可以跨库的)

总的流程走向:先判断db-level,如果db-level 判断完成后需要exit,则退出。如果db-level判断完成后,没有exit,则再判断table-level

在db-level中,如果有replicate-do-db,则判断replicate-do-db,将不会走到replicate-ignore-db这层。 如果判断replicate-do-db符合条件,则判断table-level。 如果不符合,则exit

在db-level中,如果没有replicate-do-db,但是有replicate-ignore-db。 流程则是:符合replicate-ignore-db规则,则exit,不符合,则走到table-level层继续判断

在table-level中,判断逻辑顺序自上而下为:replicate-do-table -&gt; replicate-ignore-table -&gt; replicate-wild-do-table -&gt; replicate-wild-ignore-table

在table-level中, 从第一个阶段(replicate-do-table)开始,如果符合replicate-do-table判断规则,则exit。如果不符合,则跳到下一层(replicate-ignore-table)。 然后以此内推,直到最后一层(replicate-wild-ignore-table)都不符合,则最后判断是否有(replicate-do-table or replicate-wild-do-table),如果有,则ignore &amp; exit。如果没有,则execute &amp; exit

说明:以下测试,均以statement格式为例。 rows模式参见原理同样可以证明,这里就不解释。

第一种情况:设置replicate_do_db=a,b

do-db

ignoare-db

do-db &amp; ignore-db

do-table

ignore-table

wild-do-table

wild-ignore-table

do-table &amp; ignore-table

do-table &amp; wild-ignore-table

wild-do-table &amp; wild-ignore-table

do-db &amp; do-table

do-db &amp; wild-do-table

do-db &amp; ignore-table

do-db &amp; wild-ignore-table

最常见场景: db-db &amp; do-ignore-db &amp; wild-do-table &amp; wild-ignore-table

实战: wild-do-table &amp; ignore-table &amp; wild-ignore-table

由于组合太多,就不一一列举。

以上情况,还可以衍生出各种场景和组合,只要弄懂了原理,基本都没有问题。

继续阅读