mysql事件调度器未启用会导致create event静默失败或报错;须先执行show variables like 'event_scheduler'确认状态,若为off或disabled,需set global event_scheduler = on临时开启,或在my.cnf中配置event_scheduler = on并重启。

MySQL事件调度器没启用,CREATE EVENT 会静默失败
直接写 CREATE EVENT 却发现事件不执行?大概率是调度器根本没开。MySQL 默认关闭事件调度器,且不会报错提示——它只会把语句当成普通 DDL 忽略掉。
检查是否启用:
SHOW VARIABLES LIKE 'event_scheduler';返回
OFF 或 DISABLED 都不行。- 临时启用(重启失效):
SET GLOBAL event_scheduler = ON; - 永久启用:在
my.cnf或my.ini的[mysqld]段下加一行event_scheduler = ON,然后重启 MySQL - 注意权限:
EVENT权限必须授予当前用户,例如:GRANT EVENT ON *.* TO 'your_user'@'%';
创建定时统计事件时,DEFINER 和权限上下文容易出错
事件以 DEFINER 身份执行,不是当前登录用户。如果定义者账号不存在、密码过期、或没有目标库表的 SELECT/INSERT 权限,事件会静默跳过执行,日志里只显示“Event execution failed”但不说明原因。
- 显式指定可靠定义者:
CREATE DEFINER = 'stats_user'@'localhost' EVENT ...,并确保该账号存在且有完整权限 - 避免用
CURRENT_USER或未指定DEFINER——MySQL 可能自动填入已删除账号 - 测试权限:用定义者账号手动执行事件体内的 SQL,确认无报错
- 事件体内不要依赖用户变量或临时表(除非显式声明
SQL SECURITY DEFINER并确认上下文)
时间表达式写成 EVERY 1 DAY 不等于每天凌晨0点执行
EVERY 是相对事件**首次创建时间**开始计时的周期偏移,不是按日历对齐。比如下午3点创建 EVERY 1 DAY,后续执行永远在下午3点,而非你想要的“每日统计昨日数据”场景。
- 要固定时间点执行,用
AT+ON SCHEDULE EVERY组合:ON SCHEDULE EVERY 1 DAY STARTS '2024-06-01 00:00:00'
- 更稳妥的做法:事件体中用
CURDATE() - INTERVAL 1 DAY明确计算昨日日期,避免依赖调度时刻 - 注意时区:
event_scheduler使用 MySQL 服务器时区(SELECT @@time_zone;),若应用跨时区,务必统一设置default-time-zone - 避免用
EVERY 1 HOUR做日粒度统计——累积误差和重复执行风险高
事件执行失败不会重试,也无默认日志,排查靠手动查 mysql.event 和错误日志
事件失败后不会告警、不进慢日志、也不写 general log。唯一结构化记录在系统表 mysql.event 中,但只存定义,不存执行历史。
- 开启事件日志(5.7+):
SET GLOBAL log_error_verbosity = 3;并确认错误日志路径(SHOW VARIABLES LIKE 'log_error';),失败事件会在其中输出类似Event Scheduler: [db_name@user] Error code: 1146... - 检查最近执行状态:
SELECT * FROM information_schema.EVENTS WHERE EVENT_SCHEMA = 'your_db' \G
重点关注LAST_EXECUTED和STATUS - 关键逻辑加异常捕获:在事件体中用
BEGIN ... DECLARE EXIT HANDLER FOR SQLEXCEPTION记录失败到自建日志表 - 不要依赖事件做强一致性任务——它本质是 best-effort,重要统计建议改用外部调度器(如 cron + mysql client)
事件调度器适合低频、容忍短时延迟、非核心链路的统计补全。一旦涉及多表强一致更新、大事务或需幂等控制,就得跳出事件本身,从架构上重新设计触发时机和回滚机制。











