跳转到主内容
极星编程网:以代码为星,赴技术山海!

mysql触发器是什么_mysql自动执行机制说明

MySQL触发器是表级事件驱动的自动执行机制,由内核在DML流程中硬编码钩子实现,需满足BEFORE/AFTER、绑定具体表、FOR EACH ROW三要素;仅支持行级触发,NEW/OLD变量依DML类型可用性不同;InnoDB中与主DML同事务,MyISAM无事务保障;禁止显式事务控制,且高并发下易成性能瓶颈。 MySQL触发器是表级事件驱动的自动执行机制——当对某张表执行
INSERT
、
UPDATE
或
DELETE
时,它会**在指定时机(BEFORE/AFTER)自动运行一段 SQL 逻辑**,无需应用层调用,也不依赖定时任务或外部脚本。 触发器怎么“自动执行”?关键看三要素 它的自动性不是魔法,而是由 MySQL 内核在 DML 执行流程中硬 编码 插入的钩子。只要满足以下三个条件,就必然触发:
BEFORE
或
AFTER
:决定是在语句修改数据前还是后介入(例如
BEFORE INSERT
可改
NEW
值,
AFTER DELETE
只能读
OLD
) 明确绑定一个表:
ON table_name
,不能跨表定义,也不能作用于视图或临时表
FOR EACH ROW
:MySQL **只支持行级触发器**,哪怕你写
INSERT INTO t VALUES (1),(2),(3)
,也会为每行调用一次触发器体 为什么 NEW 和 OLD 有时报错?变量访问规则必须记清 触发器里能用
NEW
和
OLD
是它区别于普通存储过程的核心能力,但它们不是随时可用的“全局变量”:
INSERT
触发器:只有
NEW
可用(代表待插入/已插入的行),
OLD
未定义,引用会报
Unknown column 'OLD.id' in 'field list'
UPDATE
触发器:
OLD
(更新前值)和
NEW
(更新后值)都可用;
BEFORE UPDATE
中可
SET NEW.col = ...
修改即将写入的值
DELETE
触发器:只有
OLD
可用(代表将被删的行),
NEW
不存在 常见误用:
AFTER INSERT
里写
UPDATE other_table SET x = OLD.val
—— 直接报错,因为
OLD
根本不存在。 MySQL(Linux) MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。 下载 触发器真能“保证一致性”?InnoDB 和 MyISAM 差别极大 很多人以为加个触发器就能稳稳同步数据,其实是否原子、是否回滚,完全取决于底层引擎: InnoDB 表上的触发器与主 DML 在**同一个事务内执行**:如果触发器里的
INSERT INTO log_table
失败,整个原始
INSERT
也会回滚 MyISAM 表不支持事务,触发器操作失败**不会导致原语句回滚**,极易造成数据不一致(比如库存扣减成功但日志没写成) 所有触发器都**禁止执行显式事务控制语句**(
COMMIT
、
ROLLBACK
、
START TRANSACTION
),否则直接报错
ERROR 1307 (HY000): Can't use COMMIT in a TRIGGER
DELIMITER // CREATE TRIGGER order_stock_check BEFORE INSERT ON `order_item` FOR EACH ROW BEGIN DECLARE stock_left INT DEFAULT 0; SELECT quantity INTO stock_left FROM product WHERE id = NEW.product_id; IF stock_left < NEW.quantity THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '库存不足'; END IF; END// DELIMITER ;
这个例子看似合理,但它会在批量插入时逐行检查,性能陡降;若
product
表被其他事务锁住,还会拖慢主订单插入。真正高并发场景下,靠触发器做强校验反而容易成为瓶颈——自动执行不等于安全执行,更不等于高效执行。

相关文章