replicate_do_db常同步失败,因其仅依赖use上下文而非sql实际操作对象,如use work后执行drop user会误判为操作work库;推荐改用replicate_wild_do_table配合binlog_format=row,并显式忽略系统库。

replicate_do_db 为什么经常同步失败
它只看客户端执行的 USE db_name,不解析 SQL 实际操作对象。比如你在主库上 USE work,然后执行 DROP USER 'guest'@'localhost',MySQL 会把这条语句当成对 work 库的操作去匹配规则——哪怕它真正影响的是 mysql 系统库。从库上没这个用户,直接报错中断复制。
常见错误现象包括:Last_SQL_Error 显示类似 Can't drop user 'guest'@'localhost',但你根本没在 work 库里建过用户;跨库语句如 INSERT INTO db2.t SELECT * FROM db1.t 完全失效;多个库用逗号分隔时多一个空格(replicate_do_db=db1, db2)就导致整条配置被忽略。
这类问题在运维账号、清理系统表、触发器调用跨库逻辑时高频出现,且难以复现。
replicate_wild_do_table 是更稳的选择
它直接按表名字符串匹配,绕过 USE 上下文,只要 SQL 涉及的表名符合通配模式,就触发同步。例如:
-
replicate_wild_do_table = db1.%→ 同步所有db1下的表,无论当前是否USE db1 -
replicate_wild_do_table = db1.table_%→ 只同步db1中表名以table_开头的表 - 可叠加多条:配置
replicate_wild_do_table = db1.%和replicate_wild_do_table = db2.test_01即可混合白名单粒度
注意:replicate_wild_do_table 必须配合 binlog_format=ROW 才可靠。如果主库是 STATEMENT 或 MIXED,某些跨库 DML(如子查询涉及多库)可能被错误放行或拦截。
检查并设置主库格式:SELECT @@binlog_format;,不是 ROW 就得改配置并重启,或用 SET PERSIST binlog_format = 'ROW';(需 SUPER 权限)。
忽略系统库必须显式加 wild_ignore 规则
即使你只配了 replicate_wild_do_table = db1.%,默认仍会同步 mysql、performance_schema 这类系统库里的变更——因为它们不匹配你的白名单,但也没被明确禁止。一旦主库执行了 CREATE USER 或 GRANT,从库就可能因权限表结构差异或用户已存在而中断。
务必加上这两行:
replicate_wild_ignore_table = mysql.%replicate_wild_ignore_table = performance_schema.%
如果用了 sys 库或自定义监控库,也建议一并加入 replicate_wild_ignore_table。这些规则优先级高于 replicate_do_db,且不依赖 USE 上下文。
配置后必须重启 SQL 线程,不能只 reload 配置
修改 my.cnf 后,不能只执行 systemctl restart mysqld 或 mysqladmin reload —— 大多数过滤参数(包括 replicate_wild_do_table)属于「冷配置」,需要先停掉 SQL 线程再重载规则。
正确步骤是:
- 在从库执行:
STOP SLAVE SQL_THREAD; - 确认
Slave_SQL_Running: No后,再执行:START SLAVE SQL_THREAD; - 观察
SHOW SLAVE STATUS\G中的Seconds_Behind_Master是否归零、Last_SQL_Error是否为空
漏掉这一步,配置看似生效,实际 SQL 线程仍在用旧规则运行,后续任何跨库操作都可能突然报错。真正麻烦的不是写错几行配置,而是忘了这一步重启线程,以及忽略了 binlog_format 和系统库过滤这两个隐性依赖点。











