MySQL触发器不能显式调用其他触发器,所谓嵌套实为当前触发器执行DML操作(如INSERT INTO t2)间接激活目标表上已定义的触发器;跨表可行,但自表递归默认禁止,须开启innodb_recursive_triggers。

MySQL 触发器根本不能“触发其他触发器”——所谓嵌套,全是靠 DML 语句间接激活的假象。你写不出 CALL、EXECUTE 或任何显式调用语法,所有“链式执行”都依赖于当前触发器里是否真有对**另一张表**(或同一张表但开启递归)的 INSERT/UPDATE/DELETE。
触发器之间没有调用关系,只有隐式 DML 激活
很多人以为在 t1 的触发器里写个 INSERT INTO t2 就是“调用了 t2 的触发器”,其实不是调用,是「触发条件被满足」:只要 t2 上定义了对应事件(比如 AFTER INSERT),且该语句成功执行,就会被 MySQL 自动拉起。
-
INSERT INTO t2 VALUES ()能激活t2的触发器,前提是语句没被事务回滚、没报错、没违反外键约束 -
UPDATE t1 SET x = 1 WHERE id = NEW.id在默认配置下不会再次触发t1上的任何触发器,哪怕逻辑上看起来“又改了一次” - 试图用
SELECT ... INTO或子查询绕过限制?没用。ERROR 1442 是解析期硬拦截,不看内容只看语义
跨表链式触发可行,但自表递归默认关闭
想让一张表的触发器最终影响到自己,必须显式打开 innodb_recursive_triggers,而且要承担风险:
- 该变量是全局的,设为
ON后,所有表都可能递归,不是单个触发器可控 - 递归深度受
max_sp_recursion_depth限制(默认 6),超限直接报 ERROR 1456 - 即使只改一行,若触发器内又
UPDATE t1→ 再触发自身 → 再UPDATE t1… 很快就爆栈 - 调试时容易误判:一条
INSERT ... SELECT影响 100 行,会看到 100 条触发记录,这不是嵌套,是正常逐行触发
主从复制会让“看似嵌套”的行为失效
主库上 t1 触发器插入 t2,t2 触发器再插入 t3,整条链在主库跑通;但从库只会重放 binlog 里的原始语句(比如主库那条 INSERT INTO t1),t2 和 t3 的变更都是主库直接写的,从库上的 t2 和 t3 触发器完全不执行。
- 从库触发器默认被忽略,这是 MySQL 复制机制决定的,不是 bug
- 不能靠
SET sql_log_bin = OFF在从库临时启用——这会破坏主从一致性 - 如果业务强依赖链式日志(比如操作
t1必须同步记审计到sys_log.audit_log),得确保目标表也在主库上,并由主库触发器直写
最容易被忽略的是:触发器逻辑是否真的走到了那条关键 DML 语句。比如 BEFORE UPDATE 里加了条件判断,结果因 NEW.status = OLD.status 直接跳过后续 INSERT INTO t2,整条链就断了——它不是“没嵌套”,是压根没走到嵌套那步。


















