mysql触发器中禁止使用commit/rollback,因其运行在父语句事务上下文中;事件调度器默认关闭,需手动启用;truncate table绕过所有触发器;event与trigger均不可跨会话引用临时表。

MySQL 触发器里不能用 COMMIT 或 ROLLBACK
触发器运行在父语句的事务上下文中,它本身不是独立事务。一旦你在 BEFORE 或 AFTER 触发器里写 COMMIT,MySQL 直接报错:ERROR 1305 (42000): FUNCTION does not exist(实际是语法拒绝,但错误提示常误导人)。
常见错误现象:想在插入后自动更新统计表并提交,结果整个 INSERT 失败;或者误以为加了 START TRANSACTION 就能“另起炉灶”,其实触发器内不允许任何显式事务控制语句。
- 触发器中只允许 DML(
INSERT/UPDATE/DELETE)、变量赋值、条件判断,不能调用存储过程以外的事务命令 - 如果真需要跨表一致性操作,把逻辑提到应用层,或改用存储过程封装整套动作
-
INSERT ... ON DUPLICATE KEY UPDATE配合触发器时尤其危险——冲突路径可能绕过触发器预期执行顺序
MySQL 事件调度器(Event Scheduler)默认是关的
写了 CREATE EVENT 却没反应?大概率是 event_scheduler 系统变量为 OFF。它不像触发器那样随表自动激活,必须手动打开。
使用场景包括定时归档旧数据、每小时刷新汇总视图、清理临时表等。但它不保证精确到秒级执行,且依赖 MySQL 实例持续运行。
ECTouch是上海商创网络科技有限公司推出的一套基于 PHP 和 MySQL 数据库构建的开源且易于使用的移动商城网店系统!应用于各种服务器平台的高效、快速和易于管理的网店解决方案,采用稳定的MVC框架开发,完美对接ecshop系统与模板堂众多模板,为中小企业提供最佳的移动电商解决方案。ECTouch程序源代码完全无加密。安装时只需将已集成的文件夹放进指定位置,通过浏览器访问一键安装,无需对已有
- 检查状态:
SHOW VARIABLES LIKE 'event_scheduler';,返回OFF就得开 - 临时开启:
SET GLOBAL event_scheduler = ON;(需 SUPER 权限) - 永久生效:在
my.cnf的[mysqld]段落加一行event_scheduler=ON - 事件定义里用
ON COMPLETION PRESERVE可避免执行完就自动删除,方便调试
触发器无法响应 TRUNCATE TABLE
TRUNCATE TABLE 不走 DML 流程,而是直接重建表结构,绕过所有触发器。哪怕你建了 AFTER DELETE 触发器,对 TRUNCATE 完全无效。
这在日志审计、软删除设计、计数器同步等场景容易踩坑——你以为删光了会触发清理逻辑,其实什么都没发生。
- 替代方案只有两种:改用
DELETE FROM table(注意带 WHERE 1=1 并确认有索引支撑性能) - 或在应用层强制拦截
TRUNCATE命令,统一转成带触发器的DELETE - 某些 ORM 自动生成
TRUNCATE(比如测试环境清库),要特别检查其行为是否被触发器覆盖
EVENT 和 TRIGGER 都不能跨数据库引用临时表
不管是事件里建的临时表,还是触发器里 SELECT 的临时表,只要不是当前会话创建的,就会报 ERROR 1146 (42S02): Table 'db.tmp' doesn't exist。因为临时表只在创建它的会话内可见,而事件在独立线程运行,触发器则依附于调用语句的会话——但都不是“你当前连着的那个”。
这个限制在做分库汇总、中间计算时特别隐蔽,比如想在事件里先算出一批 ID 再批量更新主表,结果临时表根本读不到。
- 避免用临时表传数据,改用普通表 + 唯一前缀(如
tmp_<code>CONNECTION_ID()_xxx) - 触发器中禁止
SELECT ... INTO TEMPORARY TABLE,哪怕只是中间步骤 - 事件中若需缓存中间结果,优先考虑内存表(
ENGINE=MEMORY)或带 TTL 的普通表









