事件调度器
约 778 字大约 3 分钟
布欧-Lewyon
2026-05-15
首页 › MySQL › 高级特性(在新窗口打开) › 事件调度器
事件调度器(Event Scheduler)是 MySQL 内置的定时任务工具,可以在指定时间或按固定间隔自动执行 SQL。
开启事件调度器
-- 查看事件调度器状态
SHOW VARIABLES LIKE 'event_scheduler';
-- 默认 OFF
-- 运行时开启(临时)
SET GLOBAL event_scheduler = ON;
-- 配置文件开启(永久)
-- [mysqld]
-- event_scheduler = ON创建事件
一次性事件
-- 在指定时间执行一次
CREATE EVENT one_time_cleanup
ON SCHEDULE AT '2026-06-01 02:00:00'
DO
DELETE FROM temp_log WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY);周期性事件
CREATE EVENT nightly_cleanup
ON SCHEDULE EVERY 1 DAY
STARTS '2026-01-01 02:00:00'
DO
DELETE FROM session_log WHERE expired_at < NOW();带条件的事件
CREATE EVENT hourly_stats
ON SCHEDULE EVERY 1 HOUR
STARTS '2026-01-01 00:00:00'
ENDS '2026-12-31 23:59:59'
DO
INSERT INTO access_stats (hour, count)
SELECT HOUR(NOW()), COUNT(*)
FROM access_log
WHERE accessed_at >= DATE_SUB(NOW(), INTERVAL 1 HOUR);事件选项
CREATE EVENT [IF NOT EXISTS] event_name
ON SCHEDULE
AT timestamp -- 一次执行
| EVERY interval -- 周期性执行
[STARTS timestamp] [ENDS timestamp]
DO
body_sql;
-- interval 支持:
-- EVERY 1 HOUR
-- EVERY 2 DAY
-- EVERY 1 MONTH
-- EVERY 1 YEAR
-- EVERY 10 MINUTE_SECOND # 每 10 分 0 秒事件主体支持多条语句
DELIMITER $$
CREATE EVENT complex_cleanup
ON SCHEDULE EVERY 1 DAY
STARTS '2026-01-01 03:00:00'
DO
BEGIN
DELETE FROM temp_data WHERE expired < NOW();
DELETE FROM old_audit WHERE created_at < DATE_SUB(NOW(), INTERVAL 90 DAY);
OPTIMIZE TABLE temp_data;
END$$
DELIMITER ;管理事件
-- 查看所有事件
SHOW EVENTS;
SHOW EVENTS FROM demo;
-- 查看事件定义
SHOW CREATE EVENT hourly_stats;
-- 修改事件
ALTER EVENT nightly_cleanup
ON SCHEDULE EVERY 2 DAY; -- 改为每 2 天
-- 启用/禁用事件
ALTER EVENT hourly_stats ENABLE;
ALTER EVENT hourly_stats DISABLE;
-- 删除事件
DROP EVENT IF EXISTS hourly_stats;适用场景
-- 1. 定期清理过期数据
CREATE EVENT clean_expired_sessions
ON SCHEDULE EVERY 1 DAY
DO
DELETE FROM user_session WHERE last_active < DATE_SUB(NOW(), INTERVAL 7 DAY);
-- 2. 定时生成汇总报表
CREATE EVENT generate_daily_report
ON SCHEDULE EVERY 1 DAY
STARTS '2026-01-01 01:00:00'
DO
INSERT INTO daily_sales_summary (report_date, total_amount, order_count)
SELECT CURDATE() - INTERVAL 1 DAY, SUM(amount), COUNT(*)
FROM orders
WHERE order_date >= CURDATE() - INTERVAL 1 DAY
AND order_date < CURDATE();
-- 3. 数据归档(将旧数据移到历史表)
CREATE EVENT archive_old_orders
ON SCHEDULE EVERY 1 MONTH
STARTS '2026-02-01 02:00:00'
DO
INSERT INTO orders_archive SELECT * FROM orders
WHERE order_date < DATE_SUB(NOW(), INTERVAL 6 MONTH);
DELETE FROM orders WHERE order_date < DATE_SUB(NOW(), INTERVAL 6 MONTH);事件调度器 vs 应用层定时任务
| 对比 | MySQL Event | 应用层定时任务(Cron / Celery / XXL-Job) |
|---|---|---|
| 依赖 | 无需额外组件 | 需要操作系统或框架支持 |
| 管理 | SQL 语句即可 | 需登录服务器或调度中心 |
| 复杂度 | 仅支持 SQL | 支持任意语言逻辑 |
| 可观测性 | SHOW EVENTS 查看 | 有日志、告警、重试机制 |
| 适合场景 | 纯数据库操作 | 需要调用外部系统(发邮件、推送通知等) |
小结
- 事件调度器在 MySQL 内部执行定时任务,需要将
event_scheduler设为 ON。 - 支持
AT(一次性)和EVERY(周期性)两种调度方式。 - 适用场景:清理过期数据、生成汇总报表、数据归档等纯数据库操作。
- 对于涉及外部系统的复杂定时任务,建议使用应用层的调度框架。
上一节:触发器 下一节:JSON 类型与函数
