前言
MySQL 5.1 引入 Event Scheduler (事件調度器),可在資料庫內部實現定時任務,替代部分作業系統 cron 工作,優勢在於:跨平台、備份遷移隨資料庫、事務一致性、權限體系統一。
啟用事件調度器
-- 查看狀態
SHOW VARIABLES LIKE 'event_scheduler';
SELECT @@event_scheduler;
-- OFF / ON / DISABLED (啟動參數 --event-scheduler=DISABLED 時)
-- 運行時開啟 (重啟失效)
SET GLOBAL event_scheduler = ON;
-- 永久生效:my.cnf [mysqld]
event_scheduler = ON
事件建立語法詳解
CREATE EVENT [IF NOT EXISTS] event_name
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE]
[COMMENT 'comment']
DO sql_statement;
Schedule 類型
| 類型 | 語法 | 範例 |
| 一次性執行 | AT timestamp [+ INTERVAL interval] | AT '2024-12-31 23:59:59'
AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR |
| 循環執行 | EVERY interval [STARTS timestamp] [ENDS timestamp] | EVERY 1 DAY STARTS '2024-01-01 00:00:00'
EVERY 5 MINUTE
EVERY 1 MONTH ENDS '2025-12-31' |
Interval 單位
YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE | WEEK | SECOND |
YEAR_MONTH | DAY_HOUR | DAY_MINUTE | DAY_SECOND |
HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND
實戰範例
1. 每日零點清理 30 天前日誌
CREATE EVENT ev_clean_old_logs
ON SCHEDULE EVERY 1 DAY STARTS '2024-01-01 00:00:00'
ON COMPLETION PRESERVE
ENABLE
COMMENT '清理 30 天前操作日誌'
DO
DELETE FROM sys_operation_log
WHERE create_time < DATE_SUB(CURDATE(), INTERVAL 30 DAY);
2. 每小時統計活躍用戶數
CREATE EVENT ev_hourly_active_users
ON SCHEDULE EVERY 1 HOUR
DO
INSERT INTO stat_hourly_active (stat_time, active_count)
SELECT
DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00'),
COUNT(DISTINCT user_id)
FROM user_access_log
WHERE access_time >= DATE_SUB(NOW(), INTERVAL 1 HOUR);
3. 一次性任務:下個月 1 號歸檔訂單
CREATE EVENT ev_archive_orders_once
ON SCHEDULE AT '2024-02-01 00:00:00'
ON COMPLETION NOT PRESERVE -- 執行後自動刪除事件
DO
CALL sp_archive_orders('2024-01');
4. 呼叫儲存過程 (複雜邏輯封裝)
CREATE EVENT ev_complex_job
ON SCHEDULE EVERY 1 DAY
DO
CALL sp_daily_settlement();
事件管理指令
| 操作 | 指令 |
| 查看所有事件 | SHOW EVENTS; 或 SELECT * FROM information_schema.EVENTS; |
| 查看特定事件 | SHOW CREATE EVENT ev_name; |
| 啟用/禁用事件 | ALTER EVENT ev_name ENABLE/DISABLE; |
| 修改事件 | ALTER EVENT ev_name ON SCHEDULE EVERY 2 DAY; |
| 刪除事件 | DROP EVENT [IF EXISTS] ev_name; |
權限要求
- 建立/修改/刪除事件:
EVENT 權限 (對應庫級)。
- 事件執行時以 定義者 (DEFINER) 權限運行,需確保定義者擁有 SQL 涉及物件的權限。
GRANT EVENT ON db.* TO 'user'@'host';
限制與注意事項
- 不支援秒級精度:最小粒度 1 秒,高頻任務勿用。
- 單執行緒串行執行:同一時間點多個事件排隊,長任務會阻塞後續事件。
- 不支援分散式協調:主從複制下事件預設在主庫執行,從庫不執行 (除非
event_scheduler=ON 且 replicate_events_marked_for_skip 相關參數配置)。
- 時區一致性:確保 Server 系統時區、
time_zone 變數、應用層時區一致。
- 備份/遷移:
mysqldump --events 導出事件定義,--skip-events 跳過。
- 監控:
SHOW PROCESSLIST 可見 User=event_scheduler 執行緒;information_schema.EVENTS 監控 LAST_EXECUTED、STATUS。
對比:Event vs Cron vs 應用層排程
| 維度 | MySQL Event | Linux Cron | 應用層 |
| 部署耦合度 | 隨資料庫遷移 | 依賴作業系統 | 隨應用代碼 |
| 事務一致性 | 原生支援 | 需自行處理 | 靈活控制 |
| 精度 | 秒級 | 分鐘級 | 毫秒級 |
| 高可用 | 隨主庫故障轉移 | 需 Keepalived | 分散式鎖/調度器 |
| 監控運維 | SQL 介面 | 系統日誌 | 應用監控 |
建議:資料庫維護類任務 (清理、統計、歸檔、分區管理) 用 Event;業務邏輯、外部 API 調用、高精度/分散式協調 用應用層排程 (Quartz, XXL-Job, Celery Beat)。