不会。mysql在row格式下从库不执行触发器,仅回放主库触发器产生的行变更结果;但若触发器含now()、uuid()等非确定性函数,会静默退化为statement模式导致重复执行和数据不一致。

触发器在ROW格式下是否会被从库执行
不会。MySQL主从复制中,binlog_format = ROW 时,触发器本身不被复制,只记录它产生的最终行变更(Write_rows_log_event)。从库回放的是“变更结果”,不是触发器逻辑——这是安全的前提,也是降低延迟的关键。
但有个严重例外:只要触发器里出现 NOW()、UUID()、USER()、子查询带 LIMIT,或更新了未显式出现在 binlog 中的表,MySQL 就会**静默退化为 STATEMENT 格式**记录该事件。此时从库必须重新执行原始 SQL,触发器逻辑可能被重复执行,且破坏一致性。
- 验证方式:在主库执行
SHOW BINLOG EVENTS IN 'mysql-bin.000001' LIMIT 20,看是否混有Query_log_event(STATEMENT)和Table_map_log_event(ROW) - 修复动作:把触发器内所有非确定性函数调用替换成常量或由应用层传入;避免跨表操作;用
SELECT ... FOR UPDATE前确认是否真有必要
DEFINER 用户缺失导致从库加载失败
MySQL 8.0 加载触发器时会严格校验 DEFINER 用户是否存在、是否有 TRIGGER 权限。主库上 DEFINER='zabbix'@'localhost' 的触发器,若从库没这个用户,启动时就会报错:[ERROR] [MY-010952] Failed to load trigger 'xxx': Access denied,甚至整个 SQL Thread 卡住。
不能靠“忽略错误”绕过——8.0 不再容忍空或无效 DEFINER。必须提前处理:
- 导出前用
SELECT DEFINER FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = 'db_name'扫描所有触发器定义者 - 在从库确认对应用户存在:
SELECT User,Host FROM mysql.user WHERE User = 'zabbix' - 若用户不存在,要么重建该用户并赋权
GRANT TRIGGER ON *.* TO 'zabbix'@'localhost',要么导出后全局替换DEFINER=`zabbix`@`localhost`为DEFINER=CURRENT_USER
mysqldump 导出触发器时漏掉 --triggers 参数
默认 mysqldump 完全不导出触发器,即使加了 --routines 也不管用。漏掉 --triggers 意味着从库导入后触发器彻底消失,业务逻辑断裂——比如审计日志写入、状态自动更新全部失效。
尤其注意两个坑:
-
-B(即--databases)不会自动启用--triggers,必须显式加上 - 导出命令必须同时含
--triggers和--routines,否则存储过程/函数缺一不可,而触发器依赖的函数若未先导入,CREATE TRIGGER会直接报Can't find function - 正确示例:
mysqldump -u root -p --triggers --routines --databases mydb > backup.sql
主从延迟突然升高,怎么快速定位是触发器惹的祸
别猜。直接查从库当前卡在哪:
- 运行
SHOW REPLICA STATUS\G,重点看Slave_SQL_Running_State字段——如果卡在Updating、System lock或Waiting for table metadata lock,且持续数秒以上,大概率是触发器在从库执行慢查询 - 配合
SHOW PROCESSLIST,找State为Updating且Info显示涉及触发器关联表的线程 - 临时验证:在从库执行
SET SESSION sql_log_bin = 0,然后手动重放一条主库刚执行过的带触发器的语句,看是否同样卡住——如果是,说明触发器逻辑本身有性能问题
真正麻烦的不是触发器存在,而是它在从库单线程回放时做了不该做的事:访问大表、调用复杂函数、锁等待。这类问题往往在压力上升后才暴露,上线前务必在从库压测触发路径。











