* GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
适合读者:DBA 后端架构师 运维工程师
关键词:MySQL 复制、binlog_do_db、replicate_do_db、数据不一致
一、背景
在许多 MySQL 体系的数据库环境中,为了降低 binlog relay log 日志量、缓解从库复制压力或减少同步延迟,往往会引入 主库 binlog 过滤 或 从库复制过滤 的配置方案。 这些手段在一定程度上能够缓解资源消耗,但如果对其工作机制理解不充分,使用了不合理的过滤策略,极易引入隐蔽且不可逆的数据不一致风险。更为危险的是,这类问题在系统运行过程中通常不会立刻暴露,当业务侧发现数据异常时,往往已经无法通过常规手段进行补救。
本文将从 主库与从库两种过滤方式的实现机制入手,分析它们各自的优缺点及潜在风险。
二、复制过滤的判断逻辑
明确主库和从库在处理 SQL 和 row event 时的判断逻辑存在差异。
2.1 主库:是否写 binlog
判断发生在 SQL 执行完成之后。
binlog_do_db binlog_ignore_db
仅根据当前会话的 USE db
判断,而不关注 SQL 实际操作的目标表。
2.2 从库:是否执行 relay log
判断发生在 SQLThread 回放阶段
判断依据包括:
replicate_* 复制过滤参数 row event 真实的 db table 表是否存在 GTID 执行状态
结论:当主库和从库判断条件不一致时,即使 binlog 已记录,从库也可能未执行对应 row event,从而导致数据不一致。
三、主库过滤参数及风险
3.1 binlog_do_db binlog_ignore_db 的行为示例
主库参数设置:
binlog_do_db = db1
主库执行SQL:
USE db1;
INSERT INTO db2.t2 VALUES (1);
执行结果:
主库 binlog 会记录该事务。 记录的 row event 目标表为 db2.t2
,与 USE db1
不一致。
3.2 相关风险
binlog 语义与实际操作对象脱钩 新从库或延迟从库无法补全缺失数据 binlog 回放、审计等可能出现语义错误
四、从库复制过滤参数及风险
4.1 常用复制过滤参数
从库复制过滤前提条件就是主库的binlog必须完整。
Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table:
4.2 复制或忽略库参数
说明:
Replicate_Do_DB/Replicate_Ignore_DB 这两个参数一个是只同步某些库,另一个是只忽略某些库,判断依据是relay log中记录use的数据库,并不是SQL语句实际操作的库。
测试:
从库配置复制过滤
STOP SLAVE;
CHANGE REPLICATION FILTER Replicate_Do_DB = test1;
START SLAVE;
主库不配置过滤并执行操作
USE test;
CREATE TABLE TEST1.T1 LIKE TEST.T1;
INSERT INTO TEST1.T1 VALUES(1,'A');
验证数据
主库查看数据:
greatsql> SELECT * FROM TEST1.T1;
+----+-------+
| id | cname |
+----+-------+
| 1 | A |
+----+-------+
1 row in set (0.00 sec)
从库查看数据:
greatsql> SELECT * FROM TEST1.T1;
ERROR 1146 (42S02): Table 'test1.t1' doesn't exist
结论:
从库报错表不存在,所以这样会导致从库同步数据失败,因为use的是test库。
风险:
多库写入(跨库SQL)、存储过程、触发器、应用层不指定USE库都会导致数据不同步的风险。
4.3 复制或忽略表参数
说明:
Replicate_Do_Table/Replicate_Ignore_Table 这两个参数一个是只同步指定表,另一个是只忽略指定表,两个参数都不支持通配符,可以精确到表但使用要确保库名表名正确。
测试:
从库配置复制过滤
STOP SLAVE;
CHANGE REPLICATION FILTER Replicate_Ignore_Table= (test1.t1_tmp);
START SLAVE;
主库不配置过滤并执行DDL操作
RENAME TABLE test1.t1 TO test1.t1_bak;
RENAME TABLE test1.t1_tmp TO test1.t1;
验证数据
主库查看数据:
greatsql> USE test1
Database changed
greatsql> SHOW tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| t1 |
| t1_bak |
+-----------------+
2 rows in set (0.01 sec)
从库查看数据:
greatsql> USE test1
Database changed
greatsql> SHOW tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| t1_bak |
| t1_tmp |
+-----------------+
2 rows in set (0.01 sec)
结论:
由于主库执行rename操作将t1表更为t1_bak,t1_tmp更为t1,而从库忽略了t1_tmp导致sql同步失败,如果业务往新t1表插入数据从库就会因表不存在而断开复制链路,这是典型的“表级过滤被 DDL 绕过”事故。
风险:
未匹配的表默认全部不复制 新增表需要人工维护配置 与 DDL 操作存在天然冲突 如果过滤表过多添加在配置文件中只能一个参数匹配一个表
4.4 指定复制或忽略库参数
说明:
Replicate_Wild_Do_Table/Replicate_Wild_Ignore_Table 这两个参数一个是同步指定表,另一个是忽略指定表,两个参数都支持通配符,使用要确保库名表名没有通配符的隐患存在。
匹配方式:%
、_
(LIKE 语义)
测试:
从库配置复制过滤
忽略日志类表,不需要同步到从库。
STOP SLAVE;
CHANGE REPLICATION FILTER Replicate_Wild_Ignore_Table = (test1.log%);
START SLAVE;
主库不配置过滤并执行DML操作
一年后业务上线新业务test1.log_important
验证表结构
主库查看数据:
greatsql> USE test1
Database changed
greatsql> SHOW tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| log_important |
+-----------------+
1 row in set (0.00 sec)
从库查看数据:
greatsql> USE test1
Database changed
greatsql> SHOW tables;
Empty set (0.00 sec)
结论:
log_important
被 log_%
命中新业务数据未同步到从库,主从复制正常但是从库数据丢失,如果主库故障切换到从库才发现数据不一致就会导致故障,这是典型的“通配规则忽略业务表”事故。
风险:
匹配范围过宽 新表“自动进入过滤范围” DDL 影响范围不可控
五、最常见的踩坑配置
主库 从库 风险 是否推荐 binlog_do_db Replicate_Do_DB/Replicate_Ignore_DB 跨库静默丢数据 不推荐 binlog_do_db replicate_wild_ignore 从库失效 不推荐 binlog_ignore_db 无过滤 永久不可补 不推荐 无过滤 Replicate_Do_DB/Replicate_Ignore_DB 跨库静默丢数据 不推荐 无过滤 Replicate_Do_Table/Replicate_Ignore_Table 与DDL操作存在冲突,人工维护成本高 可用,前提是过滤表数量少 无过滤 Replicate_Wild_Do_Table/Replicate_Wild_Ignore_Table 匹配范围过宽,通配符需要转义 可用,前提是确保通配符不会影响其他表
六、最终建议(可直接当规范)
如果可以不做过滤就不做,做了就会有数据风险。 主库禁止做库表忽略,主库的binlog必须完整。 从库Replicate_Do_DB/Replicate_Ignore_DB最好不使用,业务操作并非DBA可以控制,但数据不一致就是DBA的锅。 从库Replicate_Do_Table/Replicate_Ignore_Table看似精确,但对 DDL 极其敏感,一旦表结构或命名发生变化,复制语义就可能在无感知的情况下被破坏。 从库Replicate_Wild_Do_Table/Replicate_Wild_Ignore_Table可以使用,库表都可做过滤,前提是一定要做转义,规避不应该发生的数据问题。 有条件可以使用GreatSQL 的gt checksum工具定期做主从数据校验。
适合读者:DBA 后端架构师 运维工程师
关键词:MySQL 复制、binlog_do_db、replicate_do_db、数据不一致
一、背景
在许多 MySQL 体系的数据库环境中,为了降低 binlog relay log 日志量、缓解从库复制压力或减少同步延迟,往往会引入 主库 binlog 过滤 或 从库复制过滤 的配置方案。 这些手段在一定程度上能够缓解资源消耗,但如果对其工作机制理解不充分,使用了不合理的过滤策略,极易引入隐蔽且不可逆的数据不一致风险。更为危险的是,这类问题在系统运行过程中通常不会立刻暴露,当业务侧发现数据异常时,往往已经无法通过常规手段进行补救。
本文将从 主库与从库两种过滤方式的实现机制入手,分析它们各自的优缺点及潜在风险。
二、复制过滤的判断逻辑
明确主库和从库在处理 SQL 和 row event 时的判断逻辑存在差异。
2.1 主库:是否写 binlog
判断发生在 SQL 执行完成之后。
binlog_do_db binlog_ignore_db
仅根据当前会话的 USE db
判断,而不关注 SQL 实际操作的目标表。
2.2 从库:是否执行 relay log
判断发生在 SQLThread 回放阶段
判断依据包括:
replicate_* 复制过滤参数 row event 真实的 db table 表是否存在 GTID 执行状态
结论:当主库和从库判断条件不一致时,即使 binlog 已记录,从库也可能未执行对应 row event,从而导致数据不一致。
三、主库过滤参数及风险
3.1 binlog_do_db binlog_ignore_db 的行为示例
主库参数设置:
binlog_do_db = db1
主库执行SQL:
USE db1;
INSERT INTO db2.t2 VALUES (1);
执行结果:
主库 binlog 会记录该事务。 记录的 row event 目标表为 db2.t2
,与 USE db1
不一致。
3.2 相关风险
binlog 语义与实际操作对象脱钩 新从库或延迟从库无法补全缺失数据 binlog 回放、审计等可能出现语义错误
四、从库复制过滤参数及风险
4.1 常用复制过滤参数
从库复制过滤前提条件就是主库的binlog必须完整。
Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table:
4.2 复制或忽略库参数
说明:
Replicate_Do_DB/Replicate_Ignore_DB 这两个参数一个是只同步某些库,另一个是只忽略某些库,判断依据是relay log中记录use的数据库,并不是SQL语句实际操作的库。
测试:
从库配置复制过滤
STOP SLAVE;
CHANGE REPLICATION FILTER Replicate_Do_DB = test1;
START SLAVE;
主库不配置过滤并执行操作
USE test;
CREATE TABLE TEST1.T1 LIKE TEST.T1;
INSERT INTO TEST1.T1 VALUES(1,'A');
验证数据
主库查看数据:
greatsql> SELECT * FROM TEST1.T1;
+----+-------+
| id | cname |
+----+-------+
| 1 | A |
+----+-------+
1 row in set (0.00 sec)
从库查看数据:
greatsql> SELECT * FROM TEST1.T1;
ERROR 1146 (42S02): Table 'test1.t1' doesn't exist
结论:
从库报错表不存在,所以这样会导致从库同步数据失败,因为use的是test库。
风险:
多库写入(跨库SQL)、存储过程、触发器、应用层不指定USE库都会导致数据不同步的风险。
4.3 复制或忽略表参数
说明:
Replicate_Do_Table/Replicate_Ignore_Table 这两个参数一个是只同步指定表,另一个是只忽略指定表,两个参数都不支持通配符,可以精确到表但使用要确保库名表名正确。
测试:
从库配置复制过滤
STOP SLAVE;
CHANGE REPLICATION FILTER Replicate_Ignore_Table= (test1.t1_tmp);
START SLAVE;
主库不配置过滤并执行DDL操作
RENAME TABLE test1.t1 TO test1.t1_bak;
RENAME TABLE test1.t1_tmp TO test1.t1;
验证数据
主库查看数据:
greatsql> USE test1
Database changed
greatsql> SHOW tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| t1 |
| t1_bak |
+-----------------+
2 rows in set (0.01 sec)
从库查看数据:
greatsql> USE test1
Database changed
greatsql> SHOW tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| t1_bak |
| t1_tmp |
+-----------------+
2 rows in set (0.01 sec)
结论:
由于主库执行rename操作将t1表更为t1_bak,t1_tmp更为t1,而从库忽略了t1_tmp导致sql同步失败,如果业务往新t1表插入数据从库就会因表不存在而断开复制链路,这是典型的“表级过滤被 DDL 绕过”事故。
风险:
未匹配的表默认全部不复制 新增表需要人工维护配置 与 DDL 操作存在天然冲突 如果过滤表过多添加在配置文件中只能一个参数匹配一个表
4.4 指定复制或忽略库参数
说明:
Replicate_Wild_Do_Table/Replicate_Wild_Ignore_Table 这两个参数一个是同步指定表,另一个是忽略指定表,两个参数都支持通配符,使用要确保库名表名没有通配符的隐患存在。
匹配方式:%
、_
(LIKE 语义)
测试:
从库配置复制过滤
忽略日志类表,不需要同步到从库。
STOP SLAVE;
CHANGE REPLICATION FILTER Replicate_Wild_Ignore_Table = (test1.log%);
START SLAVE;
主库不配置过滤并执行DML操作
一年后业务上线新业务test1.log_important
验证表结构
主库查看数据:
greatsql> USE test1
Database changed
greatsql> SHOW tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| log_important |
+-----------------+
1 row in set (0.00 sec)
从库查看数据:
greatsql> USE test1
Database changed
greatsql> SHOW tables;
Empty set (0.00 sec)
结论:
log_important
被 log_%
命中新业务数据未同步到从库,主从复制正常但是从库数据丢失,如果主库故障切换到从库才发现数据不一致就会导致故障,这是典型的“通配规则忽略业务表”事故。
风险:
匹配范围过宽 新表“自动进入过滤范围” DDL 影响范围不可控
五、最常见的踩坑配置
主库 从库 风险 是否推荐 binlog_do_db Replicate_Do_DB/Replicate_Ignore_DB 跨库静默丢数据 不推荐 binlog_do_db replicate_wild_ignore 从库失效 不推荐 binlog_ignore_db 无过滤 永久不可补 不推荐 无过滤 Replicate_Do_DB/Replicate_Ignore_DB 跨库静默丢数据 不推荐 无过滤 Replicate_Do_Table/Replicate_Ignore_Table 与DDL操作存在冲突,人工维护成本高 可用,前提是过滤表数量少 无过滤 Replicate_Wild_Do_Table/Replicate_Wild_Ignore_Table 匹配范围过宽,通配符需要转义 可用,前提是确保通配符不会影响其他表
六、最终建议(可直接当规范)
如果可以不做过滤就不做,做了就会有数据风险。 主库禁止做库表忽略,主库的binlog必须完整。 从库Replicate_Do_DB/Replicate_Ignore_DB最好不使用,业务操作并非DBA可以控制,但数据不一致就是DBA的锅。 从库Replicate_Do_Table/Replicate_Ignore_Table看似精确,但对 DDL 极其敏感,一旦表结构或命名发生变化,复制语义就可能在无感知的情况下被破坏。 从库Replicate_Wild_Do_Table/Replicate_Wild_Ignore_Table可以使用,库表都可做过滤,前提是一定要做转义,规避不应该发生的数据问题。 有条件可以使用GreatSQL 的gt checksum工具定期做主从数据校验。
适合读者:DBA 后端架构师 运维工程师
关键词:MySQL 复制、binlog_do_db、replicate_do_db、数据不一致
适合读者:DBA 后端架构师 运维工程师
关键词:MySQL 复制、binlog_do_db、replicate_do_db、数据不一致
一、背景
在许多 MySQL 体系的数据库环境中,为了降低 binlog relay log 日志量、缓解从库复制压力或减少同步延迟,往往会引入 主库 binlog 过滤 或 从库复制过滤 的配置方案。 这些手段在一定程度上能够缓解资源消耗,但如果对其工作机制理解不充分,使用了不合理的过滤策略,极易引入隐蔽且不可逆的数据不一致风险。更为危险的是,这类问题在系统运行过程中通常不会立刻暴露,当业务侧发现数据异常时,往往已经无法通过常规手段进行补救。
本文将从 主库与从库两种过滤方式的实现机制入手,分析它们各自的优缺点及潜在风险。
二、复制过滤的判断逻辑
明确主库和从库在处理 SQL 和 row event 时的判断逻辑存在差异。
2.1 主库:是否写 binlog
判断发生在 SQL 执行完成之后。
binlog_do_db binlog_ignore_db
仅根据当前会话的 USE db
判断,而不关注 SQL 实际操作的目标表。
2.2 从库:是否执行 relay log
判断发生在 SQLThread 回放阶段
判断依据包括:
replicate_* 复制过滤参数 row event 真实的 db table 表是否存在 GTID 执行状态
结论:当主库和从库判断条件不一致时,即使 binlog 已记录,从库也可能未执行对应 row event,从而导致数据不一致。
三、主库过滤参数及风险
3.1 binlog_do_db binlog_ignore_db 的行为示例
主库参数设置:
binlog_do_db = db1
主库执行SQL:
USE db1;
INSERT INTO db2.t2 VALUES (1);
执行结果:
主库 binlog 会记录该事务。 记录的 row event 目标表为 db2.t2
,与USE db1
不一致。
3.2 相关风险
binlog 语义与实际操作对象脱钩 新从库或延迟从库无法补全缺失数据 binlog 回放、审计等可能出现语义错误
四、从库复制过滤参数及风险
4.1 常用复制过滤参数
从库复制过滤前提条件就是主库的binlog必须完整。
Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table:
4.2 复制或忽略库参数
说明:
Replicate_Do_DB/Replicate_Ignore_DB 这两个参数一个是只同步某些库,另一个是只忽略某些库,判断依据是relay log中记录use的数据库,并不是SQL语句实际操作的库。
测试:
从库配置复制过滤
STOP SLAVE;
CHANGE REPLICATION FILTER Replicate_Do_DB = test1;
START SLAVE;
主库不配置过滤并执行操作
USE test;
CREATE TABLE TEST1.T1 LIKE TEST.T1;
INSERT INTO TEST1.T1 VALUES(1,'A');
验证数据
主库查看数据:
greatsql> SELECT * FROM TEST1.T1;
+----+-------+
| id | cname |
+----+-------+
| 1 | A |
+----+-------+
1 row in set (0.00 sec)
从库查看数据:
greatsql> SELECT * FROM TEST1.T1;
ERROR 1146 (42S02): Table 'test1.t1' doesn't exist
结论:
从库报错表不存在,所以这样会导致从库同步数据失败,因为use的是test库。
风险:
多库写入(跨库SQL)、存储过程、触发器、应用层不指定USE库都会导致数据不同步的风险。
4.3 复制或忽略表参数
说明:
Replicate_Do_Table/Replicate_Ignore_Table 这两个参数一个是只同步指定表,另一个是只忽略指定表,两个参数都不支持通配符,可以精确到表但使用要确保库名表名正确。
测试:
从库配置复制过滤
STOP SLAVE;
CHANGE REPLICATION FILTER Replicate_Ignore_Table= (test1.t1_tmp);
START SLAVE;
主库不配置过滤并执行DDL操作
RENAME TABLE test1.t1 TO test1.t1_bak;
RENAME TABLE test1.t1_tmp TO test1.t1;
验证数据
主库查看数据:
greatsql> USE test1
Database changed
greatsql> SHOW tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| t1 |
| t1_bak |
+-----------------+
2 rows in set (0.01 sec)
从库查看数据:
greatsql> USE test1
Database changed
greatsql> SHOW tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| t1_bak |
| t1_tmp |
+-----------------+
2 rows in set (0.01 sec)
结论:
由于主库执行rename操作将t1表更为t1_bak,t1_tmp更为t1,而从库忽略了t1_tmp导致sql同步失败,如果业务往新t1表插入数据从库就会因表不存在而断开复制链路,这是典型的“表级过滤被 DDL 绕过”事故。
风险:
未匹配的表默认全部不复制 新增表需要人工维护配置 与 DDL 操作存在天然冲突 如果过滤表过多添加在配置文件中只能一个参数匹配一个表
4.4 指定复制或忽略库参数
说明:
Replicate_Wild_Do_Table/Replicate_Wild_Ignore_Table 这两个参数一个是同步指定表,另一个是忽略指定表,两个参数都支持通配符,使用要确保库名表名没有通配符的隐患存在。
匹配方式:%
、_
(LIKE 语义)
测试:
从库配置复制过滤
忽略日志类表,不需要同步到从库。
STOP SLAVE;
CHANGE REPLICATION FILTER Replicate_Wild_Ignore_Table = (test1.log%);
START SLAVE;
主库不配置过滤并执行DML操作
一年后业务上线新业务test1.log_important
验证表结构
主库查看数据:
greatsql> USE test1
Database changed
greatsql> SHOW tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| log_important |
+-----------------+
1 row in set (0.00 sec)
从库查看数据:
greatsql> USE test1
Database changed
greatsql> SHOW tables;
Empty set (0.00 sec)
结论:
log_important
被 log_%
命中新业务数据未同步到从库,主从复制正常但是从库数据丢失,如果主库故障切换到从库才发现数据不一致就会导致故障,这是典型的“通配规则忽略业务表”事故。
风险:
匹配范围过宽 新表“自动进入过滤范围” DDL 影响范围不可控
五、最常见的踩坑配置
六、最终建议(可直接当规范)
如果可以不做过滤就不做,做了就会有数据风险。 主库禁止做库表忽略,主库的binlog必须完整。 从库Replicate_Do_DB/Replicate_Ignore_DB最好不使用,业务操作并非DBA可以控制,但数据不一致就是DBA的锅。 从库Replicate_Do_Table/Replicate_Ignore_Table看似精确,但对 DDL 极其敏感,一旦表结构或命名发生变化,复制语义就可能在无感知的情况下被破坏。 从库Replicate_Wild_Do_Table/Replicate_Wild_Ignore_Table可以使用,库表都可做过滤,前提是一定要做转义,规避不应该发生的数据问题。 有条件可以使用GreatSQL 的gt checksum工具定期做主从数据校验。
《三分钟学会一个MySQL知识》
GreatSQL数据库是一款开源免费数据库,可在普通硬件上满足金融级应用场景,具有高可用、高性能、高兼容、高安全等特性,可作为MySQL或Percona Server for MySQL的理想可选替换。
⏩GitHub : https://github.com/GreatSQL/
🆙BiliBili : https://space.bilibili.com/1363850082

(对文章有疑问或见解可去社区官网提出哦~)
![]() | ![]() |






