会回滚,但不是“触发器自己回滚”,而是整个事务(含主 INSERT 和触发器内所有操作)一起回滚——前提是事务上下文有效、引擎支持原子性、且没被 autocommit 或 DDL 暗中破坏。

MySQL 触发器失败时事务回滚的硬条件
触发器报错能触发回滚,不是默认成立的,必须同时满足:
- 表引擎是
InnoDB(MyISAM不支持事务,回滚无效) - 连接处于事务模式:
SELECT @@autocommit返回0;若为1,单条INSERT执行完立刻提交,根本无“回滚”可言 - 没在事务中执行过
ALTER TABLE、TRUNCATE TABLE或对MyISAM表操作——这些会隐式提交,让前面的BEGIN失效 - 触发器错误是“可传播”的:比如
SIGNAL SQLSTATE '45000'、外键冲突、字段类型不匹配;而语法错误(如SELECT未接INTO)可能静默失败,需靠SHOW WARNINGS查
SQL Server 触发器里 RAISERROR 不等于回滚
RAISERROR 只是抛异常,不终止事务流。常见误操作是写完就以为完事了:
-
RAISERROR('金额超限', 16, 1)→ 客户端看到错误,但INSERT已落库 - 必须紧跟
ROLLBACK TRANSACTION,且放在IF分支末尾,不能只塞进TRY...CATCH的CATCH块却不执行回滚 - 更稳妥的做法是改用
THROW(SQL Server 2012+),但必须配合SET XACT_ABORT ON,否则某些错误仍可能部分提交 - 检查事务是否活跃:
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION,避免在无事务上下文时执行ROLLBACK报错
触发器里想“局部失败不中断主流程”?别试了
MySQL 不支持触发器内捕获异常后继续执行,SQL Server 也不允许在触发器里开启自治事务。所谓“日志写失败但主数据要插入”,本质违背触发器语义:
- MySQL 中连
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION都无法捕获SIGNAL或约束错误,只能捕获极少数运行时异常(如除零) - 强行绕过(比如用
INSERT ... ON DUPLICATE KEY UPDATE写日志)会导致主从不一致或死锁风险陡增 - 真正需要异步/降级能力的逻辑(如调用外部 API、重试、发消息),应该移出触发器,放到应用层或带事务控制的存储过程中
- 调试时别依赖
SELECT“打印”变量——会报ERROR 1415;改用向临时表INSERT INTO debug_log记录
最容易被忽略的是:触发器本身不记日志,SHOW WARNINGS 和错误日志(log_error)必须主动查,否则失败像没发生过一样。

















