触发器能自动执行数据联动更新、审计留痕和强制校验与修正三类操作;即表级事件(insert/update/delete)发生时,数据库内核实时响应并执行预设sql,无需应用调用或定时任务。

触发器到底能帮你自动干啥事
触发器本质是“表级事件响应器”——你对某张表执行 INSERT、UPDATE 或 DELETE,它就自动跑一段 SQL。不是靠应用调用,也不是定时任务,而是数据库内核级的实时响应。
最常用的真实场景有三类:
- 数据联动更新:比如向
orders插入订单后,自动把products表里对应商品的stock减 1 - 审计留痕:每次改员工薪资,自动往
salary_audit表里写一条记录,含操作人(如果可获取)、旧值、新值、时间 - 强制校验与修正:插入新用户时,若
email为空,用username + '@example.com'填充;若salarySET NEW.salary = 0 或抛错回滚(用SIGNAL)
BEFORE 和 AFTER 的区别不是“先后”,而是“能否改数据”
BEFORE 触发器能读写 NEW 行(对 INSERT/UPDATE),甚至可以修改即将入库的值或中止操作;AFTER 只能读 NEW 或 OLD,不能改当前行——因为那行已经落盘了。
常见误用:
技术上面应用了三层结构,AJAX框架,URL重写等基础的开发。并用了动软的代码生成器及数据访问类,加进了一些自己用到的小功能,算是整理了一些自己的操作类。系统设计上面说不出用什么模式,大体设计是后台分两级分类,设置好一级之后,再设置二级并选择栏目类型,如内容,列表,上传文件,新窗口等。这样就可以生成无限多个二级分类,也就是网站栏目。对于扩展性来说,如果有新的需求可以直接加一个栏目类型并新加功能操作
- 想在
AFTER INSERT里设NEW.id = UUID()→ 报错,NEW在AFTER阶段只读 - 在
BEFORE UPDATE里没判断IF OLD.status != NEW.status THEN ...,导致每次 UPDATE 都记日志,哪怕 status 没变 - 用
AFTER DELETE去删关联表数据,但没加外键约束或事务包裹,一旦中间出错,主表已删、子表没删干净,数据不一致
别碰这三类高危操作,否则线上会抖
触发器看着轻量,但滥用会直接拖垮性能或引发死锁:
- 触发器里再操作本表(比如
AFTER INSERT ON users又去UPDATE users)→ 极易触发循环调用,MySQL 默认禁止,报错Can't update table 'users' in stored function/trigger - 跨库写操作(如
INSERT INTO log_db.audit_log ...)→ 若目标库网络延迟或不可用,整个原始 DML 会被阻塞甚至失败 - 调用存储过程或函数,而该过程里含复杂查询、临时表或锁表操作 → 单条
INSERT可能变成秒级延迟,批量导入时雪崩
调试难?先看这个检查清单
触发器不报错也不执行?大概率卡在这几个地方:
- 权限不足:
CREATE TRIGGER需要TRIGGER权限,非 root 用户常被忽略 - 分隔符没切:
DELIMITER //必须在CREATE TRIGGER前设置,否则遇到第一个;就终止解析,报语法错 - 触发器名重复:同一张表上已有同名触发器,新建会失败,但错误提示不明确(只说
Trigger already exists) - 没生效却以为生效:用
SELECT @@log_bin确认 binlog 是否开启——某些云 MySQL 实例默认关 binlog,AFTER触发器可能被跳过(尤其涉及复制链路时)
真正棘手的是隐式行为:比如在事务中触发多个触发器,其中一个失败会导致整个事务回滚,但业务代码可能只捕获了主 SQL 错误,没意识到是触发器抛的 SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'xxx'。









