MySQL中同一事件和时机的触发器按创建时间升序执行,先建先触发;BEFORE全部执行完才执行语句主体,再执行AFTER;无法显式调整优先级,只能重建控制。

触发器执行顺序由事件类型和定义顺序共同决定
MySQL 不允许显式指定多个触发器的执行优先级,但实际执行顺序是确定的:同一张表、同一事件(如 INSERT)、同一时机(BEFORE 或 AFTER)下,触发器按创建时间升序执行——也就是先建的先触发。这个顺序无法通过 ALTER TRIGGER 调整,只能靠重建控制。
- 不同事件(
INSERT/UPDATE/DELETE)之间不互相干扰,不存在交叉排序问题 -
BEFORE和AFTER触发器严格分阶段执行:BEFORE全部跑完才进入语句主体,再执行所有AFTER - 若需改变逻辑先后关系,必须
DROP TRIGGER后按目标顺序重新CREATE TRIGGER
同一事件下多个 BEFORE/AFTER 触发器不能并行或跳过
MySQL 会强制串行执行同类型的触发器,且不提供禁用某一个而保留其余的机制。如果你在调试时发现某个 BEFORE INSERT 触发器修改了新行数据,后续同为 BEFORE INSERT 的触发器会看到已被前一个改过的 NEW 值——这是隐式依赖,容易引发意料外的行为。
- 避免在多个
BEFORE触发器中反复赋值给同一个NEW.column,除非你明确需要链式覆盖 - 不要假设触发器之间有“隔离”,它们共享同一事务上下文和临时修改状态
- 用
SHOW TRIGGERS LIKE 'table_name'查看当前顺序,输出中的Timing和Created字段可辅助判断
触发流程无法被 SQL 语句中途打断或跳过
只要 DML 语句成功匹配到触发条件(比如对某张有触发器的表执行 INSERT),对应的所有匹配触发器就会无条件执行。没有类似 SKIP TRIGGER 的语法,也无法在存储过程中动态启用/禁用单个触发器。
- 临时绕过方式只有两种:用
DISABLE KEYS不起作用,真正有效的是SET sql_log_bin = 0(仅限二进制日志,不影响触发器本身)或切换用户权限(移除TRIGGER权限) - 更稳妥的做法是在触发器内部加判断逻辑,例如检查
USER()或自定义会话变量@skip_trigger,但需确保调用方主动设置 - 注意:触发器内不能执行
COMMIT或ROLLBACK,否则报错ERROR 1422 (HY000): Explicit or implicit commit is not allowed in stored function or trigger
跨表触发器不会自动形成调用链
如果 TRIGGER t1 在表 A 上,它对表 B 执行 INSERT,而表 B 上又有 TRIGGER t2,那么 t2 会被正常激活——但这不是 MySQL “调度”出来的,而是因为 DML 语句本身触发了目标表的规则。这种间接调用容易造成递归或死锁,尤其当两个触发器相互写对方的表时。
- MySQL 默认不限制嵌套深度,但可通过系统变量
max_sp_recursion_depth控制(默认为 0,即不限制;设为非零值可限制存储过程/触发器递归层数) - 使用
SELECT @@session.max_sp_recursion_depth查看当前会话设置 - 线上环境建议显式设为较小值(如 5),避免意外无限触发导致连接卡死
CREATE TRIGGER 时间戳一旦写入数据字典就不可更新,哪怕修改了触发器体内容,也不改变其执行序位**。










