触发器是绑定在表上的事件驱动SQL逻辑,由DML自动触发,无显式调用入口;BEFORE可修改NEW数据,AFTER仅能读取且适合日志;典型场景含校验、日志、级联,但存在性能与一致性风险。

触发器本质是“表级自动钩子”
触发器不是独立运行的程序,而是绑定在某张表上的、由 INSERT、UPDATE 或 DELETE 操作自动唤起的一段 SQL 逻辑。它不接受调用,也不依赖应用层——只要 DML 动作发生,且满足定义条件(比如“在 user 表插入前”),就立刻执行。它的底层机制和存储过程类似,但关键区别在于:**没有显式调用入口,只有事件驱动入口**。
BEFORE 和 AFTER 的实际影响远不止“前后”字面意思
BEFORE 触发器能读写 NEW(新行数据),甚至修改它——比如把空 age 改成 0,或拦截非法值并报错(用 SIGNAL SQLSTATE '45000');而 AFTER 只能读 NEW 和 OLD,不能改当前操作的数据,但适合做日志记录、跨表同步这类“事后动作”。注意:BEFORE DELETE 中只能访问 OLD,AFTER INSERT 中没有 OLD——这些限制一旦写错,会直接导致语法错误或逻辑失效。
典型使用场景与真实风险点
常见用途有三类,但每类都藏着隐性成本:
- 数据校验(如订单金额 ≥ 0):用
BEFORE INSERT/UPDATE+SIGNAL实现,但 MySQL 不支持事务内部分回滚,整个语句会失败,需应用层配合重试逻辑 - 操作日志(如往
user_logs插入记录):必须用AFTER,否则日志可能写入但主表插入失败,造成数据不一致 - 级联更新(如下单减库存):看似方便,但若订单表批量插入 1000 行,触发器会执行 1000 次单条
UPDATE,极易拖慢性能——此时更推荐用应用层事务或定时任务补偿
一张表最多允许 6 个触发器(BEFORE/AFTER × INSERT/UPDATE/DELETE),超量会报错 ERROR 1359 (HY000): Trigger already exists;另外,LOAD DATA 和 REPLACE 也会激活对应类型的触发器,这点常被忽略。
查看、删除与调试必须掌握的三条命令
开发中遇到触发器不生效,先确认它是否真的存在且没被覆盖:
- 查所有触发器:
SHOW TRIGGERS LIKE 'user'; - 看创建语句(含 timing/event/table):
SHOW CREATE TRIGGER trigger_insert_person; - 删掉重来(避免命名冲突):
DROP TRIGGER IF EXISTS trigger_insert_person;
别忘了改分隔符——DELIMITER // 是写多语句触发器的前提,漏掉会导致语法解析中断,错误信息往往指向 BEGIN 行而非真正问题点。
触发器最危险的地方不是写错逻辑,而是它静默运行、脱离应用监控体系。上线前务必验证它在批量操作、异常输入、并发写入下的行为,否则故障时连日志都找不到源头。










