replicate-do-db匹配不到跨库操作,因为它仅依据use语句或显式库名前缀判断“当前库”,不解析sql实际操作的库表;gtid模式下必须重启生效,且与replicate-ignore-db混用会导致行为不可预测。

replicate-do-db 为什么匹配不到跨库操作
它只看当前会话的 USE 数据库,不解析 SQL 实际操作的表。比如主库执行 USE test; CREATE TABLE app_db.users (id INT),这条语句的“当前库”是 test,哪怕目标表在 app_db,replicate-do-db = app_db 也不会触发——规则压根没被评估。
常见错误现象:
- 从库
SHOW SLAVE STATUS\G显示Replicate_Do_DB: app_db,但app_db的表始终没建出来 - 主库
USE app_db; INSERT INTO users能同步,但INSERT INTO app_db.users(没USE)却不同步
根本原因是:MySQL 在回放 relay log 时,只检查语句是否“属于”该库,判断依据只有两个:USE db_name 或语句中显式带 db_name.table_name 前缀。两者缺一不可。
GTID 模式下修改 replicate-do-db 必须重启
一旦开启 gtid_mode=ON,所有复制过滤参数都变成只读配置项。运行中执行 SET GLOBAL replicate_do_db = 'app_db' 会直接报错:Variable 'replicate_do_db' is a read only variable。
实操建议:
- 必须在从库首次启动前,把
replicate-do-db = app_db写进/etc/my.cnf的[mysqld]段 - 改完后不能只
mysqladmin reload,必须systemctl restart mysql - 重启后检查
SHOW VARIABLES LIKE 'replicate_do_db'是否生效,再查SHOW SLAVE STATUS\G中的Replicate_Do_DB字段
replicate-do-db 和 replicate-wild-do-table 混用风险高
当同时配置 replicate-do-db = app_db 和 replicate-wild-do-table = app_db.users,MySQL 会按“更精确规则优先”处理,即后者生效;但一旦再加个 replicate-ignore-db = tmp_db,行为就不可预测——白名单和黑名单逻辑冲突,MySQL 不保证执行顺序。
更麻烦的是:replicate-ignore-db 在 MySQL 8.0.26+ 已被标记为 deprecated,官方明确建议弃用。
推荐做法:
- 彻底删除所有
replicate-ignore-db配置 - 统一用
replicate-wild-do-table = app_db.%替代replicate-do-db,它不依赖USE,只要语句涉及app_db下任意表就匹配 - 若需精细控制(如只同步
app_db.users和app_db.orders),写两行:replicate-wild-do-table = app_db.users、replicate-wild-do-table = app_db.orders
replicate-do-db 失效时从库报错 1146 怎么办
典型场景:主库在 test 库下执行 CREATE TABLE app_db.t1,从库因 replicate-do-db = app_db 未启用该语句,导致后续 INSERT INTO app_db.t1 报错 Last_Error: Error 'Table 'app_db.t1' doesn't exist'。
这不是数据不一致的“后果”,而是过滤机制本身的必然结果——replicate-do-db 在 DDL 阶段就跳过了建表语句。
临时绕过方法(仅限紧急修复):
- 在从库手动建表:
CREATE TABLE app_db.t1 (...) - 跳过当前错误:
SET GLOBAL sql_slave_skip_counter = 1; START SLAVE;(仅适用于语句级复制) - 但长期方案仍是换用
replicate-wild-do-table,否则每次跨库 DDL 都可能触发同类问题
真正容易被忽略的点是:这个参数失效时,你看到的往往不是“没同步”,而是“同步了一半”——建表被跳过,插入却执行失败,最终留下一个空壳库或中断的复制流。











