MySQL主从复制依靠binlog把主库的变更同步到从库,但在实际运维中,有时我们并不希望某些表的删除操作被传递到从库。例如从库用作报表查询,禁止任何删表动作;或者从库缺失某张表,主库删表时从库回放就会直接报错。理解同步过滤机制,是从架构层面解决这类问题的关键。

一、为什么表删除会在从库报错
在典型的基于binlog的复制中,主库执行的DROP TABLE或DELETE操作都会以事件形式写入二进制日志,从库的SQL线程读取后重新执行。如果这张表在从库根本不存在,或者从库被设置为super_read_only且过滤规则未生效,从库执行删除时就会抛出1146(Table doesn't exist)或1036(Table is read only)等错误,导致复制中断。
一旦复制线程停止,从库状态会停留在出错的事务点,后续所有同步都会停滞。过去常见的临时处理是在从库跳过错误事件,但这会破坏数据一致性。更合理的做法是提前配置同步过滤,让从库压根不接收这类危险操作。
二、MySQL同步过滤的核心参数
MySQL提供了多个复制过滤选项,常用的包括replicate_ignore_db、replicate_ignore_table以及replicate_wild_ignore_table。其中replicate_ignore_table用于精确忽略某张表的全部复制事件,replicate_wild_ignore_table支持通配符,适合批量忽略符合命名规则的表。
这些参数既可以在启动时通过命令行指定,也可以写入配置文件永久生效。需要注意,过滤规则是在从库SQL线程回放前生效的,也就是说被忽略的表操作不会在从库执行,自然也就不会触发删表报错。但要注意,过滤是基于从库视角,主库binlog依然完整,若日后调整架构需重新同步数据,要评估数据差异。
2.1 配置文件写法示例
假设从库需要忽略主库test库下的tmp_log表所有操作,可以在从库my.cnf的[mysqld]段落添加如下配置:
[mysqld] # 忽略指定库的指定表,格式为 库名.表名 replicate_ignore_table=test.tmp_log # 使用通配符忽略所有以 _bak 结尾的表 replicate_wild_ignore_table=test.%.bak
修改后需重启从库MySQL服务,或者通过CHANGE REPLICATION FILTER语句在线调整(MySQL 5.7+支持)。重启后可以通过SHOW SLAVE STATUS查看过滤规则是否加载。
2.2 在线动态调整过滤
如果不想重启实例,可以使用如下语句临时设置忽略规则:
STOP SLAVE SQL_THREAD;
CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE = ('test.tmp_log');
START SLAVE SQL_THREAD;
这种方式在故障应急时非常有用。不过在线修改在实例重启后会失效,因此稳定环境仍建议写进配置文件。同时,多个过滤规则会按顺序匹配,建议通过SHOW REPLICATE_FILTERS(部分版本支持)或错误日志确认实际生效范围。
三、基于库与基于表的过滤对比
很多团队图省事直接用replicate_ignore_db忽略整个库,但这会带来隐式跨库风险。例如在主库使用test库连接去更新其他库的表,基于库的忽略可能失效。而基于表的replicate_ignore_table则更精确,只挡住特定表,不影响同库其他业务表同步。
| 过滤方式 | 粒度 | 适用场景 | 风险 |
|---|---|---|---|
| replicate_ignore_db | 库级 | 整库不参与复制 | 跨库SQL可能漏过滤 |
| replicate_ignore_table | 表级 | 单表保护或缺失表 | 需逐个配置 |
| replicate_wild_ignore_table | 表级通配 | 批量临时表 | 通配不当误忽略 |
从实践看,报表从库通常只需要忽略几张写频度高或结构不一致的表,使用表级通配就能兼顾维护成本与安全性。核心交易从库则不建议开启任何忽略,以保证数据强一致。
四、配置后的校验与监控
配置同步过滤后,必须验证从库复制状态。执行SHOW SLAVE STATUSG,重点观察Slave_SQL_Running是否为Yes,以及Last_Error是否为空。若之前因删表报错而中断,重新启动复制后错误应不再出现。
另外可以在主库对忽略表执行一次DROP TABLE,然后到从库查询该表是否依然存在。若从库表未被删除且复制无报错,说明过滤生效。日常监控中,建议把Seconds_Behind_Master和Last_SQL_Error纳入告警,避免新的过滤盲区引发复制停滞。
五、避坑与总结
有一点容易混淆:同步过滤不是在主库控制,而是从库行为。如果在主库设置ignore规则,是不会影响复制的。此外,使用GTID模式时,被过滤的事务依然会记录GTID,只是不执行,因此从库Executed_Gtid_Set可能少于主库,这是正常现象,不要误判为数据丢失。
总体思路是:先明确从库角色,再选择库级或表级过滤,通过配置文件固化规则并配合监控。这样即便主库发生表删除,从库也能安稳跳过,不再出现复制报错,保障下游业务连续性。