如果您使用数据库级和表级复制过滤选项的组合,副本将首先使用数据库选项接受或忽略事件,然后根据表选项评估所有这些选项允许的事件。这有时会导致看似违反直觉的结果。同样重要的是要注意,结果会因使用基于语句还是基于行的二进制日志记录格式记录操作而异。如果您希望确保您的复制过滤器始终以相同的方式工作,而与二进制日志记录格式无关,这对于使用混合二进制日志记录格式尤其重要,请遵循本主题中的指南。
复制过滤选项的效果因二进制日志记录格式而异,因为数据库名称的识别方式不同。使用基于语句的格式,DML 语句是根据当前数据库处理的,如 USE
语句中指定的那样。使用基于行的格式,DML 语句是根据修改的表所在的数据库处理的。DDL 语句始终根据当前数据库进行过滤,如 USE
语句中指定的那样,而与二进制日志记录格式无关。
涉及多个表的运算也会因二进制日志记录格式的不同而受到复制过滤选项的不同影响。需要注意的操作包括涉及多表 UPDATE
语句、触发器、级联外键、更新多个表的存储函数以及调用更新一个或多个表的存储函数的 DML 语句的事务。如果这些操作同时更新了过滤后的表和过滤后的表,结果会因二进制日志记录格式而异。
如果您需要保证您的复制过滤器无论二进制日志记录格式如何都能始终如一地工作,特别是如果您使用的是混合二进制日志记录格式 (binlog_format=MIXED
),请仅使用表级复制过滤选项,不要使用数据库级复制过滤选项。此外,不要使用更新了过滤后的表和过滤后的表的多个表 DML 语句。
如果您需要使用数据库级和表级复制过滤器的组合,并且希望它们尽可能一致地工作,请选择以下策略之一
如果您使用基于行的二进制日志记录格式 (
binlog_format=ROW
),对于 DDL 语句,请依靠USE
语句来设置数据库,并且不要指定数据库名称。您可以考虑更改为基于行的二进制日志记录格式,以提高与复制过滤的一致性。有关更改二进制日志记录格式的适用条件,请参见 第 7.4.4.2 节,“设置二进制日志记录格式”。如果您使用基于语句或混合二进制日志格式(
binlog_format=STATEMENT
或MIXED
),对于 DML 和 DDL 语句,都依赖于USE
语句,并且不要使用数据库名称。此外,不要使用更新了过滤进和过滤出表的多个表的 DML 语句。
示例 19.7 一个 --replicate-ignore-db
选项和一个 --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
在 db1
中创建表,如前面的 USE
语句指定。副本根据其 --replicate-ignore-db = db1
选项过滤掉此语句,因为 db1
是当前数据库。无论复制源服务器上的二进制日志格式是什么,结果都是相同的。但是,DML INSERT
语句的结果取决于二进制日志格式
如果源上使用基于行的二进制日志格式(
binlog_format=ROW
),副本使用表所在的数据库来评估INSERT
操作,该数据库名为db2
。因此,首先评估的数据库级选项--replicate-ignore-db = db1
不适用。表级选项--replicate-do-table = db2.t3
适用,因此副本将更改应用于表t3
。如果源上使用基于语句的二进制日志格式(
binlog_format=STATEMENT
),副本使用默认数据库来评估INSERT
操作,该数据库由USE
语句设置为db1
,并且尚未更改。根据其数据库级--replicate-ignore-db = db1
选项,因此它忽略操作,并且不将更改应用于表t3
。表级选项--replicate-do-table = db2.t3
未被检查,因为该语句已经匹配了数据库级选项并且被忽略了。
如果副本上的 --replicate-ignore-db = db1
选项是必要的,并且源上也必须使用基于语句(或混合)的二进制日志格式,则可以通过从 INSERT
语句中省略数据库名称,并改为依赖 USE
语句来使结果一致,如下所示
USE db1;
CREATE TABLE t2 LIKE t1;
USE db2;
INSERT INTO t3 VALUES (1);
在这种情况下,副本始终根据数据库 db2
来评估 INSERT
语句。无论操作是基于语句的二进制格式还是基于行的二进制格式记录,结果都保持一致。