mysql中的触发器(Triggers)的基本概念与作用

11次阅读

触发器是mysql中与表绑定的事件驱动机制,在INSERT、UPDATE或delete时自动执行;它不可显式调用、不支持事务控制语句,BEFORE可修改NEW值,AFTER适合日志记录,性能开销需谨慎评估。

mysql中的触发器(Triggers)的基本概念与作用

触发器是什么:数据库层的自动响应机制

触发器是 MySQL 中一种特殊的存储程序,它在特定表上发生 INSERTUPDATEDELETE 操作时自动执行,无需应用层调用。它不是函数也不是存储过程,而是一段与表强绑定的、事件驱动的逻辑。

常见错误现象:执行 INSERT 后发现数据“莫名”被改了,或日志表没写入——大概率是触发器在后台生效但未被察觉。

  • 触发器必须关联到具体表,且一个表同一事件(如 BEFORE INSERT)只能有一个同类型触发器
  • 不能显式调用,也不能传参;它的输入来自当前操作的行(NEW / OLD
  • 不支持事务控制语句(如 START TRANSACTION),但会参与外层语句的事务

BEFORE 和 AFTER 触发器的关键区别

BEFORE 触发器在语句实际执行前运行,可修改 NEW 行值;AFTER 在语句成功提交后运行,适合记录日志或同步更新其他表。

典型误用:在 AFTER UPDATE 里试图修改本表数据,会报错 Can't update table 't' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.

  • BEFORE INSERT:可用于设置默认值、校验字段(如把空邮箱转为 'unknown@example.com'
  • BEFORE UPDATE:适合自动更新 updated_at 字段,或阻止非法状态变更(如 status'done' 改回 'pending'
  • AFTER DELETE:常用于归档删除记录到历史表,或清理关联缓存键

触发器中 NEW 和 OLD 的使用限制

NEW 代表新行数据(INSERTUPDATE 可用),OLD 代表旧行数据(UPDATEDELETE 可用)。它们是只读别名,不能赋值给变量再修改——必须直接赋值给 NEW.column_name

容易踩的坑:在 BEFORE INSERT 中写 SET @tmp = NEW.id;SET NEW.id = @tmp + 1; 是无效的;必须写成 SET NEW.id = NEW.id + 1;

  • INSERT:只有 NEWOLDNULL
  • DELETE:只有 OLDNEWNULL
  • UPDATENEWOLD 都存在,OLD 是更新前值,NEW 是待写入值

创建和查看触发器的实操要点

创建触发器需有 TRIGGER 权限,且不能跨库引用表(除非用 db_name.table_name 显式指定)。MySQL 8.0+ 支持多语句触发器,但必须用 BEGIN ... END 包裹,并临时修改分隔符。

DELIMITER $$ CREATE TRIGGER users_update_updated_at BEFORE UPDATE ON users FOR EACH ROW BEGIN   SET NEW.updated_at = NOW(); END$$ DELIMITER ;

查看已建触发器:

  • 查当前库所有触发器:SHOW TRIGGERS;
  • 查某张表的触发器:SHOW TRIGGERS LIKE 'users';
  • 查定义语句:select TRIGGER_NAME, ACTION_TIMING, EVENT_MANIPULATION, ACTION_STATEMENT FROM information_schema.TRIGGERS WHERE EVENT_OBJECT_TABLE = 'users';

性能影响容易被低估:每个触发器都会增加 DML 延迟,尤其是涉及复杂查询或跨表更新时。高并发写入场景下,应优先考虑应用层处理或异步方案。

text=ZqhQzanResources