mysql replicate-* 参数为静态配置,需停启sql线程才能生效,且row格式下replicate-do-db/ignore-db失效;replicate-wild-ignore-table仅匹配表名部分通配符,库名不能含%或_,大小写敏感,规则按顺序匹配且只作用于sql线程重放阶段。

绝大多数情况下,不是规则写错了,而是根本没加载进去。 MySQL 的 replicate-* 类参数(比如 replicate-ignore-table、replicate-wild-do-table)全部是静态配置,SET GLOBAL 无法实时生效,必须重启 SQL 线程或整个 mysqld 进程。
为什么 SET GLOBAL replicate_ignore_table = 'db.t' 没用
MySQL 不报错,但也不执行。这个变量确实会被写入全局状态(SHOW VARIABLES LIKE 'replicate_ignore_table' 能看到新值),可正在运行的 SQL 线程压根不读它——过滤器只在启动时初始化一次。
- 执行
SET GLOBAL replicate_ignore_table = 'db.t'后,SHOW SLAVE STATUS\G里的Replicate_Ignore_Table字段仍显示旧值 - 主库往
db.t写数据,从库照样同步,毫无反应 - 这是官方明确行为,不是 bug,文档里写着:“Changes take effect only after the slave SQL thread has been stopped and restarted.”
replicate-do-db 在 ROW 格式下完全失效
如果你的 @@binlog_format 是 ROW(当前主流默认),那 replicate-do-db 和 replicate-ignore-db 就等于没配。它们依赖主库执行时的 USE db 上下文,而行格式日志里不带这个信息。
- 主库执行
INSERT INTO app_log.audit_log(没USE app_log),从库配了replicate-do-db = app_log→ 该语句被跳过,数据丢失 - DDL 语句(如
CREATE TABLE)始终以 STATEMENT 格式记 binlog,所以库级过滤对 DDL 可能“偶然生效”,但不可靠,且会破坏 GTID 一致性 - 验证方式:
SELECT @@binlog_format;,返回ROW就别碰这两个参数
replicate-wild-ignore-table 配置写错也白搭
它匹配的是「库名.表名」全路径,不是模糊搜索,通配符只作用于表名部分,库名不能含 % 或 _,且大小写敏感。
-
replicate-wild-ignore-table = user_service.user_%→ 正确,匹配user_service.user_profile -
replicate-wild-ignore-table = %.user_%→ 错误,%不能出现在库名位置,整条规则被忽略 - 库名含下划线(如
app_db)必须写成app\_db.%,否则_当通配符处理 - 若主库
lower_case_table_names = 0(区分大小写),从库也必须设为0,否则MyDB.t1不匹配mydb.t1
改完配置后忘了重启 SQL 线程
所谓“在线修改”,是指不用重启 mysqld,但必须显式停启 SQL 线程才能重载规则。IO 线程可以不停,避免 relay log 积压。
- 正确顺序:
STOP SLAVE SQL_THREAD;→SET GLOBAL replicate_wild_ignore_table = 'db.log_%';→START SLAVE SQL_THREAD; - 只执行
STOP SLAVE;再START SLAVE;也行,但会短暂中断 IO 拉取 - 验证是否生效:主库执行
INSERT INTO db.log_20260810 VALUES (1);,查从库对应表是否真的没新增数据 - 多条规则按文件中出现顺序匹配,第一条命中即终止,后续不检查
最容易被忽略的一点:所有复制过滤都只作用于 SQL 线程重放阶段,不会删除从库上已存在的数据;如果表已经同步过来,得手动 DROP TABLE,且要确认无业务写入,否则直接删会丢数据。











