#### 17.2.5.3 复制过滤选项之间的交互

如果您使用数据库级和表级复制过滤选项的组合，则副本首先使用数据库选项接受或忽略事件，然后根据表选项评估这些选项允许的所有事件。这有时会导致看似违反直觉的结果。同样重要的是要注意，结果会根据操作是使用基于语句还是基于行的二进制日志记录格式来记录而有所不同。如果您想确保您的复制过滤器始终以独立于二进制日志记录格式的相同方式运行，如果您使用混合二进制日志记录格式，这一点尤其重要，请遵循本主题中的指导。

由于识别数据库名称的方式，复制过滤选项的效果因二进制日志记录格式而异。使用基于语句的格式，DML 语句是根据当前数据库处理的，由[`采用`](use.html)陈述。使用基于行的格式，DML 语句根据修改表所在的数据库进行处理。DDL 语句始终根据当前数据库进行过滤，如[`采用`](use.html)语句，无论二进制日志记录格式如何。

涉及多个表的操作也可能受到复制过滤选项的不同影响，具体取决于二进制日志记录格式。需要注意的操作包括涉及多表的事务[`更新`](update.html)语句、触发器、级联外键、更新多个表的存储函数，以及调用更新一个或多个表的存储函数的 DML 语句。如果这些操作同时更新已过滤表和已过滤表，则结果可能会因二进制日志记录格式而异。

如果您需要保证无论二进制日志格式如何，您的复制过滤器都能始终如一地运行，特别是如果您使用混合二进制日志格式（[`binlog_format=混合`](replication-options-binary-log.html#sysvar_binlog_format))，只使用表级复制过滤选项，不使用数据库级复制过滤选项。此外，不要使用同时更新已过滤表和已过滤表的多表 DML 语句。

如果您需要结合使用数据库级和表级复制过滤器，并希望这些过滤器尽可能一致地运行，请选择以下策略之一：

1.  如果您使用基于行的二进制日志记录格式（[`binlog_format=行`](replication-options-binary-log.html#sysvar_binlog_format))，对于 DDL 语句，依赖于[`采用`](use.html)语句来设置数据库并且不指定数据库名称。您可以考虑更改为基于行的二进制日志记录格式，以提高与复制过滤的一致性。看[第 5.4.4.2 节，“设置二进制日志格式”](binary-log-setting.html)适用于更改二进制日志记录格式的条件。

2.  如果您使用基于语句或混合二进制日志记录格式（[`binlog_format=声明`](replication-options-binary-log.html#sysvar_binlog_format)要么`混合`)，对于 DML 和 DDL 语句，依赖于[`采用`](use.html)语句并且不要使用数据库名称。此外，不要使用同时更新已过滤表和已过滤表的多表 DML 语句。

[](<>)

**示例 17.7 A[`--replicate-ignore-db`](replication-options-replica.html#option_mysqld_replicate-ignore-db)选项和一个[`--replicate-do-table`](replication-options-replica.html#option_mysqld_replicate-do-table)选项**

在复制源服务器上，发出以下语句：

```
USE db1;
CREATE TABLE t2 LIKE t1;
INSERT INTO db2.t3 VALUES (1);
```

副本具有以下复制过滤选项集：

```
replicate-ignore-db = db1
replicate-do-table = db2.t3
```

DDL 语句[`创建表`](create-table.html)在中创建表`db1`，如前所述[`采用`](use.html)陈述。副本根据其过滤掉这条语句[`--复制-忽略-db = db1`](replication-options-replica.html#option_mysqld_replicate-ignore-db)选项，因为`db1`是当前数据库。无论复制源服务器上的二进制日志记录格式是什么，此结果都是相同的。但是，DML 的结果[`插入`](insert.html)语句因二进制日志记录格式而异：

-   如果源上正在使用基于行的二进制日志记录格式（[`binlog_format=行`](replication-options-binary-log.html#sysvar_binlog_format))，副本评估[`插入`](insert.html)使用该表所在的数据库进行操作，命名为`数据库2`.数据库级选项[`--复制-忽略-db = db1`](replication-options-replica.html#option_mysqld_replicate-ignore-db)，首先评估，因此不适用。表级选项[`--replicate-do-table = db2.t3`](replication-options-replica.html#option_mysqld_replicate-do-table)确实适用，因此副本将更改应用于表`t3`.

-   如果源上使用了基于语句的二进制日志记录格式（[`binlog_format=声明`](replication-options-binary-log.html#sysvar_binlog_format))，副本评估[`插入`](insert.html)使用默认数据库进行操作，该数据库由[`采用`](use.html)声明`db1`并且没有改变。根据其数据库级别[`--复制-忽略-db = db1`](replication-options-replica.html#option_mysqld_replicate-ignore-db)选项，因此它会忽略操作并且不会将更改应用于表`t3`.表级选项[`--replicate-do-table = db2.t3`](replication-options-replica.html#option_mysqld_replicate-do-table)未检查，因为该语句已匹配数据库级选项并被忽略。

    如果[`--复制-忽略-db = db1`](replication-options-replica.html#option_mysqld_replicate-ignore-db)副本上的选项是必要的，并且在源上使用基于语句（或混合）的二进制日志记录格式也是必要的，可以通过省略数据库名称来使结果保持一致[`插入`](insert.html)声明并依赖于[`采用`](use.html)而是声明，如下：


```
USE db1;
CREATE TABLE t2 LIKE t1;
USE db2;
INSERT INTO t3 VALUES (1);
```

在这种情况下，副本总是评估[`插入`](insert.html)基于数据库的语句`数据库2`.无论操作是以基于语句的还是基于行的二进制格式记录的，结果都保持不变。
