replicate-do-db在语句复制中仅按当前数据库(USE)匹配,不按操作表所属库判断,行为反直觉且不可动态生效;推荐改用ROW格式+replicate-wild-do-table。

replicate-do-db 在语句复制模式下几乎没用
MySQL 的 replicate-do-db 只在基于语句的复制(SBR)中起作用,而且行为反直觉:它只过滤「当前数据库」(即 USE db 或当前连接默认库)匹配的语句,不是按语句实际操作的表所属库来判断。比如执行 USE test; UPDATE otherdb.users SET name='a';,这条语句仍会被复制——因为当前库是 test,不匹配 replicate-do-db=otherdb;反过来,如果 USE otherdb,哪怕 UPDATE 的是 test 表,也会被复制。
常见错误现象:SHOW SLAVE STATUS\G 显示 SQL 线程正在执行明显该被过滤的语句,但复制仍在继续。
- 如果你用的是默认的
binlog_format=STATEMENT,replicate-do-db实际上很难精准控制,建议改用行格式 +replicate-do-table或replicate-wild-do-table - 检查当前格式:
SELECT @@binlog_format; - 临时切换(需主从都支持):
SET GLOBAL binlog_format = 'ROW';,但注意事务大、网络带宽和磁盘 IO 压力会上升
replicate-do-db 必须在从库启动前配置才可靠
MySQL 不支持运行时动态生效 replicate-do-db。即使你用 CHANGE REPLICATION FILTER 修改,也仅对后续新建的复制通道有效;已有的 SQL 线程不会重新加载过滤规则,必须重启复制才能应用。
使用场景:上线新过滤策略、修复误同步后想“补救”——别指望改完就停掉不该同步的数据。
- 正确做法:先
STOP SLAVE;,再在my.cnf的[mysqld]段添加或修改replicate-do-db=dbname,然后systemctl restart mysqld(或手动 kill + 重启 mysqld 进程) - 错误做法:只执行
SET GLOBAL replicate_do_db = 'dbname';—— 这个变量根本不存在,MySQL 会报错Unknown system variable 'replicate_do_db' - 验证是否加载成功:
SELECT * FROM performance_schema.replication_applier_filters;(MySQL 8.0.23+),旧版本只能靠SHOW VARIABLES LIKE 'replicate%';查配置项,但不反映运行时状态
大小写敏感与默认库缺失导致匹配失败
replicate-do-db 的值严格区分大小写,且要求语句执行时存在明确的默认数据库。没有 USE、也不带库名前缀的语句(如直接 UPDATE users...)会被 MySQL 视为「无当前库」,此时无论怎么配 replicate-do-db 都不匹配,整条语句被跳过——这反而可能造成数据不一致。
常见错误现象:主库执行不带库名的 DML 后,从库对应表数据没更新,SHOW SLAVE STATUS 却显示 SQL 线程正常运行,找不到错误。
- 确认主库语句是否带库名:开启
general_log或解析主库 binlog:mysqlbinlog --base64-output=DECODE-ROWS -v master-bin.000001 | grep -A2 "UPDATE\|INSERT" - 避免无库上下文:应用层强制所有 SQL 显式指定库名,例如
UPDATE dbname.users...,或连接时指定--database=dbname - 测试匹配逻辑:在从库上模拟执行
USE wrongcaseDB; CREATE TABLE t1(id INT);,看是否被复制——如果replicate-do-db=WrongCaseDB,就不会复制
混合复制模式下 filter 行为更难预测
当主库 binlog_format 设为 MIXED,MySQL 会根据语句类型自动在 STATEMENT 和 ROW 之间切换。而 replicate-do-db 只影响 STATEMENT 模式下的判断,ROW 模式下完全不生效(行事件自带库表信息,但 MySQL 不用它做 replicate-do-db 过滤)。结果就是:同一条逻辑语句,在不同条件下可能被复制或被跳过,极难调试。
性能 / 兼容性影响:启用 MIXED 增加主库判断开销;从库无法统一依赖某一种过滤机制,维护成本陡增。
- 最稳妥的做法:主从统一设为
binlog_format=ROW,改用replicate-wild-do-table=dbname.%替代 - 不要混用:
replicate-do-db和replicate-wild-do-table同时存在时,MySQL 会先按库过滤,再按表过滤,但 ROW 模式下前者无效,容易误以为后者也没起作用 - 检查实际生效的过滤器:
SELECT CHANNEL_NAME, FILTER_NAME, FILTER_RULE FROM performance_schema.replication_applier_filters;(MySQL 8.0.23+),旧版本无此视图,只能靠日志和现象反推
真正麻烦的从来不是写几行配置,而是复制链路里一个看似无关的 USE 语句、一次格式自动切换、或者配置文件里多了一个空格,就能让过滤器彻底失效。别信“试一下”,得查 binlog、看变量、重启验证三步缺一不可。










