否,Row格式下从库不执行触发器,主库触发器效果已体现在binlog行变更中,从库仅应用数据变更而不重放触发器逻辑,这是设计行为而非bug。
主库上触发器通常只影响当前事务,而从库的 SQL thread 是单线程(MySQL 5.6 及以前)或受限于并行复制粒度(MySQL 5.7+),所有触发器逻辑都串行执行。一旦某个触发器涉及 UPDATE 或 INSERT ... SELECT 等扫描操作,就可能长时间持有行锁或表锁,阻塞后续 relay log 中的其他事件。
常见表现是:SHOW PROCESSLIST 中看到 Slave_SQL_Running_State 长时间停留在 Updating 或 Waiting for table metadata lock;同时 Seconds_Behind_Master 持续上涨。
MySQL 主从复制默认使用 binlog_format=ROW(推荐),此时主库记录的是变更后的行镜像,而非原始 SQL。但触发器本身不写入 binlog —— 它只在主库执行一次,从库不会重新触发,除非你显式启用 log_bin_trust_function_creators=1 并把触发器定义也同步过去(极不推荐)。
问题在于:如果主库触发器修改了额外字段(比如自动填充 updated_at),而从库表结构缺失对应触发器,就会出现数据不一致;若强行在从库也部署相同触发器,则可能因执行时机(before/after)、上下文(如 NEW 值来源)不同,导致重复更新或违反约束。
ROW 复制下,从库跳过触发器逻辑 → 数据差异风险STATEMENT 复制下,触发器被重放 → 但 STATEMENT 本身已不安全,且容易因非确定性函数失败gtid_mode=ON,也无法解决触发器语义在主从两端不对等的问题一个典型的批量导入场景:INSERT INTO orders (...) SELECT ... FROM staging; 插入 10 万行,每行触发 AFTER INSERT 更新统计表。主库可能通过优化(如 bulk insert 缓冲)快速完成;但从库 SQL thread 必须逐行回放,每行都执行一次触发器逻辑,相当于把 1 次批量操作拆成 10 万次单行操作。
这时你会观察到:Relay_Log_Space 增长缓慢,但 Seconds_Behind_Master 直线上升,SHOW SLAVE STATUS 中 Exec_Master_Log_Pos 几乎不动。
有人尝试在从库执行 SET sql_log_bin = 0; 后删掉触发器,以为能“跳过”逻辑。这很危险:一旦主库后续有 DDL 修改触发器定义,或者该触发器本就是业务一致性关键路径(如生成唯一流水号),从库缺失它就会直接导致数据错乱。
更稳妥的做法是——根本不在主从架构中依赖触发器做跨表联动。真正需要强一致的关联写入,应由应用层统一控制事务边界;弱一致场景(如日志归档),用 EVENT 或外部调度替代。
最容易被忽略的一点:即使你没主动创建触发器,某些 ORM 框架(如 Django 的 pre_save)或中间件(如 ShardingSphere 的自动分表路由)可能在连接层注入类触发行为,它们同样会在线程模型受限的从库上暴露放大效应。