MySQL主从同步中跳过某表复制需在从库my.cnf配置replicate-ignore-table或replicate-wild-ignore-table并重启mysqld;动态SET无效,过滤仅作用于SQL线程重放阶段,不删除已同步数据。
MySQL 主从同步怎么跳过某个表的复制
主从同步中想让从库不复制某张表,核心是配置 replicate-ignore-table 或 replicate-wild-ignore-table,但必须在从库的 my.cnf 中设置并重启 mysqld 才生效——动态 set 不起作用。
常见错误是直接在从库执行:SET GLOBAL replicate_ignore_table = 'db1.t1';,这完全无效,变量只读,且 MySQL 不支持运行时修改这类复制过滤规则。
-
replicate-ignore-table精确匹配,格式必须是db_name.table_name,大小写敏感(取决于lower_case_table_names设置) -
replicate-wild-ignore-table支持通配符,比如db1.log_%或test.%,更灵活,也更常用 - 多个表要忽略?写多行,每行一个配置项,不能用逗号分隔
- 配置后必须重启从库进程,否则不加载;重启后检查
SHOW SLAVE STATUS\G的Replicate_Ignore_Table字段是否已更新
为什么 replicate-do-db 和 replicate-ignore-db 很容易出错
这两个基于数据库名的过滤规则实际依赖 SQL 线程当前的 USE 数据库,而不是语句里显式写的库名。比如执行 INSERT INTO db1.t1 ... 但当前没 USE 任何库,或 USE 的是 db2,那这条语句可能被意外放过或拦截。
真正安全的场景极少,除非所有写操作都严格先 USE db_x 再执行跨库语句(现实中几乎没人这么干)。
- DDL(如
CREATE TABLE db1.t2)同样受此影响,replicate-ignore-db对它基本不可靠 - 如果用了 GTID,这些基于库/表名的过滤规则还会导致
gtid_executed和gtid_purged不一致,后续切换主库可能失败 - 优先用
replicate-wild-ignore-table替代,明确到表,行为可预测
从库已同步了不该同步的表,现在想补救
过滤规则只对新事件生效,不会自动删除从库上已存在的数据。如果那张表已经同步过来,得手动清理。
- 先停复制:
STOP SLAVE; - 确认从库该表无业务写入(否则删了会丢数据),再执行
DROP TABLE db1.t1; - 重新启动:
START SLAVE;,此后主库对该表的任何变更都不会再同步过来 - 注意:如果主库该表后续有
DROP DATABASE或TRUNCATE操作,从库因表不存在会报错(Table doesn't exist),需人工跳过(SET GLOBAL sql_slave_skip_counter = 1;或用gtid_next跳过单个事务)
使用 replicate-wild-ignore-table 时的路径陷阱
通配符匹配的是“语句中出现的库名和表名”,不是磁盘路径,但要注意反斜杠、点号、下划线这些字符在正则语义里有特殊含义——而 MySQL 的 wild-ignore 是简单 shell 风格通配(* 匹配任意字符,? 匹配单字符,_ 就是字面量下划线)。
- 想忽略
log_20240101这种带日期的表?写成db1.log_*即可,_不需要转义 - 想忽略
db1.user_info和db1.user_settings?用db1.user_*,别写成db1.user%(%在这里是普通字符,不是通配符) - 配置值里不能有空格,比如
replicate-wild-ignore-table = db1.t1 , db1.t2会解析失败,必须换行或去掉空格 - 大小写:Linux 下默认区分,
DB1.T1和db1.t1是两个不同匹配目标
Relay_Log_Space)不会变小,排查延迟时容易误判。










