触发器未执行的首要原因是STATUS为DISABLED或操作类型不匹配,需查information_schema.TRIGGERS确认状态与事件类型;TRUNCATE、无变更UPDATE、REPLACE等天然不触发;错误常藏于SHOW WARNINGS中,且DEFINER权限和跨库路径必须正确。

触发器没执行,八成不是代码写错了,而是压根没被调用——最常见原因是 STATUS 为 DISABLED,或操作类型根本不在触发器定义范围内。
查触发器是否真启用:别信 SHOW TRIGGERS 就完事
MySQL 不会提示触发器被禁用了,它就安静地挂在那里。你执行 INSERT 成功,但逻辑没跑,第一反应该查系统表。
- 运行
SELECT TRIGGER_NAME, STATUS, EVENT_MANIPULATION, EVENT_OBJECT_TABLE FROM information_schema.TRIGGERS WHERE TRIGGER_NAME = 'your_trigger_name';,确认STATUS是ENABLED,且EVENT_MANIPULATION(比如INSERT)和你的实际操作一致 -
SHOW TRIGGERS LIKE 'table_name';很快,但它只查当前库;跨库必须先USE db_name再查 - MySQL 5.7 不支持
ALTER TRIGGER ... ENABLE,禁用后只能DROP TRIGGER+ 重建
TRUNCATE、UPDATE SET x=x、REPLACE INTO 这些操作天然不走触发器
这不是配置问题,是 MySQL 的行为设计。你以为在清空表或更新字段,其实触发器连解析阶段都没进。
-
TRUNCATE TABLE t是 DDL 操作,不生成inserted/deleted伪表,任何INSERT/UPDATE/DELETE类型触发器都完全不触发 - MySQL 8.0+ 中,
UPDATE t SET name = name这种无实际变更的语句,默认跳过触发器——检查@@sql_mode是否含STRICT_TRANS_TABLES,否则它会静默忽略 -
REPLACE INTO和INSERT ... ON DUPLICATE KEY UPDATE在部分版本中只触发BEFORE UPDATE,不触发BEFORE INSERT,得看具体版本和事件定义
触发器里报错却被吞掉:立刻执行 SHOW WARNINGS
触发器失败通常不抛给客户端,主语句可能成功也可能失败,但错误信息藏在警告里,不主动查就看不到。
- 执行完疑似失败的
INSERT或UPDATE后,**马上**运行SHOW WARNINGS;,常能捕获真实错误,比如Unknown column 'xxx' in 'field list'或Undeclared variable: NEW.invalid_col - 确保错误日志开启:
SELECT @@log_error;确认路径可读(如/var/log/mysql/error.log),并设SET GLOBAL log_error_verbosity = 3;(MySQL 8.0+) - 别在触发器里写裸
SELECT col FROM t,必须接INTO @var,否则直接报ERROR 1415 (0A000)
跨库写日志、改其他表、用 NEW/OLD 字段,权限和路径一个都不能漏
触发器执行用的是 DEFINER 用户权限,不是你当前登录用户;而且所有表名都得带库前缀,否则默认找当前库。
- 查定义:
SHOW CREATE TRIGGER trigger_name;看DEFINER是谁;再查SHOW GRANTS FOR 'definer_user'@'%';,确认它对日志表(如sys_log.audit_log)有INSERT权限 - 触发器内写日志不能只写
INSERT INTO audit_log,必须写全路径:INSERT INTO sys_log.audit_log -
DEFINER若没有对原表的SELECT权限,OLD.col或NEW.col可能读不到值,导致后续判断失效,且不报错
真正难排查的,往往是那些“看似执行了、实则中途静默退出”的情况——比如 IF 条件不满足直接跳过主体逻辑,或者 sql_mode 不严格导致类型转换失败却不中断。动手前先建张独立的 debug_log 表,把关键节点写进去,比猜强得多。


















