mysql复制中库级过滤应避免replicate-do-db/replicate-ignore-db,因其在row格式下失效;推荐用replicate-wild-do-table实现库表全路径匹配,gtid环境下更需谨慎,禁用reset master以防gtid错位。

MySQL复制中如何用 replicate-do-db 和 replicate-ignore-db 控制库级过滤
这两个参数只在 STATEMENT 格式复制下按「当前数据库」生效,ROW 格式下基本失效——因为行格式不记录 USE db_name,从库无法判断语句本意操作的是哪个库。
常见错误现象:INSERT INTO other_db.t1 ... 在主库执行时没切换库,但目标表在 other_db,从库却因 replicate-do-db=mydb 被跳过,数据丢失。
- 仅当所有 DML 都显式
USE mydb且不跨库操作时,replicate-do-db才可靠 - 避免混用
STATEMENT和ROW格式;若必须做库级过滤,统一用ROW+ 表级规则更稳妥 - 多个库需过滤时,每项单独写一行配置,不能用逗号分隔
用 replicate-wild-do-table 实现模糊表名匹配
这是最常用也相对可靠的过滤方式,支持通配符 % 和 _,对 STATEMENT 和 ROW 均有效,且基于实际修改的表名匹配,不依赖当前库上下文。
例如只同步 user_service 库下以 user_ 开头的表:
replicate-wild-do-table = user_service.user_%
注意点:
- 通配符只作用于表名部分,库名不能含
%(即不支持%.t1) - 如果主库有
user_service.user_profile和order_service.user_log,后者不会被匹配——replicate-wild-do-table是「库名.表名」全路径匹配 - 多个规则按顺序逐条匹配,第一条命中即执行,后续忽略;未命中则跳过该事件
为什么 binlog-do-db 不等于复制过滤
binlog-do-db 是主库参数,控制哪些库的更改写入 binlog;它不是复制过滤器,而是日志裁剪开关。一旦启用,连 SHOW BINLOG EVENTS 都看不到被排除库的操作,GTID 也会断连,从库无法追平。
典型误用场景:想让从库少同步点数据,就在主库加 binlog-ignore-db=test,结果导致:
- 主从 GTID 集合不一致,
SELECT MASTER_GTID_WAIT()失效 - 切换主库或搭建新从库时,缺失的 binlog 无法补全
-
mysqlbinlog --database=test解析不到任何事件,调试困难
结论:复制过滤逻辑必须放在从库侧,主库应保留完整 binlog。
GTID 模式下过滤的兼容性陷阱
GTID 要求事务在所有节点上「完全一致地执行或跳过」,而过滤规则是单边从库行为。MySQL 5.7+ 允许在 GTID 环境下使用 replicate-* 参数,但存在两个关键限制:
-
replicate-ignore-table类规则在 GTID 下仍可用,但replicate-do-db在ROW格式中几乎无效,慎用 - 跳过的事务仍会占用 GTID,从库
gtid_executed包含这些空跳 ID,但gtid_purged不包含——这会导致RESET MASTER后无法再挂新从库 - 若用
mysqldump --set-gtid-purged=ON导出带过滤的从库,生成的SET @@GLOBAL.GTID_PURGED可能漏掉被跳过的 GTID,恢复后主从 GTID 集合错位
真正安全的选择是:GTID 环境下优先用 replicate-wild-do-table,避免库级参数,且不要在生产从库上随意 RESET MASTER 或 CHANGE MASTER TO ... GTID_SET。










