MySQL通过内置EVENT实现定时任务,需启用event_scheduler并授EVENT权限,适用于简单定时SQL如更新过期订单,但不适用于PostgreSQL/SQLite且云数据库可能限制该功能。
MySQL 本身不支持像 cron 那样的外部调度,但内置了 EVENT 功能,本质是数据库级的定时触发器。它能按指定时间间隔自动执行 SQL,适合更新过期状态这类简单逻辑。前提是你的 MySQL 版本 ≥ 5.1 且 event_scheduler 系统变量已启用。
常见错误现象:执行 CREATE EVENT 报错 “Event scheduler is not enabled”,或者事件创建成功但没运行——基本都是因为 event_scheduler 默认是 OFF。
SHOW VARIABLES LIKE 'event_scheduler';,返回 ON 才有效SET GLOBAL event_scheduler = ON;
my.cnf 中添加:event_scheduler=ON,然后重启 MySQLEVENT 权限必须授予对应用户,否则建事件会报错 ERROR 1227 (42000)
假设有一张 orders 表,其中 status 字段为 'pending',created_at 是下单时间,要求每 5 分钟把超过 30 分钟未处理的订单设为 'expired'。
CREATE EVENT expire_pending_ordersON SCHEDULE EVERY 5 MINUTEDO UPDATE orders SET status = 'expired' WHERE status = 'pending' AND created_at < NOW() - INTERVAL 30 MINUTE;
关键点:
EVERY 5 MINUTE 是触发频率,不是“延迟执行”,它会严格按时间点轮询(如 10:00、10:05…)NOW() - INTERVAL 30 MINUTE 用的是服务器当前时间,不是事件定义时的时间,每次执行都动态计算status = 'pending',否则可能重复更新已过期记录status 和 created_at 上建联合索引:INDEX idx_status_created (status, created_at)
PostgreSQL 没有等价的 EVENT,得靠外部调度(如 pg_cron 扩展或系统 cron 调 psql);SQLite 更是完全没定时能力,只能由应用层轮询或外部触发。强行用 MySQL 的 EVENT 语法在其他数据库上会直接报错 syntax error near 'EVENT'。
如果你用的是云数据库(比如阿里云 RDS、AWS RDS),还要确认是否允许开启事件调度器——部分托管服务默认禁用或限制权限,得去控制台手动开启或提工单申请。
真正容易被忽略的是时间精度和事务边界:MySQL EVENT 在自己的事务中执行,不会自动加锁全表,但如果并发高、UPDATE 影响行数多,仍可能因锁等待导致下一轮执行延迟。别指望它做到毫秒级精准,也别把它当替代应用层调度的万能方案。