mysql事件调度器默认关闭,create event会静默失败;需通过select @@event_scheduler检查,用set global event_scheduler=on临时开启或在配置文件中添加event_scheduler=on永久启用。

MySQL 事件调度器没开启,CREATE EVENT 会静默失败
你执行了 CREATE EVENT 却查不到,也没报错?大概率是调度器根本没开。MySQL 默认关闭事件调度器,它不像触发器或存储过程那样随服务自动启用。
检查和开启方式很简单:
- 先确认状态:
SELECT @@event_scheduler;—— 返回OFF就得开 - 临时开启(重启失效):
SET GLOBAL event_scheduler = ON; - 永久生效:在
my.cnf或my.ini的[mysqld]段落加一行:event_scheduler = ON
注意:没有 SUPER 权限的用户执行 SET GLOBAL 会报错 ERROR 1227 (42501): Access denied;生产环境改配置文件后务必重启 mysqld,光 reload 不行。
CREATE EVENT 语法里 ON SCHEDULE 容易写错时间单位
写成 EVERY 1 DAY 没问题,但写成 EVERY 24 HOUR 或 EVERY 1440 MINUTE 也合法;真正容易出错的是用错时间粒度或漏掉单位。
常见错误现象:
-
EVERY 1—— 缺少单位,报错ERROR 1064 (42000) -
EVERY 1 SECOND—— 理论可行,但 MySQL 实际最小调度间隔是 1 秒,且高频率事件可能堆积,导致后续执行被跳过 -
AT '2024-01-01'—— 没有时分秒,默认为00:00:00,如果当前时间已过,事件立即失效(不会补跑)
建议:用 EVERY 配合 STARTS 明确起始时间,比如:ON SCHEDULE EVERY 1 HOUR STARTS '2024-05-20 02:00:00',避免歧义。
事件体里不能直接用未声明变量,INSERT INTO ... SELECT 最常用也最易翻车
事件体本质是 SQL 语句块,不支持像存储过程那样用 DECLARE 定义局部变量。想动态构造值,只能靠函数或子查询。
使用模板与程序分离的方式构建,依靠专门设计的数据库操作类实现数据库存取,具有专有错误处理模块,通过 Email 实时报告数据库错误,除具有满足购物需要的全部功能外,成新商城购物系统还对购物系统体系做了丰富的扩展,全新设计的搜索功能,自定义成新商城购物系统代码功能代码已经全面优化,杜绝SQL注入漏洞前台测试用户名:admin密码:admin888后台管理员名:admin密码:admin888
典型场景:每天凌晨清空日志表但保留最近 7 天数据。
错误写法(试图用变量):SET @cutoff = DATE_SUB(NOW(), INTERVAL 7 DAY); DELETE FROM logs WHERE created_at —— 在事件体里 <code>SET 语句必须用 BEGIN...END 包裹,且需定义为存储程序语法(即加上 DO 或改用 CREATE PROCEDURE + 调用)。
正确轻量做法:
- 直接写函数:
DELETE FROM logs WHERE created_at - 若逻辑复杂,拆到存储过程里,事件只负责调用:
CALL cleanup_logs(); - 注意权限:事件以定义者(DEFINER)权限运行,不是调用者。确保
DEFINER用户对涉及表有DELETE权限
事件停用、删除和排查,SHOW EVENTS 和 INFORMATION_SCHEMA.EVENTS 用哪个
SHOW EVENTS 看得快,但只显示当前数据库;跨库管理或写监控脚本时,必须查 INFORMATION_SCHEMA.EVENTS。
关键字段说明:
-
EVENT_SCHEMA:所属数据库名 -
STATUS:值为ENABLED/DISABLED/SLAVESIDE_DISABLED,停用事件别只删代码,要用ALTER EVENT e_name DISABLE; -
LAST_EXECUTED:最后一次执行时间,NULL表示还没跑过或已失效(比如AT时间已过) -
EVENT_DEFINITION:完整 SQL,但会被截断(默认 64 字符),长逻辑要进mysql.event表查原始内容(不推荐直改)
删之前务必确认:DROP EVENT IF EXISTS <code>e_name; —— 没加 IF EXISTS 且事件不存在,会报错中断后续脚本。
事件的时间精度依赖系统时钟和调度器唤醒机制,同一秒内多个事件不保证执行顺序;跨时区部署时,NOW() 返回的是服务器本地时间,不是 UTC,这点在分布式定时任务里很容易被忽略。









