答案:replicate-do-table是语句级白名单,非表数据级开关。它匹配SQL中显式写出的库表名(如db1.t1),不依赖USE语句,但跨库操作易失配;需STOP SLAVE SQL_THREAD后用CHANGE REPLICATION FILTER在线修改,不支持通配符;与ignore规则冲突时后者优先;生产推荐改用replicate-wild-do-table。

replicate-do-table 只对跨库操作有效,不是“只同步某张表”
replicate-do-table 看似直白,但它的行为和多数人想的不一样:它**不检查 SQL 语句的目标表名是否匹配,而是检查语句中显式出现的表名(含库前缀)是否匹配规则**。这意味着:
- 如果主库执行
USE db1; INSERT INTO t1 VALUES (1);,而replicate-do-table = db1.t1,这条语句会被复制 - 但如果执行
INSERT INTO db1.t1 VALUES (1);(没 USE),同样能匹配成功 - 而
INSERT INTO db2.t1 SELECT * FROM db1.t2;这种跨库语句——即使目标是db1.t1,只要语句里没写全db1.t1(比如只写了t1),就可能被跳过
所以它本质是“语句级白名单”,不是“表数据级开关”。真正想按表名精确控制,replicate-wild-do-table 更可靠。
配置 replicate-do-table 必须停 SQL 线程,不能热生效
MySQL 5.7 虽支持 CHANGE REPLICATION FILTER 在线修改,但对 replicate-do-table 这类旧参数,仍需先停掉 SQL 线程:
STOP SLAVE SQL_THREAD;CHANGE REPLICATION FILTER REPLICATE_DO_TABLE = ('db1.t1', 'db1.t2');START SLAVE SQL_THREAD;
注意:REPLICATE_DO_TABLE 不支持通配符,必须写全 db_name.table_name;多个表要一次性用括号+逗号列出,不能重复写多条 CHANGE 语句。
replicate-do-table 和 replicate-ignore-table 优先级冲突时 ignore 生效
如果同时设置了 replicate-do-table = db1.t1 和 replicate-ignore-table = db1.t1,后者会胜出——整条涉及该表的语句都会被跳过,不管是否在 do 列表里。
- 这种冲突常见于运维误配或脚本批量生成配置时
-
SHOW SLAVE STATUS\G中的Replicate_Do_Table和Replicate_Ignore_Table字段会显示当前值,但不会提示冲突 - 验证方法:在主库执行一条明确操作该表的语句(如
INSERT INTO db1.t1 VALUES (NOW());),再查从库是否落地
比 replicate-do-table 更推荐用 replicate-wild-do-table
几乎所有生产环境都应该跳过 replicate-do-table,直接用 replicate-wild-do-table:
- 它匹配的是 binlog 事件中的实际库表名,不依赖 USE 或语句写法
- 支持
%和_通配符,例如replicate-wild-do-table = app_log.2026_%可精准捕获日表 - 可与
replicate-wild-ignore-table共存,ignore 仍具更高优先级 - 修改后只需
STOP SLAVE; START SLAVE;,无需重启 mysqld
真正难搞的从来不是怎么写规则,而是确认 binlog_format 是 ROW(推荐)还是 STATEMENT——前者让表名匹配更稳定,后者在跨库、函数调用等场景下容易失准。


















