event_scheduler默认关闭,需set global event_scheduler=on或配置文件设为on并重启;starts/ends须用明确datetime;多语句需begin...end包裹。

event_scheduler 默认是关闭的,必须手动开启
MySQL 5.1+ 虽然自带事件调度器,但默认 event_scheduler 变量值为 OFF,不开启就无法创建或执行任何事件。只执行 CREATE EVENT 会静默失败,不会报错,但 SHOW EVENTS 查不到,也看不到 NEXT_EXECUTED 时间。
临时开启(重启失效):SET GLOBAL event_scheduler = ON;
永久生效(推荐):在 my.cnf 或 my.ini 的 [mysqld] 段下添加:event_scheduler = ON,然后重启 MySQL。
验证是否生效:SHOW VARIABLES LIKE 'event_scheduler'; —— 必须返回 ON 才算真正启用。
容易踩的坑:
- 只在会话里执行
SET SESSION event_scheduler = ON无效,必须用GLOBAL; - 配置文件修改后忘记重启 MySQL,导致设置不生效;
- 某些云数据库(如阿里云 RDS)默认禁用该功能且不允许修改,需在控制台开启或联系支持。
CREATE EVENT 语法中 STARTS 和 ENDS 容易写错时间表达式
STARTS 和 ENDS 不接受模糊描述(比如 “每天凌晨”),必须是明确的 DATETIME 值或可计算出确定时间的表达式。常见错误是直接写 STARTS '00:00:00',这会被当成日期 0000-00-00 00:00:00,导致事件立即失效。
正确写法示例:
- 从明天零点开始:
STARTS CURRENT_DATE + INTERVAL 1 DAY; - 从今天 2 点开始,每小时一次:
ON SCHEDULE EVERY 1 HOUR STARTS TIMESTAMP(CURDATE(), '02:00:00'); - 运行一个月后自动停:
ENDS CURRENT_DATE + INTERVAL 1 MONTH; - 避免时区偏差:确保
@@global.time_zone是你期望的值(如'+08:00'),否则CURRENT_TIMESTAMP可能不是本地时间。
DO 子句里不能直接写多条语句,必须用 BEGIN...END 包裹
如果定时任务需要执行多个 SQL(比如先插入日志、再删数据、再更新统计),直接写 DO INSERT ...; DELETE ...; 会报语法错误。MySQL 要求多语句必须放在存储过程或 BEGIN...END 复合语句块中。
正确写法(注意分隔符切换):
DELIMITER $$ CREATE EVENT clean_logs ON SCHEDULE EVERY 1 DAY STARTS CURRENT_DATE + INTERVAL 1 DAY DO BEGIN INSERT INTO log_archive SELECT * FROM logs WHERE create_time <p>关键点:</p>
-
DELIMITER $$是为了防止客户端把中间的分号当成语句结束; -
BEGIN...END内部每条语句仍以分号结尾; - 事务行为默认不自动提交,若需原子性,应在
BEGIN...END中显式加START TRANSACTION和COMMIT; - 避免在
DO中调用未定义的存储过程,否则事件会静默跳过执行。
事件状态变更和清理常被忽略,导致任务“看似存在却不再运行”
事件创建后默认是 ENABLE,但一旦到达 ENDS 时间,状态会自动变为 DISABLED,而不是删除。此时 SHOW EVENTS 仍能看到它,但 NEXT_EXECUTED 为 NULL,也不会再触发。
日常维护建议:
- 查状态用:
SELECT EVENT_NAME, STATUS, LAST_EXECUTED, NEXT_EXECUTED FROM information_schema.EVENTS WHERE EVENT_SCHEMA = 'your_db';; - 临时停用:
ALTER EVENT your_event DISABLE;; - 确认不再需要后,务必执行:
DROP EVENT IF EXISTS your_event;,否则残留的DISABLED事件会堆积; - 权限注意:操作事件需要
EVENT权限,不是所有 DBA 账号默认拥有,建库时要显式授权。
最常被忽略的是时区和 ENDS 到期后的状态残留——看起来“还在”,其实早已停摆,排查时容易误判为调度器故障。











